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 
10 #include "libbb.h"
11 
12 /* static const uint8_t ascii64[] ALIGN1 =
13  * "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
14  */
15 
i64c(int i)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 
crypt_make_salt(char * p,int cnt)30 int FAST_FUNC crypt_make_salt(char *p, int cnt /*, int x */)
31 {
32 	/* was: x += ... */
33 	int x = getpid() + monotonic_us();
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 
crypt_make_pw_salt(char salt[MAX_PW_SALT_LEN],const char * algo)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 
56 	/* Standard chpasswd uses uppercase algos ("MD5", not "md5").
57 	 * Need to be case-insensitive in the code below.
58 	 */
59 	if ((algo[0]|0x20) != 'd') { /* not des */
60 		len = 8/2; /* so far assuming md5 */
61 		*salt_ptr++ = '$';
62 		*salt_ptr++ = '1';
63 		*salt_ptr++ = '$';
64 #if !ENABLE_USE_BB_CRYPT || ENABLE_USE_BB_CRYPT_SHA
65 		if ((algo[0]|0x20) == 's') { /* sha */
66 			salt[1] = '5' + (strcasecmp(algo, "sha512") == 0);
67 			len = 16/2;
68 		}
69 #endif
70 	}
71 	crypt_make_salt(salt_ptr, len);
72 	return salt_ptr;
73 }
74 
75 #if ENABLE_USE_BB_CRYPT
76 
77 static char*
to64(char * s,unsigned v,int n)78 to64(char *s, unsigned v, int n)
79 {
80 	while (--n >= 0) {
81 		/* *s++ = ascii64[v & 0x3f]; */
82 		*s++ = i64c(v);
83 		v >>= 6;
84 	}
85 	return s;
86 }
87 
88 /*
89  * DES and MD5 crypt implementations are taken from uclibc.
90  * They were modified to not use static buffers.
91  */
92 
93 #include "pw_encrypt_des.c"
94 #include "pw_encrypt_md5.c"
95 #if ENABLE_USE_BB_CRYPT_SHA
96 #include "pw_encrypt_sha.c"
97 #endif
98 
99 /* Other advanced crypt ids (TODO?): */
100 /* $2$ or $2a$: Blowfish */
101 
102 static struct const_des_ctx *des_cctx;
103 static struct des_ctx *des_ctx;
104 
105 /* my_crypt returns malloc'ed data */
my_crypt(const char * key,const char * salt)106 static char *my_crypt(const char *key, const char *salt)
107 {
108 	/* MD5 or SHA? */
109 	if (salt[0] == '$' && salt[1] && salt[2] == '$') {
110 		if (salt[1] == '1')
111 			return md5_crypt(xzalloc(MD5_OUT_BUFSIZE), (unsigned char*)key, (unsigned char*)salt);
112 #if ENABLE_USE_BB_CRYPT_SHA
113 		if (salt[1] == '5' || salt[1] == '6')
114 			return sha_crypt((char*)key, (char*)salt);
115 #endif
116 	}
117 
118 	if (!des_cctx)
119 		des_cctx = const_des_init();
120 	des_ctx = des_init(des_ctx, des_cctx);
121 	return des_crypt(des_ctx, xzalloc(DES_OUT_BUFSIZE), (unsigned char*)key, (unsigned char*)salt);
122 }
123 
124 /* So far nobody wants to have it public */
my_crypt_cleanup(void)125 static void my_crypt_cleanup(void)
126 {
127 	free(des_cctx);
128 	free(des_ctx);
129 	des_cctx = NULL;
130 	des_ctx = NULL;
131 }
132 
pw_encrypt(const char * clear,const char * salt,int cleanup)133 char* FAST_FUNC pw_encrypt(const char *clear, const char *salt, int cleanup)
134 {
135 	char *encrypted;
136 
137 	encrypted = my_crypt(clear, salt);
138 
139 	if (cleanup)
140 		my_crypt_cleanup();
141 
142 	return encrypted;
143 }
144 
145 #else /* if !ENABLE_USE_BB_CRYPT */
146 
pw_encrypt(const char * clear,const char * salt,int cleanup)147 char* FAST_FUNC pw_encrypt(const char *clear, const char *salt, int cleanup)
148 {
149 	char *s;
150 
151 	s = crypt(clear, salt);
152 	/*
153 	 * glibc used to return "" on malformed salts (for example, ""),
154 	 * but since 2.17 it returns NULL.
155 	 */
156 	return xstrdup(s ? s : "");
157 }
158 
159 #endif
160