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 | * |
Denys Vlasenko | 0ef64bd | 2010-08-16 20:14:46 +0200 | [diff] [blame] | 7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
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 | |
Denys Vlasenko | 12a4327 | 2011-05-13 03:19:01 +0200 | [diff] [blame] | 30 | int FAST_FUNC crypt_make_salt(char *p, int cnt /*, int x */) |
Denis Vlasenko | d1a84a2 | 2008-12-07 01:16:34 +0000 | [diff] [blame] | 31 | { |
Denys Vlasenko | 12a4327 | 2011-05-13 03:19:01 +0200 | [diff] [blame] | 32 | /* was: x += ... */ |
| 33 | int x = getpid() + monotonic_us(); |
Denis Vlasenko | d1a84a2 | 2008-12-07 01:16:34 +0000 | [diff] [blame] | 34 | do { |
| 35 | /* x = (x*1664525 + 1013904223) % 2^32 generator is lame |
| 36 | * (low-order bit is not "random", etc...), |
| 37 | * but for our purposes it is good enough */ |
| 38 | x = x*1664525 + 1013904223; |
| 39 | /* BTW, Park and Miller's "minimal standard generator" is |
| 40 | * x = x*16807 % ((2^31)-1) |
| 41 | * It has no problem with visibly alternating lowest bit |
| 42 | * but is also weak in cryptographic sense + needs div, |
| 43 | * which needs more code (and slower) on many CPUs */ |
| 44 | *p++ = i64c(x >> 16); |
| 45 | *p++ = i64c(x >> 22); |
| 46 | } while (--cnt); |
| 47 | *p = '\0'; |
| 48 | return x; |
| 49 | } |
| 50 | |
Denys Vlasenko | 12a4327 | 2011-05-13 03:19:01 +0200 | [diff] [blame] | 51 | char* FAST_FUNC crypt_make_pw_salt(char salt[MAX_PW_SALT_LEN], const char *algo) |
| 52 | { |
| 53 | int len = 2/2; |
| 54 | char *salt_ptr = salt; |
| 55 | if (algo[0] != 'd') { /* not des */ |
| 56 | len = 8/2; /* so far assuming md5 */ |
| 57 | *salt_ptr++ = '$'; |
| 58 | *salt_ptr++ = '1'; |
| 59 | *salt_ptr++ = '$'; |
| 60 | #if !ENABLE_USE_BB_CRYPT || ENABLE_USE_BB_CRYPT_SHA |
| 61 | if (algo[0] == 's') { /* sha */ |
| 62 | salt[1] = '5' + (strcmp(algo, "sha512") == 0); |
| 63 | len = 16/2; |
| 64 | } |
| 65 | #endif |
| 66 | } |
| 67 | crypt_make_salt(salt_ptr, len); |
| 68 | return salt_ptr; |
| 69 | } |
| 70 | |
Denis Vlasenko | b4c5bf6 | 2008-06-15 18:35:34 +0000 | [diff] [blame] | 71 | #if ENABLE_USE_BB_CRYPT |
| 72 | |
Denis Vlasenko | d1a84a2 | 2008-12-07 01:16:34 +0000 | [diff] [blame] | 73 | static char* |
| 74 | to64(char *s, unsigned v, int n) |
| 75 | { |
| 76 | while (--n >= 0) { |
| 77 | /* *s++ = ascii64[v & 0x3f]; */ |
| 78 | *s++ = i64c(v); |
| 79 | v >>= 6; |
| 80 | } |
| 81 | return s; |
| 82 | } |
| 83 | |
Denis Vlasenko | 4ea83bf | 2008-06-12 16:55:59 +0000 | [diff] [blame] | 84 | /* |
| 85 | * DES and MD5 crypt implementations are taken from uclibc. |
| 86 | * They were modified to not use static buffers. |
Denis Vlasenko | 4ea83bf | 2008-06-12 16:55:59 +0000 | [diff] [blame] | 87 | */ |
Denis Vlasenko | 2211d52 | 2008-11-10 18:52:35 +0000 | [diff] [blame] | 88 | |
Denis Vlasenko | 4ea83bf | 2008-06-12 16:55:59 +0000 | [diff] [blame] | 89 | #include "pw_encrypt_des.c" |
| 90 | #include "pw_encrypt_md5.c" |
Denis Vlasenko | 2211d52 | 2008-11-10 18:52:35 +0000 | [diff] [blame] | 91 | #if ENABLE_USE_BB_CRYPT_SHA |
| 92 | #include "pw_encrypt_sha.c" |
| 93 | #endif |
Denis Vlasenko | 4ea83bf | 2008-06-12 16:55:59 +0000 | [diff] [blame] | 94 | |
Denis Vlasenko | 2211d52 | 2008-11-10 18:52:35 +0000 | [diff] [blame] | 95 | /* Other advanced crypt ids (TODO?): */ |
Denis Vlasenko | 30e1ab6 | 2008-11-07 13:36:46 +0000 | [diff] [blame] | 96 | /* $2$ or $2a$: Blowfish */ |
Denis Vlasenko | 4ea83bf | 2008-06-12 16:55:59 +0000 | [diff] [blame] | 97 | |
| 98 | static struct const_des_ctx *des_cctx; |
| 99 | static struct des_ctx *des_ctx; |
| 100 | |
| 101 | /* my_crypt returns malloc'ed data */ |
| 102 | static char *my_crypt(const char *key, const char *salt) |
Eric Andersen | 27f64e1 | 2002-06-23 04:24:25 +0000 | [diff] [blame] | 103 | { |
Denis Vlasenko | 2211d52 | 2008-11-10 18:52:35 +0000 | [diff] [blame] | 104 | /* MD5 or SHA? */ |
| 105 | if (salt[0] == '$' && salt[1] && salt[2] == '$') { |
| 106 | if (salt[1] == '1') |
| 107 | return md5_crypt(xzalloc(MD5_OUT_BUFSIZE), (unsigned char*)key, (unsigned char*)salt); |
| 108 | #if ENABLE_USE_BB_CRYPT_SHA |
| 109 | if (salt[1] == '5' || salt[1] == '6') |
| 110 | return sha_crypt((char*)key, (char*)salt); |
| 111 | #endif |
Denis Vlasenko | 4ea83bf | 2008-06-12 16:55:59 +0000 | [diff] [blame] | 112 | } |
| 113 | |
Denis Vlasenko | 2211d52 | 2008-11-10 18:52:35 +0000 | [diff] [blame] | 114 | if (!des_cctx) |
| 115 | des_cctx = const_des_init(); |
| 116 | des_ctx = des_init(des_ctx, des_cctx); |
| 117 | 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] | 118 | } |
| 119 | |
| 120 | /* So far nobody wants to have it public */ |
| 121 | static void my_crypt_cleanup(void) |
| 122 | { |
| 123 | free(des_cctx); |
| 124 | free(des_ctx); |
| 125 | des_cctx = NULL; |
| 126 | des_ctx = NULL; |
| 127 | } |
| 128 | |
Denis Vlasenko | defc1ea | 2008-06-27 02:52:20 +0000 | [diff] [blame] | 129 | 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] | 130 | { |
Denis Vlasenko | fdddab0 | 2008-06-12 16:56:52 +0000 | [diff] [blame] | 131 | char *encrypted; |
Eric Andersen | 27f64e1 | 2002-06-23 04:24:25 +0000 | [diff] [blame] | 132 | |
Denis Vlasenko | fdddab0 | 2008-06-12 16:56:52 +0000 | [diff] [blame] | 133 | encrypted = my_crypt(clear, salt); |
Denis Vlasenko | 4ea83bf | 2008-06-12 16:55:59 +0000 | [diff] [blame] | 134 | |
| 135 | if (cleanup) |
| 136 | my_crypt_cleanup(); |
| 137 | |
Denis Vlasenko | fdddab0 | 2008-06-12 16:56:52 +0000 | [diff] [blame] | 138 | return encrypted; |
Eric Andersen | 27f64e1 | 2002-06-23 04:24:25 +0000 | [diff] [blame] | 139 | } |
Denis Vlasenko | b4c5bf6 | 2008-06-15 18:35:34 +0000 | [diff] [blame] | 140 | |
| 141 | #else /* if !ENABLE_USE_BB_CRYPT */ |
| 142 | |
Denis Vlasenko | defc1ea | 2008-06-27 02:52:20 +0000 | [diff] [blame] | 143 | 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] | 144 | { |
Denys Vlasenko | 8ed9672 | 2014-02-09 14:38:03 +0100 | [diff] [blame] | 145 | char *s; |
| 146 | |
| 147 | s = crypt(clear, salt); |
| 148 | /* |
| 149 | * glibc used to return "" on malformed salts (for example, ""), |
| 150 | * but since 2.17 it returns NULL. |
| 151 | */ |
| 152 | return xstrdup(s ? s : ""); |
Denis Vlasenko | b4c5bf6 | 2008-06-15 18:35:34 +0000 | [diff] [blame] | 153 | } |
| 154 | |
| 155 | #endif |