Start 1.33.0 development cycle
[oweals/busybox.git] / libbb / pw_encrypt.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Utility routines.
4  *
5  * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
6  *
7  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8  */
9 #if !ENABLE_USE_BB_CRYPT
10 #include <crypt.h>
11 #endif
12 #include "libbb.h"
13
14 /* static const uint8_t ascii64[] ALIGN1 =
15  * "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
16  */
17
18 static int i64c(int i)
19 {
20         i &= 0x3f;
21         if (i == 0)
22                 return '.';
23         if (i == 1)
24                 return '/';
25         if (i < 12)
26                 return ('0' - 2 + i);
27         if (i < 38)
28                 return ('A' - 12 + i);
29         return ('a' - 38 + i);
30 }
31
32 int FAST_FUNC crypt_make_salt(char *p, int cnt /*, int x */)
33 {
34         /* was: x += ... */
35         unsigned x = getpid() + monotonic_us();
36         do {
37                 /* x = (x*1664525 + 1013904223) % 2^32 generator is lame
38                  * (low-order bit is not "random", etc...),
39                  * but for our purposes it is good enough */
40                 x = x*1664525 + 1013904223;
41                 /* BTW, Park and Miller's "minimal standard generator" is
42                  * x = x*16807 % ((2^31)-1)
43                  * It has no problem with visibly alternating lowest bit
44                  * but is also weak in cryptographic sense + needs div,
45                  * which needs more code (and slower) on many CPUs */
46                 *p++ = i64c(x >> 16);
47                 *p++ = i64c(x >> 22);
48         } while (--cnt);
49         *p = '\0';
50         return x;
51 }
52
53 char* FAST_FUNC crypt_make_pw_salt(char salt[MAX_PW_SALT_LEN], const char *algo)
54 {
55         int len = 2/2;
56         char *salt_ptr = salt;
57
58         /* Standard chpasswd uses uppercase algos ("MD5", not "md5").
59          * Need to be case-insensitive in the code below.
60          */
61         if ((algo[0]|0x20) != 'd') { /* not des */
62                 len = 8/2; /* so far assuming md5 */
63                 *salt_ptr++ = '$';
64                 *salt_ptr++ = '1';
65                 *salt_ptr++ = '$';
66 #if !ENABLE_USE_BB_CRYPT || ENABLE_USE_BB_CRYPT_SHA
67                 if ((algo[0]|0x20) == 's') { /* sha */
68                         salt[1] = '5' + (strcasecmp(algo, "sha512") == 0);
69                         len = 16/2;
70                 }
71 #endif
72         }
73         crypt_make_salt(salt_ptr, len);
74         return salt_ptr;
75 }
76
77 #if ENABLE_USE_BB_CRYPT
78
79 static char*
80 to64(char *s, unsigned v, int n)
81 {
82         while (--n >= 0) {
83                 /* *s++ = ascii64[v & 0x3f]; */
84                 *s++ = i64c(v);
85                 v >>= 6;
86         }
87         return s;
88 }
89
90 /*
91  * DES and MD5 crypt implementations are taken from uclibc.
92  * They were modified to not use static buffers.
93  */
94
95 #include "pw_encrypt_des.c"
96 #include "pw_encrypt_md5.c"
97 #if ENABLE_USE_BB_CRYPT_SHA
98 #include "pw_encrypt_sha.c"
99 #endif
100
101 /* Other advanced crypt ids (TODO?): */
102 /* $2$ or $2a$: Blowfish */
103
104 static struct const_des_ctx *des_cctx;
105 static struct des_ctx *des_ctx;
106
107 /* my_crypt returns malloc'ed data */
108 static char *my_crypt(const char *key, const char *salt)
109 {
110         /* MD5 or SHA? */
111         if (salt[0] == '$' && salt[1] && salt[2] == '$') {
112                 if (salt[1] == '1')
113                         return md5_crypt(xzalloc(MD5_OUT_BUFSIZE), (unsigned char*)key, (unsigned char*)salt);
114 #if ENABLE_USE_BB_CRYPT_SHA
115                 if (salt[1] == '5' || salt[1] == '6')
116                         return sha_crypt((char*)key, (char*)salt);
117 #endif
118         }
119
120         if (!des_cctx)
121                 des_cctx = const_des_init();
122         des_ctx = des_init(des_ctx, des_cctx);
123         return des_crypt(des_ctx, xzalloc(DES_OUT_BUFSIZE), (unsigned char*)key, (unsigned char*)salt);
124 }
125
126 /* So far nobody wants to have it public */
127 static void my_crypt_cleanup(void)
128 {
129         free(des_cctx);
130         free(des_ctx);
131         des_cctx = NULL;
132         des_ctx = NULL;
133 }
134
135 char* FAST_FUNC pw_encrypt(const char *clear, const char *salt, int cleanup)
136 {
137         char *encrypted;
138
139         encrypted = my_crypt(clear, salt);
140
141         if (cleanup)
142                 my_crypt_cleanup();
143
144         return encrypted;
145 }
146
147 #else /* if !ENABLE_USE_BB_CRYPT */
148
149 char* FAST_FUNC pw_encrypt(const char *clear, const char *salt, int cleanup)
150 {
151         char *s;
152
153         s = crypt(clear, salt);
154         /*
155          * glibc used to return "" on malformed salts (for example, ""),
156          * but since 2.17 it returns NULL.
157          */
158         return xstrdup(s ? s : "");
159 }
160
161 #endif