Eric Andersen | 27f64e1 | 2002-06-23 04:24:25 +0000 | [diff] [blame] | 1 | /* vi: set sw=4 ts=4: */ |
| 2 | /* |
Denis Vlasenko | d1a84a2 | 2008-12-07 01:16:34 +0000 | [diff] [blame] | 3 | * Utility routines. |
Eric Andersen | 27f64e1 | 2002-06-23 04:24:25 +0000 | [diff] [blame] | 4 | * |
Eric Andersen | c7bda1c | 2004-03-15 08:29:22 +0000 | [diff] [blame] | 5 | * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org> |
Eric Andersen | 27f64e1 | 2002-06-23 04:24:25 +0000 | [diff] [blame] | 6 | * |
"Robert P. J. Day" | 5d8843e | 2006-07-10 11:41:19 +0000 | [diff] [blame] | 7 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. |
Eric Andersen | 27f64e1 | 2002-06-23 04:24:25 +0000 | [diff] [blame] | 8 | */ |
| 9 | |
Rob Landley | ea224be | 2006-06-18 20:20:07 +0000 | [diff] [blame] | 10 | #include "libbb.h" |
Eric Andersen | 27f64e1 | 2002-06-23 04:24:25 +0000 | [diff] [blame] | 11 | |
Denis Vlasenko | d1a84a2 | 2008-12-07 01:16:34 +0000 | [diff] [blame] | 12 | /* static const uint8_t ascii64[] = |
| 13 | * "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; |
| 14 | */ |
| 15 | |
| 16 | static int i64c(int i) |
| 17 | { |
| 18 | i &= 0x3f; |
| 19 | if (i == 0) |
| 20 | return '.'; |
| 21 | if (i == 1) |
| 22 | return '/'; |
| 23 | if (i < 12) |
| 24 | return ('0' - 2 + i); |
| 25 | if (i < 38) |
| 26 | return ('A' - 12 + i); |
| 27 | return ('a' - 38 + i); |
| 28 | } |
| 29 | |
| 30 | int FAST_FUNC crypt_make_salt(char *p, int cnt, int x) |
| 31 | { |
| 32 | x += getpid() + time(NULL); |
| 33 | do { |
| 34 | /* x = (x*1664525 + 1013904223) % 2^32 generator is lame |
| 35 | * (low-order bit is not "random", etc...), |
| 36 | * but for our purposes it is good enough */ |
| 37 | x = x*1664525 + 1013904223; |
| 38 | /* BTW, Park and Miller's "minimal standard generator" is |
| 39 | * x = x*16807 % ((2^31)-1) |
| 40 | * It has no problem with visibly alternating lowest bit |
| 41 | * but is also weak in cryptographic sense + needs div, |
| 42 | * which needs more code (and slower) on many CPUs */ |
| 43 | *p++ = i64c(x >> 16); |
| 44 | *p++ = i64c(x >> 22); |
| 45 | } while (--cnt); |
| 46 | *p = '\0'; |
| 47 | return x; |
| 48 | } |
| 49 | |
Denis Vlasenko | b4c5bf6 | 2008-06-15 18:35:34 +0000 | [diff] [blame] | 50 | #if ENABLE_USE_BB_CRYPT |
| 51 | |
Denis Vlasenko | d1a84a2 | 2008-12-07 01:16:34 +0000 | [diff] [blame] | 52 | static char* |
| 53 | to64(char *s, unsigned v, int n) |
| 54 | { |
| 55 | while (--n >= 0) { |
| 56 | /* *s++ = ascii64[v & 0x3f]; */ |
| 57 | *s++ = i64c(v); |
| 58 | v >>= 6; |
| 59 | } |
| 60 | return s; |
| 61 | } |
| 62 | |
Denis Vlasenko | 4ea83bf | 2008-06-12 16:55:59 +0000 | [diff] [blame] | 63 | /* |
| 64 | * DES and MD5 crypt implementations are taken from uclibc. |
| 65 | * They were modified to not use static buffers. |
Denis Vlasenko | 4ea83bf | 2008-06-12 16:55:59 +0000 | [diff] [blame] | 66 | */ |
Denis Vlasenko | 2211d52 | 2008-11-10 18:52:35 +0000 | [diff] [blame] | 67 | |
Denis Vlasenko | 4ea83bf | 2008-06-12 16:55:59 +0000 | [diff] [blame] | 68 | #include "pw_encrypt_des.c" |
| 69 | #include "pw_encrypt_md5.c" |
Denis Vlasenko | 2211d52 | 2008-11-10 18:52:35 +0000 | [diff] [blame] | 70 | #if ENABLE_USE_BB_CRYPT_SHA |
| 71 | #include "pw_encrypt_sha.c" |
| 72 | #endif |
Denis Vlasenko | 4ea83bf | 2008-06-12 16:55:59 +0000 | [diff] [blame] | 73 | |
Denis Vlasenko | 2211d52 | 2008-11-10 18:52:35 +0000 | [diff] [blame] | 74 | /* Other advanced crypt ids (TODO?): */ |
Denis Vlasenko | 30e1ab6 | 2008-11-07 13:36:46 +0000 | [diff] [blame] | 75 | /* $2$ or $2a$: Blowfish */ |
Denis Vlasenko | 4ea83bf | 2008-06-12 16:55:59 +0000 | [diff] [blame] | 76 | |
| 77 | static struct const_des_ctx *des_cctx; |
| 78 | static struct des_ctx *des_ctx; |
| 79 | |
| 80 | /* my_crypt returns malloc'ed data */ |
| 81 | static char *my_crypt(const char *key, const char *salt) |
Eric Andersen | 27f64e1 | 2002-06-23 04:24:25 +0000 | [diff] [blame] | 82 | { |
Denis Vlasenko | 2211d52 | 2008-11-10 18:52:35 +0000 | [diff] [blame] | 83 | /* MD5 or SHA? */ |
| 84 | if (salt[0] == '$' && salt[1] && salt[2] == '$') { |
| 85 | if (salt[1] == '1') |
| 86 | return md5_crypt(xzalloc(MD5_OUT_BUFSIZE), (unsigned char*)key, (unsigned char*)salt); |
| 87 | #if ENABLE_USE_BB_CRYPT_SHA |
| 88 | if (salt[1] == '5' || salt[1] == '6') |
| 89 | return sha_crypt((char*)key, (char*)salt); |
| 90 | #endif |
Denis Vlasenko | 4ea83bf | 2008-06-12 16:55:59 +0000 | [diff] [blame] | 91 | } |
| 92 | |
Denis Vlasenko | 2211d52 | 2008-11-10 18:52:35 +0000 | [diff] [blame] | 93 | if (!des_cctx) |
| 94 | des_cctx = const_des_init(); |
| 95 | des_ctx = des_init(des_ctx, des_cctx); |
| 96 | return des_crypt(des_ctx, xzalloc(DES_OUT_BUFSIZE), (unsigned char*)key, (unsigned char*)salt); |
Denis Vlasenko | 4ea83bf | 2008-06-12 16:55:59 +0000 | [diff] [blame] | 97 | } |
| 98 | |
| 99 | /* So far nobody wants to have it public */ |
| 100 | static void my_crypt_cleanup(void) |
| 101 | { |
| 102 | free(des_cctx); |
| 103 | free(des_ctx); |
| 104 | des_cctx = NULL; |
| 105 | des_ctx = NULL; |
| 106 | } |
| 107 | |
Denis Vlasenko | defc1ea | 2008-06-27 02:52:20 +0000 | [diff] [blame] | 108 | char* FAST_FUNC pw_encrypt(const char *clear, const char *salt, int cleanup) |
Denis Vlasenko | 4ea83bf | 2008-06-12 16:55:59 +0000 | [diff] [blame] | 109 | { |
Denis Vlasenko | fdddab0 | 2008-06-12 16:56:52 +0000 | [diff] [blame] | 110 | char *encrypted; |
Eric Andersen | 27f64e1 | 2002-06-23 04:24:25 +0000 | [diff] [blame] | 111 | |
Denis Vlasenko | fdddab0 | 2008-06-12 16:56:52 +0000 | [diff] [blame] | 112 | encrypted = my_crypt(clear, salt); |
Denis Vlasenko | 4ea83bf | 2008-06-12 16:55:59 +0000 | [diff] [blame] | 113 | |
| 114 | if (cleanup) |
| 115 | my_crypt_cleanup(); |
| 116 | |
Denis Vlasenko | fdddab0 | 2008-06-12 16:56:52 +0000 | [diff] [blame] | 117 | return encrypted; |
Eric Andersen | 27f64e1 | 2002-06-23 04:24:25 +0000 | [diff] [blame] | 118 | } |
Denis Vlasenko | b4c5bf6 | 2008-06-15 18:35:34 +0000 | [diff] [blame] | 119 | |
| 120 | #else /* if !ENABLE_USE_BB_CRYPT */ |
| 121 | |
Denis Vlasenko | defc1ea | 2008-06-27 02:52:20 +0000 | [diff] [blame] | 122 | char* FAST_FUNC pw_encrypt(const char *clear, const char *salt, int cleanup) |
Denis Vlasenko | b4c5bf6 | 2008-06-15 18:35:34 +0000 | [diff] [blame] | 123 | { |
Denis Vlasenko | b4c5bf6 | 2008-06-15 18:35:34 +0000 | [diff] [blame] | 124 | return xstrdup(crypt(clear, salt)); |
| 125 | } |
| 126 | |
| 127 | #endif |