1 /*-
2 * Copyright 2013 Alexander Peslyak
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted.
7 *
8 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
9 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
10 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
11 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
12 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
14 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
15 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
16 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
17 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
18 * SUCH DAMAGE.
19 */
20
21 #include <stdint.h>
22 #include <string.h>
23
24 #include "crypto_pwhash_scryptsalsa208sha256.h"
25 #include "crypto_scrypt.h"
26 #include "private/common.h"
27 #include "runtime.h"
28 #include "utils.h"
29
30 static const char *const itoa64 =
31 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
32
33 static uint8_t *
encode64_uint32(uint8_t * dst,size_t dstlen,uint32_t src,uint32_t srcbits)34 encode64_uint32(uint8_t *dst, size_t dstlen, uint32_t src, uint32_t srcbits)
35 {
36 uint32_t bit;
37
38 for (bit = 0; bit < srcbits; bit += 6) {
39 if (dstlen < 1) {
40 return NULL; /* LCOV_EXCL_LINE */
41 }
42 *dst++ = itoa64[src & 0x3f];
43 dstlen--;
44 src >>= 6;
45 }
46 return dst;
47 }
48
49 static uint8_t *
encode64(uint8_t * dst,size_t dstlen,const uint8_t * src,size_t srclen)50 encode64(uint8_t *dst, size_t dstlen, const uint8_t *src, size_t srclen)
51 {
52 size_t i;
53
54 for (i = 0; i < srclen;) {
55 uint8_t *dnext;
56 uint32_t value = 0, bits = 0;
57
58 do {
59 value |= (uint32_t) src[i++] << bits;
60 bits += 8;
61 } while (bits < 24 && i < srclen);
62
63 dnext = encode64_uint32(dst, dstlen, value, bits);
64 if (!dnext) {
65 return NULL; /* LCOV_EXCL_LINE */
66 }
67 dstlen -= dnext - dst;
68 dst = dnext;
69 }
70 return dst;
71 }
72
73 static int
decode64_one(uint32_t * dst,uint8_t src)74 decode64_one(uint32_t *dst, uint8_t src)
75 {
76 const char *ptr = strchr(itoa64, src);
77
78 if (ptr) {
79 *dst = (uint32_t)(ptr - itoa64);
80 return 0;
81 }
82 *dst = 0;
83
84 return -1;
85 }
86
87 static const uint8_t *
decode64_uint32(uint32_t * dst,uint32_t dstbits,const uint8_t * src)88 decode64_uint32(uint32_t *dst, uint32_t dstbits, const uint8_t *src)
89 {
90 uint32_t bit;
91 uint32_t value;
92
93 value = 0;
94 for (bit = 0; bit < dstbits; bit += 6) {
95 uint32_t one;
96 if (decode64_one(&one, *src)) {
97 *dst = 0;
98 return NULL;
99 }
100 src++;
101 value |= one << bit;
102 }
103 *dst = value;
104
105 return src;
106 }
107
108 const uint8_t *
escrypt_parse_setting(const uint8_t * setting,uint32_t * N_log2_p,uint32_t * r_p,uint32_t * p_p)109 escrypt_parse_setting(const uint8_t *setting,
110 uint32_t *N_log2_p, uint32_t *r_p, uint32_t *p_p)
111 {
112 const uint8_t *src;
113
114 if (setting[0] != '$' || setting[1] != '7' || setting[2] != '$') {
115 return NULL;
116 }
117 src = setting + 3;
118
119 if (decode64_one(N_log2_p, *src)) {
120 return NULL;
121 }
122 src++;
123
124 src = decode64_uint32(r_p, 30, src);
125 if (!src) {
126 return NULL;
127 }
128
129 src = decode64_uint32(p_p, 30, src);
130 if (!src) {
131 return NULL;
132 }
133 return src;
134 }
135
136 uint8_t *
escrypt_r(escrypt_local_t * local,const uint8_t * passwd,size_t passwdlen,const uint8_t * setting,uint8_t * buf,size_t buflen)137 escrypt_r(escrypt_local_t *local, const uint8_t *passwd, size_t passwdlen,
138 const uint8_t *setting, uint8_t *buf, size_t buflen)
139 {
140 uint8_t hash[crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES];
141 escrypt_kdf_t escrypt_kdf;
142 const uint8_t *src;
143 const uint8_t *salt;
144 uint8_t *dst;
145 size_t prefixlen;
146 size_t saltlen;
147 size_t need;
148 uint64_t N;
149 uint32_t N_log2;
150 uint32_t r;
151 uint32_t p;
152
153 src = escrypt_parse_setting(setting, &N_log2, &r, &p);
154 if (!src) {
155 return NULL;
156 }
157 N = (uint64_t) 1 << N_log2;
158 prefixlen = src - setting;
159
160 salt = src;
161 src = (uint8_t *) strrchr((char *) salt, '$');
162 if (src) {
163 saltlen = src - salt;
164 } else {
165 saltlen = strlen((char *) salt);
166 }
167 need = prefixlen + saltlen + 1 +
168 crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES_ENCODED + 1;
169 if (need > buflen || need < saltlen) {
170 return NULL;
171 }
172 #ifdef HAVE_EMMINTRIN_H
173 escrypt_kdf =
174 sodium_runtime_has_sse2() ? escrypt_kdf_sse : escrypt_kdf_nosse;
175 #else
176 escrypt_kdf = escrypt_kdf_nosse;
177 #endif
178 if (escrypt_kdf(local, passwd, passwdlen, salt, saltlen, N, r, p, hash,
179 sizeof(hash))) {
180 return NULL;
181 }
182 dst = buf;
183 memcpy(dst, setting, prefixlen + saltlen);
184 dst += prefixlen + saltlen;
185 *dst++ = '$';
186
187 dst = encode64(dst, buflen - (dst - buf), hash, sizeof(hash));
188 sodium_memzero(hash, sizeof hash);
189 if (!dst || dst >= buf + buflen) {
190 return NULL; /* Can't happen LCOV_EXCL_LINE */
191 }
192 *dst = 0; /* NUL termination */
193
194 return buf;
195 }
196
197 uint8_t *
escrypt_gensalt_r(uint32_t N_log2,uint32_t r,uint32_t p,const uint8_t * src,size_t srclen,uint8_t * buf,size_t buflen)198 escrypt_gensalt_r(uint32_t N_log2, uint32_t r, uint32_t p, const uint8_t *src,
199 size_t srclen, uint8_t *buf, size_t buflen)
200 {
201 uint8_t *dst;
202 size_t prefixlen =
203 (sizeof "$7$" - 1U) + (1U /* N_log2 */) + (5U /* r */) + (5U /* p */);
204 size_t saltlen = BYTES2CHARS(srclen);
205 size_t need;
206
207 need = prefixlen + saltlen + 1;
208 if (need > buflen || need < saltlen || saltlen < srclen) {
209 return NULL; /* LCOV_EXCL_LINE */
210 }
211 if (N_log2 > 63 || ((uint64_t) r * (uint64_t) p >= (1U << 30))) {
212 return NULL; /* LCOV_EXCL_LINE */
213 }
214 dst = buf;
215 *dst++ = '$';
216 *dst++ = '7';
217 *dst++ = '$';
218
219 *dst++ = itoa64[N_log2];
220
221 dst = encode64_uint32(dst, buflen - (dst - buf), r, 30);
222 if (!dst) {
223 return NULL; /* Can't happen LCOV_EXCL_LINE */
224 }
225 dst = encode64_uint32(dst, buflen - (dst - buf), p, 30);
226 if (!dst) {
227 return NULL; /* Can't happen LCOV_EXCL_LINE */
228 }
229 dst = encode64(dst, buflen - (dst - buf), src, srclen);
230 if (!dst || dst >= buf + buflen) {
231 return NULL; /* Can't happen LCOV_EXCL_LINE */
232 }
233 *dst = 0; /* NUL termination */
234
235 return buf;
236 }
237
238 int
crypto_pwhash_scryptsalsa208sha256_ll(const uint8_t * passwd,size_t passwdlen,const uint8_t * salt,size_t saltlen,uint64_t N,uint32_t r,uint32_t p,uint8_t * buf,size_t buflen)239 crypto_pwhash_scryptsalsa208sha256_ll(const uint8_t *passwd, size_t passwdlen,
240 const uint8_t *salt, size_t saltlen,
241 uint64_t N, uint32_t r, uint32_t p,
242 uint8_t *buf, size_t buflen)
243 {
244 escrypt_kdf_t escrypt_kdf;
245 escrypt_local_t local;
246 int retval;
247
248 if (escrypt_init_local(&local)) {
249 return -1; /* LCOV_EXCL_LINE */
250 }
251 #if defined(HAVE_EMMINTRIN_H)
252 escrypt_kdf =
253 sodium_runtime_has_sse2() ? escrypt_kdf_sse : escrypt_kdf_nosse;
254 #else
255 escrypt_kdf = escrypt_kdf_nosse;
256 #endif
257 retval = escrypt_kdf(&local, passwd, passwdlen, salt, saltlen, N, r, p, buf,
258 buflen);
259 if (escrypt_free_local(&local)) {
260 return -1; /* LCOV_EXCL_LINE */
261 }
262 return retval;
263 }
264