Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(223)

Side by Side Diff: src/lib/scryptenc/scryptenc.c

Issue 2847081: Initial code. (Closed) Base URL: ssh://git@chromiumos-git/libscrypt.git
Patch Set: Use scrypt distro and patch with changes instead. Created 10 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/lib/scryptenc/scryptenc.h ('k') | src/lib/scryptenc/scryptenc_cpuperf.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*-
2 * Copyright 2009 Colin Percival
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * This file was originally written by Colin Percival as part of the Tarsnap
27 * online backup system.
28 */
29 #include "scrypt_platform.h"
30
31 #include <errno.h>
32 #include <fcntl.h>
33 #include <stdint.h>
34 #include <stdio.h>
35 #include <string.h>
36 #include <unistd.h>
37
38 #include <openssl/aes.h>
39
40 #include "crypto_aesctr.h"
41 #include "crypto_scrypt.h"
42 #include "memlimit.h"
43 #include "scryptenc_cpuperf.h"
44 #include "sha256.h"
45 #include "sysendian.h"
46
47 #include "scryptenc.h"
48
49 #define ENCBLOCK 65536
50
51 static int pickparams(size_t, double, double,
52 int *, uint32_t *, uint32_t *);
53 static int checkparams(size_t, double, double, int, uint32_t, uint32_t);
54 static int getsalt(uint8_t[32]);
55
56 static int
57 pickparams(size_t maxmem, double maxmemfrac, double maxtime,
58 int * logN, uint32_t * r, uint32_t * p)
59 {
60 size_t memlimit;
61 double opps;
62 double opslimit;
63 double maxN, maxrp;
64 int rc;
65
66 /* Figure out how much memory to use. */
67 if (memtouse(maxmem, maxmemfrac, &memlimit))
68 return (1);
69
70 /* Figure out how fast the CPU is. */
71 if ((rc = scryptenc_cpuperf(&opps)) != 0)
72 return (rc);
73 opslimit = opps * maxtime;
74
75 /* Allow a minimum of 2^15 salsa20/8 cores. */
76 if (opslimit < 32768)
77 opslimit = 32768;
78
79 /* Fix r = 8 for now. */
80 *r = 8;
81
82 /*
83 * The memory limit requires that 128Nr <= memlimit, while the CPU
84 * limit requires that 4Nrp <= opslimit. If opslimit < memlimit/32,
85 * opslimit imposes the stronger limit on N.
86 */
87 #ifdef DEBUG
88 fprintf(stderr, "Requiring 128Nr <= %zu, 4Nrp <= %f\n",
89 memlimit, opslimit);
90 #endif
91 if (opslimit < memlimit/32) {
92 /* Set p = 1 and choose N based on the CPU limit. */
93 *p = 1;
94 maxN = opslimit / (*r * 4);
95 for (*logN = 1; *logN < 63; *logN += 1) {
96 if ((uint64_t)(1) << *logN > maxN / 2)
97 break;
98 }
99 } else {
100 /* Set N based on the memory limit. */
101 maxN = memlimit / (*r * 128);
102 for (*logN = 1; *logN < 63; *logN += 1) {
103 if ((uint64_t)(1) << *logN > maxN / 2)
104 break;
105 }
106
107 /* Choose p based on the CPU limit. */
108 maxrp = (opslimit / 4) / ((uint64_t)(1) << *logN);
109 if (maxrp > 0x3fffffff)
110 maxrp = 0x3fffffff;
111 *p = (uint32_t)(maxrp) / *r;
112 }
113
114 #ifdef DEBUG
115 fprintf(stderr, "N = %zu r = %d p = %d\n",
116 (size_t)(1) << *logN, (int)(*r), (int)(*p));
117 #endif
118
119 /* Success! */
120 return (0);
121 }
122
123 static int
124 checkparams(size_t maxmem, double maxmemfrac, double maxtime,
125 int logN, uint32_t r, uint32_t p)
126 {
127 size_t memlimit;
128 double opps;
129 double opslimit;
130 uint64_t N;
131 int rc;
132
133 /* Figure out the maximum amount of memory we can use. */
134 if (memtouse(maxmem, maxmemfrac, &memlimit))
135 return (1);
136
137 /* Figure out how fast the CPU is. */
138 if ((rc = scryptenc_cpuperf(&opps)) != 0)
139 return (rc);
140 opslimit = opps * maxtime;
141
142 /* Sanity-check values. */
143 if ((logN < 1) || (logN > 63))
144 return (7);
145 if ((uint64_t)(r) * (uint64_t)(p) >= 0x40000000)
146 return (7);
147
148 /* Check limits. */
149 N = (uint64_t)(1) << logN;
150 if ((memlimit / N) / r < 128)
151 return (9);
152 if ((opslimit / N) / (r * p) < 4)
153 return (10);
154
155 /* Success! */
156 return (0);
157 }
158
159 static int
160 getsalt(uint8_t salt[32])
161 {
162 int fd;
163 ssize_t lenread;
164 uint8_t * buf = salt;
165 size_t buflen = 32;
166
167 /* Open /dev/urandom. */
168 if ((fd = open("/dev/urandom", O_RDONLY)) == -1)
169 goto err0;
170
171 /* Read bytes until we have filled the buffer. */
172 while (buflen > 0) {
173 if ((lenread = read(fd, buf, buflen)) == -1)
174 goto err1;
175
176 /* The random device should never EOF. */
177 if (lenread == 0)
178 goto err1;
179
180 /* We're partly done. */
181 buf += lenread;
182 buflen -= lenread;
183 }
184
185 /* Close the device. */
186 while (close(fd) == -1) {
187 if (errno != EINTR)
188 goto err0;
189 }
190
191 /* Success! */
192 return (0);
193
194 err1:
195 close(fd);
196 err0:
197 /* Failure! */
198 return (4);
199 }
200
201 static int
202 scryptenc_setup(uint8_t header[96], uint8_t dk[64],
203 const uint8_t * passwd, size_t passwdlen,
204 size_t maxmem, double maxmemfrac, double maxtime)
205 {
206 uint8_t salt[32];
207 uint8_t hbuf[32];
208 int logN;
209 uint64_t N;
210 uint32_t r;
211 uint32_t p;
212 SHA256_CTX ctx;
213 uint8_t * key_hmac = &dk[32];
214 HMAC_SHA256_CTX hctx;
215 int rc;
216
217 /* Pick values for N, r, p. */
218 if ((rc = pickparams(maxmem, maxmemfrac, maxtime,
219 &logN, &r, &p)) != 0)
220 return (rc);
221 N = (uint64_t)(1) << logN;
222
223 /* Get some salt. */
224 if ((rc = getsalt(salt)) != 0)
225 return (rc);
226
227 /* Generate the derived keys. */
228 if (crypto_scrypt(passwd, passwdlen, salt, 32, N, r, p, dk, 64))
229 return (3);
230
231 /* Construct the file header. */
232 memcpy(header, "scrypt", 6);
233 header[6] = 0;
234 header[7] = logN;
235 be32enc(&header[8], r);
236 be32enc(&header[12], p);
237 memcpy(&header[16], salt, 32);
238
239 /* Add header checksum. */
240 SHA256_Init(&ctx);
241 SHA256_Update(&ctx, header, 48);
242 SHA256_Final(hbuf, &ctx);
243 memcpy(&header[48], hbuf, 16);
244
245 /* Add header signature (used for verifying password). */
246 HMAC_SHA256_Init(&hctx, key_hmac, 32);
247 HMAC_SHA256_Update(&hctx, header, 64);
248 HMAC_SHA256_Final(hbuf, &hctx);
249 memcpy(&header[64], hbuf, 32);
250
251 /* Success! */
252 return (0);
253 }
254
255 static int
256 scryptdec_setup(const uint8_t header[96], uint8_t dk[64],
257 const uint8_t * passwd, size_t passwdlen,
258 size_t maxmem, double maxmemfrac, double maxtime)
259 {
260 uint8_t salt[32];
261 uint8_t hbuf[32];
262 int logN;
263 uint32_t r;
264 uint32_t p;
265 uint64_t N;
266 SHA256_CTX ctx;
267 uint8_t * key_hmac = &dk[32];
268 HMAC_SHA256_CTX hctx;
269 int rc;
270
271 /* Parse N, r, p, salt. */
272 logN = header[7];
273 r = be32dec(&header[8]);
274 p = be32dec(&header[12]);
275 memcpy(salt, &header[16], 32);
276
277 /* Verify header checksum. */
278 SHA256_Init(&ctx);
279 SHA256_Update(&ctx, header, 48);
280 SHA256_Final(hbuf, &ctx);
281 if (memcmp(&header[48], hbuf, 16))
282 return (7);
283
284 /*
285 * Check whether the provided parameters are valid and whether the
286 * key derivation function can be computed within the allowed memory
287 * and CPU time.
288 */
289 if ((rc = checkparams(maxmem, maxmemfrac, maxtime, logN, r, p)) != 0)
290 return (rc);
291
292 /* Compute the derived keys. */
293 N = (uint64_t)(1) << logN;
294 if (crypto_scrypt(passwd, passwdlen, salt, 32, N, r, p, dk, 64))
295 return (3);
296
297 /* Check header signature (i.e., verify password). */
298 HMAC_SHA256_Init(&hctx, key_hmac, 32);
299 HMAC_SHA256_Update(&hctx, header, 64);
300 HMAC_SHA256_Final(hbuf, &hctx);
301 if (memcmp(hbuf, &header[64], 32))
302 return (11);
303
304 /* Success! */
305 return (0);
306 }
307
308 /**
309 * scryptenc_buf(inbuf, inbuflen, outbuf, passwd, passwdlen,
310 * maxmem, maxmemfrac, maxtime):
311 * Encrypt inbuflen bytes from inbuf, writing the resulting inbuflen + 128
312 * bytes to outbuf.
313 */
314 int
315 scryptenc_buf(const uint8_t * inbuf, size_t inbuflen, uint8_t * outbuf,
316 const uint8_t * passwd, size_t passwdlen,
317 size_t maxmem, double maxmemfrac, double maxtime)
318 {
319 uint8_t dk[64];
320 uint8_t hbuf[32];
321 uint8_t header[96];
322 uint8_t * key_enc = dk;
323 uint8_t * key_hmac = &dk[32];
324 int rc;
325 HMAC_SHA256_CTX hctx;
326 AES_KEY key_enc_exp;
327 struct crypto_aesctr * AES;
328
329 /* Generate the header and derived key. */
330 if ((rc = scryptenc_setup(header, dk, passwd, passwdlen,
331 maxmem, maxmemfrac, maxtime)) != 0)
332 return (rc);
333
334 /* Copy header into output buffer. */
335 memcpy(outbuf, header, 96);
336
337 /* Encrypt data. */
338 if (AES_set_encrypt_key(key_enc, 256, &key_enc_exp))
339 return (5);
340 if ((AES = crypto_aesctr_init(&key_enc_exp, 0)) == NULL)
341 return (6);
342 crypto_aesctr_stream(AES, inbuf, &outbuf[96], inbuflen);
343 crypto_aesctr_free(AES);
344
345 /* Add signature. */
346 HMAC_SHA256_Init(&hctx, key_hmac, 32);
347 HMAC_SHA256_Update(&hctx, outbuf, 96 + inbuflen);
348 HMAC_SHA256_Final(hbuf, &hctx);
349 memcpy(&outbuf[96 + inbuflen], hbuf, 32);
350
351 /* Zero sensitive data. */
352 memset(dk, 0, 64);
353 memset(&key_enc_exp, 0, sizeof(AES_KEY));
354
355 /* Success! */
356 return (0);
357 }
358
359 /**
360 * scryptdec_buf(inbuf, inbuflen, outbuf, outlen, passwd, passwdlen,
361 * maxmem, maxmemfrac, maxtime):
362 * Decrypt inbuflen bytes fro inbuf, writing the result into outbuf and the
363 * decrypted data length to outlen. The allocated length of outbuf must
364 * be at least inbuflen.
365 */
366 int
367 scryptdec_buf(const uint8_t * inbuf, size_t inbuflen, uint8_t * outbuf,
368 size_t * outlen, const uint8_t * passwd, size_t passwdlen,
369 size_t maxmem, double maxmemfrac, double maxtime)
370 {
371 uint8_t hbuf[32];
372 uint8_t dk[64];
373 uint8_t * key_enc = dk;
374 uint8_t * key_hmac = &dk[32];
375 int rc;
376 HMAC_SHA256_CTX hctx;
377 AES_KEY key_enc_exp;
378 struct crypto_aesctr * AES;
379
380 /*
381 * All versions of the scrypt format will start with "scrypt" and
382 * have at least 7 bytes of header.
383 */
384 if ((inbuflen < 7) || (memcmp(inbuf, "scrypt", 6) != 0))
385 return (7);
386
387 /* Check the format. */
388 if (inbuf[6] != 0)
389 return (8);
390
391 /* We must have at least 128 bytes. */
392 if (inbuflen < 128)
393 return (7);
394
395 /* Parse the header and generate derived keys. */
396 if ((rc = scryptdec_setup(inbuf, dk, passwd, passwdlen,
397 maxmem, maxmemfrac, maxtime)) != 0)
398 return (rc);
399
400 /* Decrypt data. */
401 if (AES_set_encrypt_key(key_enc, 256, &key_enc_exp))
402 return (5);
403 if ((AES = crypto_aesctr_init(&key_enc_exp, 0)) == NULL)
404 return (6);
405 crypto_aesctr_stream(AES, &inbuf[96], outbuf, inbuflen - 128);
406 crypto_aesctr_free(AES);
407 *outlen = inbuflen - 128;
408
409 /* Verify signature. */
410 HMAC_SHA256_Init(&hctx, key_hmac, 32);
411 HMAC_SHA256_Update(&hctx, inbuf, inbuflen - 32);
412 HMAC_SHA256_Final(hbuf, &hctx);
413 if (memcmp(hbuf, &inbuf[inbuflen - 32], 32))
414 return (7);
415
416 /* Zero sensitive data. */
417 memset(dk, 0, 64);
418 memset(&key_enc_exp, 0, sizeof(AES_KEY));
419
420 /* Success! */
421 return (0);
422 }
423
424 /**
425 * scryptenc_file(infile, outfile, passwd, passwdlen,
426 * maxmem, maxmemfrac, maxtime):
427 * Read a stream from infile and encrypt it, writing the resulting stream to
428 * outfile.
429 */
430 int
431 scryptenc_file(FILE * infile, FILE * outfile,
432 const uint8_t * passwd, size_t passwdlen,
433 size_t maxmem, double maxmemfrac, double maxtime)
434 {
435 uint8_t buf[ENCBLOCK];
436 uint8_t dk[64];
437 uint8_t hbuf[32];
438 uint8_t header[96];
439 uint8_t * key_enc = dk;
440 uint8_t * key_hmac = &dk[32];
441 size_t readlen;
442 HMAC_SHA256_CTX hctx;
443 AES_KEY key_enc_exp;
444 struct crypto_aesctr * AES;
445 int rc;
446
447 /* Generate the header and derived key. */
448 if ((rc = scryptenc_setup(header, dk, passwd, passwdlen,
449 maxmem, maxmemfrac, maxtime)) != 0)
450 return (rc);
451
452 /* Hash and write the header. */
453 HMAC_SHA256_Init(&hctx, key_hmac, 32);
454 HMAC_SHA256_Update(&hctx, header, 96);
455 if (fwrite(header, 96, 1, outfile) != 1)
456 return (12);
457
458 /*
459 * Read blocks of data, encrypt them, and write them out; hash the
460 * data as it is produced.
461 */
462 if (AES_set_encrypt_key(key_enc, 256, &key_enc_exp))
463 return (5);
464 if ((AES = crypto_aesctr_init(&key_enc_exp, 0)) == NULL)
465 return (6);
466 do {
467 if ((readlen = fread(buf, 1, ENCBLOCK, infile)) == 0)
468 break;
469 crypto_aesctr_stream(AES, buf, buf, readlen);
470 HMAC_SHA256_Update(&hctx, buf, readlen);
471 if (fwrite(buf, 1, readlen, outfile) < readlen)
472 return (12);
473 } while (1);
474 crypto_aesctr_free(AES);
475
476 /* Did we exit the loop due to a read error? */
477 if (ferror(infile))
478 return (13);
479
480 /* Compute the final HMAC and output it. */
481 HMAC_SHA256_Final(hbuf, &hctx);
482 if (fwrite(hbuf, 32, 1, outfile) != 1)
483 return (12);
484
485 /* Zero sensitive data. */
486 memset(dk, 0, 64);
487 memset(&key_enc_exp, 0, sizeof(AES_KEY));
488
489 /* Success! */
490 return (0);
491 }
492
493 /**
494 * scryptdec_file(infile, outfile, passwd, passwdlen,
495 * maxmem, maxmemfrac, maxtime):
496 * Read a stream from infile and decrypt it, writing the resulting stream to
497 * outfile.
498 */
499 int
500 scryptdec_file(FILE * infile, FILE * outfile,
501 const uint8_t * passwd, size_t passwdlen,
502 size_t maxmem, double maxmemfrac, double maxtime)
503 {
504 uint8_t buf[ENCBLOCK + 32];
505 uint8_t header[96];
506 uint8_t hbuf[32];
507 uint8_t dk[64];
508 uint8_t * key_enc = dk;
509 uint8_t * key_hmac = &dk[32];
510 size_t buflen = 0;
511 size_t readlen;
512 HMAC_SHA256_CTX hctx;
513 AES_KEY key_enc_exp;
514 struct crypto_aesctr * AES;
515 int rc;
516
517 /*
518 * Read the first 7 bytes of the file; all future version of scrypt
519 * are guaranteed to have at least 7 bytes of header.
520 */
521 if (fread(header, 7, 1, infile) < 1) {
522 if (ferror(infile))
523 return (13);
524 else
525 return (7);
526 }
527
528 /* Do we have the right magic? */
529 if (memcmp(header, "scrypt", 6))
530 return (7);
531 if (header[6] != 0)
532 return (8);
533
534 /*
535 * Read another 89 bytes of the file; version 0 of the srypt file
536 * format has a 96-byte header.
537 */
538 if (fread(&header[7], 89, 1, infile) < 1) {
539 if (ferror(infile))
540 return (13);
541 else
542 return (7);
543 }
544
545 /* Parse the header and generate derived keys. */
546 if ((rc = scryptdec_setup(header, dk, passwd, passwdlen,
547 maxmem, maxmemfrac, maxtime)) != 0)
548 return (rc);
549
550 /* Start hashing with the header. */
551 HMAC_SHA256_Init(&hctx, key_hmac, 32);
552 HMAC_SHA256_Update(&hctx, header, 96);
553
554 /*
555 * We don't know how long the encrypted data block is (we can't know,
556 * since data can be streamed into 'scrypt enc') so we need to read
557 * data and decrypt all of it except the final 32 bytes, then check
558 * if that final 32 bytes is the correct signature.
559 */
560 if (AES_set_encrypt_key(key_enc, 256, &key_enc_exp))
561 return (5);
562 if ((AES = crypto_aesctr_init(&key_enc_exp, 0)) == NULL)
563 return (6);
564 do {
565 /* Read data until we have more than 32 bytes of it. */
566 if ((readlen = fread(&buf[buflen], 1,
567 ENCBLOCK + 32 - buflen, infile)) == 0)
568 break;
569 buflen += readlen;
570 if (buflen <= 32)
571 continue;
572
573 /*
574 * Decrypt, hash, and output everything except the last 32
575 * bytes out of what we have in our buffer.
576 */
577 HMAC_SHA256_Update(&hctx, buf, buflen - 32);
578 crypto_aesctr_stream(AES, buf, buf, buflen - 32);
579 if (fwrite(buf, 1, buflen - 32, outfile) < buflen - 32)
580 return (12);
581
582 /* Move the last 32 bytes to the start of the buffer. */
583 memmove(buf, &buf[buflen - 32], 32);
584 buflen = 32;
585 } while (1);
586 crypto_aesctr_free(AES);
587
588 /* Did we exit the loop due to a read error? */
589 if (ferror(infile))
590 return (13);
591
592 /* Did we read enough data that we *might* have a valid signature? */
593 if (buflen < 32)
594 return (7);
595
596 /* Verify signature. */
597 HMAC_SHA256_Final(hbuf, &hctx);
598 if (memcmp(hbuf, buf, 32))
599 return (7);
600
601 /* Zero sensitive data. */
602 memset(dk, 0, 64);
603 memset(&key_enc_exp, 0, sizeof(AES_KEY));
604
605 return (0);
606 }
OLDNEW
« no previous file with comments | « src/lib/scryptenc/scryptenc.h ('k') | src/lib/scryptenc/scryptenc_cpuperf.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698