123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926 |
- /*-
- * Copyright 2009 Colin Percival
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * This file was originally written by Colin Percival as part of the Tarsnap
- * online backup system.
- */
- #include <assert.h>
- #include <inttypes.h>
- #include <stdint.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "crypto_aes.h"
- #include "crypto_aesctr.h"
- #include "crypto_entropy.h"
- #include "crypto_verify_bytes.h"
- #include "humansize.h"
- #include "insecure_memzero.h"
- #include "sha256.h"
- #include "sysendian.h"
- #include "warnp.h"
- #include "crypto_scrypt.h"
- #include "memlimit.h"
- #include "scryptenc_cpuperf.h"
- #include "scryptenc.h"
- #define ENCBLOCK 65536
- static int pickparams(size_t, double, double,
- int *, uint32_t *, uint32_t *, int);
- static int checkparams(size_t, double, double, int, uint32_t, uint32_t, int,
- int);
- #ifdef POSIXFAIL_ABSTRACT_DECLARATOR
- static int scryptdec_file_load_header(FILE * infile, uint8_t header[static 96]);
- #else
- static int scryptdec_file_load_header(FILE *, uint8_t[static 96]);
- #endif
- struct scryptdec_file_cookie {
- FILE * infile; /* This is not owned by this cookie. */
- uint8_t header[96];
- uint8_t dk[64];
- };
- static void
- display_params(int logN, uint32_t r, uint32_t p, size_t memlimit,
- double opps, double maxtime)
- {
- uint64_t N = (uint64_t)(1) << logN;
- uint64_t mem_minimum = 128 * r * N;
- double expected_seconds = opps > 0 ? (double)(4 * N * r * p) / opps : 0;
- char * human_memlimit = humansize(memlimit);
- char * human_mem_minimum = humansize(mem_minimum);
- /* Parameters */
- fprintf(stderr, "Parameters used: N = %" PRIu64 "; r = %" PRIu32
- "; p = %" PRIu32 ";\n", N, r, p);
- /* Memory */
- fprintf(stderr, " Decrypting this file requires at least"
- " %s of memory", human_mem_minimum);
- if (memlimit > 0)
- fprintf(stderr, " (%s available)", human_memlimit);
- /* CPU time */
- if (opps > 0)
- fprintf(stderr, ",\n and will take approximately %.1f "
- "seconds (limit: %.1f seconds)", expected_seconds, maxtime);
- fprintf(stderr, ".\n");
- /* Clean up */
- free(human_memlimit);
- free(human_mem_minimum);
- }
- static int
- pickparams(size_t maxmem, double maxmemfrac, double maxtime,
- int * logN, uint32_t * r, uint32_t * p, int verbose)
- {
- size_t memlimit;
- double opps;
- double opslimit;
- double maxN, maxrp;
- uint64_t checkN;
- int rc;
- /* Figure out how much memory to use. */
- if (memtouse(maxmem, maxmemfrac, &memlimit))
- return (SCRYPT_ELIMIT);
- /* Figure out how fast the CPU is. */
- if ((rc = scryptenc_cpuperf(&opps)) != SCRYPT_OK)
- return (rc);
- opslimit = opps * maxtime;
- /* Allow a minimum of 2^15 salsa20/8 cores. */
- if (opslimit < 32768)
- opslimit = 32768;
- /* Fix r = 8 for now. */
- *r = 8;
- /*
- * The memory limit requires that 128Nr <= memlimit, while the CPU
- * limit requires that 4Nrp <= opslimit. If opslimit < memlimit/32,
- * opslimit imposes the stronger limit on N.
- */
- #ifdef DEBUG
- fprintf(stderr, "Requiring 128Nr <= %zu, 4Nrp <= %f\n",
- memlimit, opslimit);
- #endif
- if (opslimit < (double)memlimit / 32) {
- /* Set p = 1 and choose N based on the CPU limit. */
- *p = 1;
- maxN = opslimit / (*r * 4);
- for (*logN = 1; *logN < 63; *logN += 1) {
- checkN = (uint64_t)(1) << *logN;
- /*
- * Find the largest power of two <= maxN, which is
- * also the least power of two > maxN/2.
- */
- if ((double)checkN > maxN / 2)
- break;
- }
- } else {
- /* Set N based on the memory limit. */
- maxN = (double)(memlimit / (*r * 128));
- for (*logN = 1; *logN < 63; *logN += 1) {
- checkN = (uint64_t)(1) << *logN;
- if ((double)checkN > maxN / 2)
- break;
- }
- /* Choose p based on the CPU limit. */
- checkN = (uint64_t)(1) << *logN;
- maxrp = (opslimit / 4) / (double)checkN;
- if (maxrp > 0x3fffffff)
- maxrp = 0x3fffffff;
- *p = (uint32_t)(maxrp) / *r;
- }
- if (verbose)
- display_params(*logN, *r, *p, memlimit, opps, maxtime);
- /* Success! */
- return (SCRYPT_OK);
- }
- static int
- checkparams(size_t maxmem, double maxmemfrac, double maxtime,
- int logN, uint32_t r, uint32_t p, int verbose, int force)
- {
- size_t memlimit;
- double opps;
- double opslimit;
- uint64_t N;
- int rc;
- /* Sanity-check values. */
- if ((logN < 1) || (logN > 63))
- return (SCRYPT_EINVAL);
- if ((uint64_t)(r) * (uint64_t)(p) >= 0x40000000)
- return (SCRYPT_EINVAL);
- if ((r == 0) || (p == 0))
- return (SCRYPT_EINVAL);
- /* Are we forcing decryption, regardless of resource limits? */
- if (!force) {
- /* Figure out the maximum amount of memory we can use. */
- if (memtouse(maxmem, maxmemfrac, &memlimit))
- return (SCRYPT_ELIMIT);
- /* Figure out how fast the CPU is. */
- if ((rc = scryptenc_cpuperf(&opps)) != SCRYPT_OK)
- return (rc);
- opslimit = opps * maxtime;
- if (verbose)
- display_params(logN, r, p, memlimit, opps, maxtime);
- /* Check limits. */
- N = (uint64_t)(1) << logN;
- if (((memlimit / N) / r < 128) &&
- (((opslimit / (double)N) / r) / p < 4))
- return (SCRYPT_EBIGSLOW);
- if ((memlimit / N) / r < 128)
- return (SCRYPT_ETOOBIG);
- if (((opslimit / (double)N) / r) / p < 4)
- return (SCRYPT_ETOOSLOW);
- } else {
- /* We have no limit. */
- memlimit = 0;
- opps = 0;
- if (verbose)
- display_params(logN, r, p, memlimit, opps, maxtime);
- }
- /* Success! */
- return (SCRYPT_OK);
- }
- /*
- * NOTE: The caller is responsible for sanitizing ${dk}, including if this
- * function fails.
- */
- static int
- scryptenc_setup(uint8_t header[96], uint8_t dk[64],
- const uint8_t * passwd, size_t passwdlen,
- struct scryptenc_params * P, int verbose, int force)
- {
- uint8_t salt[32];
- uint8_t hbuf[32];
- uint64_t N;
- SHA256_CTX ctx;
- uint8_t * key_hmac = &dk[32];
- HMAC_SHA256_CTX hctx;
- int rc;
- /* Determine parameters. */
- if (P->logN != 0) {
- /* Check logN, r, p. */
- if ((rc = checkparams(P->maxmem, P->maxmemfrac, P->maxtime,
- P->logN, P->r, P->p, verbose, force)) != 0) {
- /* Warn about resource limit, but suppress the error. */
- if ((rc == SCRYPT_ETOOBIG) || (rc == SCRYPT_EBIGSLOW))
- warn0("Warning: Explicit parameters"
- " might exceed memory limit");
- if ((rc == SCRYPT_ETOOSLOW) || (rc == SCRYPT_EBIGSLOW))
- warn0("Warning: Explicit parameters"
- " might exceed time limit");
- if ((rc == SCRYPT_ETOOBIG) || (rc == SCRYPT_ETOOSLOW) ||
- (rc == SCRYPT_EBIGSLOW))
- rc = 0;
- /* Provide a more meaningful error message. */
- if (rc == SCRYPT_EINVAL)
- rc = SCRYPT_EPARAM;
- /* Bail if we haven't suppressed the error. */
- if (rc != 0)
- return (rc);
- }
- } else {
- /* Pick values for N, r, p. */
- if ((rc = pickparams(P->maxmem, P->maxmemfrac, P->maxtime,
- &P->logN, &P->r, &P->p, verbose)) != 0)
- return (rc);
- }
- /* Sanity check. */
- assert((P->logN > 0) && (P->logN < 64));
- /* Set N. */
- N = (uint64_t)(1) << P->logN;
- /* Get some salt. */
- if (crypto_entropy_read(salt, 32))
- return (SCRYPT_ESALT);
- /* Generate the derived keys. */
- if (crypto_scrypt(passwd, passwdlen, salt, 32, N, P->r, P->p, dk, 64))
- return (SCRYPT_EKEY);
- /* Construct the file header. */
- memcpy(header, "scrypt", 6);
- header[6] = 0;
- header[7] = P->logN & 0xff;
- be32enc(&header[8], P->r);
- be32enc(&header[12], P->p);
- memcpy(&header[16], salt, 32);
- /* Add header checksum. */
- SHA256_Init(&ctx);
- SHA256_Update(&ctx, header, 48);
- SHA256_Final(hbuf, &ctx);
- memcpy(&header[48], hbuf, 16);
- /* Add header signature (used for verifying password). */
- HMAC_SHA256_Init(&hctx, key_hmac, 32);
- HMAC_SHA256_Update(&hctx, header, 64);
- HMAC_SHA256_Final(hbuf, &hctx);
- memcpy(&header[64], hbuf, 32);
- /* Success! */
- return (SCRYPT_OK);
- }
- /**
- * scryptdec_file_printparams(infile):
- * Print the encryption parameters (N, r, p) used for the encrypted ${infile}.
- */
- int
- scryptdec_file_printparams(FILE * infile)
- {
- uint8_t header[96];
- int logN;
- uint32_t r;
- uint32_t p;
- int rc;
- /* Load the header. */
- if ((rc = scryptdec_file_load_header(infile, header)) != 0)
- goto err0;
- /* Parse N, r, p. */
- logN = header[7];
- r = be32dec(&header[8]);
- p = be32dec(&header[12]);
- /* Print parameters. */
- display_params(logN, r, p, 0, 0, 0);
- /* Success! */
- return (SCRYPT_OK);
- err0:
- /* Failure! */
- return (rc);
- }
- /*
- * NOTE: The caller is responsible for sanitizing ${dk}, including if this
- * function fails.
- */
- static int
- scryptdec_setup(const uint8_t header[96], uint8_t dk[64],
- const uint8_t * passwd, size_t passwdlen,
- struct scryptenc_params * P, int verbose,
- int force)
- {
- uint8_t salt[32];
- uint8_t hbuf[32];
- uint64_t N;
- SHA256_CTX ctx;
- uint8_t * key_hmac = &dk[32];
- HMAC_SHA256_CTX hctx;
- int rc;
- /* Parse N, r, p, salt. */
- P->logN = header[7];
- P->r = be32dec(&header[8]);
- P->p = be32dec(&header[12]);
- memcpy(salt, &header[16], 32);
- /* Verify header checksum. */
- SHA256_Init(&ctx);
- SHA256_Update(&ctx, header, 48);
- SHA256_Final(hbuf, &ctx);
- if (crypto_verify_bytes(&header[48], hbuf, 16))
- return (SCRYPT_EINVAL);
- /*
- * Check whether the provided parameters are valid and whether the
- * key derivation function can be computed within the allowed memory
- * and CPU time, unless the user chose to disable this test.
- */
- if ((rc = checkparams(P->maxmem, P->maxmemfrac, P->maxtime, P->logN,
- P->r, P->p, verbose, force)) != 0)
- return (rc);
- /* Compute the derived keys. */
- N = (uint64_t)(1) << P->logN;
- if (crypto_scrypt(passwd, passwdlen, salt, 32, N, P->r, P->p, dk, 64))
- return (SCRYPT_EKEY);
- /* Check header signature (i.e., verify password). */
- HMAC_SHA256_Init(&hctx, key_hmac, 32);
- HMAC_SHA256_Update(&hctx, header, 64);
- HMAC_SHA256_Final(hbuf, &hctx);
- if (crypto_verify_bytes(hbuf, &header[64], 32))
- return (SCRYPT_EPASS);
- /* Success! */
- return (SCRYPT_OK);
- }
- /**
- * scryptenc_buf(inbuf, inbuflen, outbuf, passwd, passwdlen,
- * params, verbose, force):
- * Encrypt ${inbuflen} bytes from ${inbuf}, writing the resulting
- * ${inbuflen} + 128 bytes to ${outbuf}. If ${force} is 1, do not check
- * whether decryption will exceed the estimated available memory or time.
- * The explicit parameters within ${params} must be zero or must all be
- * non-zero. If explicit parameters are used and the computation is estimated
- * to exceed resource limits, print a warning instead of returning an error.
- * Return the explicit parameters used via ${params}.
- */
- int
- scryptenc_buf(const uint8_t * inbuf, size_t inbuflen, uint8_t * outbuf,
- const uint8_t * passwd, size_t passwdlen,
- struct scryptenc_params * P, int verbose, int force)
- {
- uint8_t dk[64];
- uint8_t hbuf[32];
- uint8_t header[96];
- uint8_t * key_enc = dk;
- uint8_t * key_hmac = &dk[32];
- int rc;
- HMAC_SHA256_CTX hctx;
- struct crypto_aes_key * key_enc_exp;
- struct crypto_aesctr * AES;
- /* The explicit parameters must be zero, or all non-zero. */
- assert(((P->logN == 0) && (P->r == 0) && (P->p == 0)) ||
- ((P->logN != 0) && (P->r != 0) && (P->p != 0)));
- /* Generate the header and derived key. */
- if ((rc = scryptenc_setup(header, dk, passwd, passwdlen,
- P, verbose, force)) != 0)
- goto err1;
- /* Copy header into output buffer. */
- memcpy(outbuf, header, 96);
- /* Encrypt data. */
- if ((key_enc_exp = crypto_aes_key_expand(key_enc, 32)) == NULL) {
- rc = SCRYPT_EOPENSSL;
- goto err1;
- }
- if ((AES = crypto_aesctr_init(key_enc_exp, 0)) == NULL) {
- crypto_aes_key_free(key_enc_exp);
- rc = SCRYPT_ENOMEM;
- goto err1;
- }
- crypto_aesctr_stream(AES, inbuf, &outbuf[96], inbuflen);
- crypto_aesctr_free(AES);
- crypto_aes_key_free(key_enc_exp);
- /* Add signature. */
- HMAC_SHA256_Init(&hctx, key_hmac, 32);
- HMAC_SHA256_Update(&hctx, outbuf, 96 + inbuflen);
- HMAC_SHA256_Final(hbuf, &hctx);
- memcpy(&outbuf[96 + inbuflen], hbuf, 32);
- /* Zero sensitive data. */
- insecure_memzero(dk, 64);
- /* Success! */
- return (SCRYPT_OK);
- err1:
- insecure_memzero(dk, 64);
- /* Failure! */
- return (rc);
- }
- /**
- * scryptdec_buf(inbuf, inbuflen, outbuf, outlen, passwd, passwdlen,
- * params, verbose, force):
- * Decrypt ${inbuflen} bytes from ${inbuf}, writing the result into ${outbuf}
- * and the decrypted data length to ${outlen}. The allocated length of
- * ${outbuf} must be at least ${inbuflen}. If ${force} is 1, do not check
- * whether decryption will exceed the estimated available memory or time.
- * The explicit parameters within ${params} must be zero. Return the explicit
- * parameters used via ${params}.
- */
- int
- scryptdec_buf(const uint8_t * inbuf, size_t inbuflen, uint8_t * outbuf,
- size_t * outlen, const uint8_t * passwd, size_t passwdlen,
- struct scryptenc_params * P, int verbose,
- int force)
- {
- uint8_t hbuf[32];
- uint8_t dk[64];
- uint8_t * key_enc = dk;
- uint8_t * key_hmac = &dk[32];
- int rc;
- HMAC_SHA256_CTX hctx;
- struct crypto_aes_key * key_enc_exp;
- struct crypto_aesctr * AES;
- /* The explicit parameters must be zero. */
- assert((P->logN == 0) && (P->r == 0) && (P->p == 0));
- /*
- * All versions of the scrypt format will start with "scrypt" and
- * have at least 7 bytes of header.
- */
- if ((inbuflen < 7) || (memcmp(inbuf, "scrypt", 6) != 0)) {
- rc = SCRYPT_EINVAL;
- goto err0;
- }
- /* Check the format. */
- if (inbuf[6] != 0) {
- rc = SCRYPT_EVERSION;
- goto err0;
- }
- /* We must have at least 128 bytes. */
- if (inbuflen < 128) {
- rc = SCRYPT_EINVAL;
- goto err0;
- }
- /* Parse the header and generate derived keys. */
- if ((rc = scryptdec_setup(inbuf, dk, passwd, passwdlen,
- P, verbose, force)) != 0)
- goto err1;
- /* Decrypt data. */
- if ((key_enc_exp = crypto_aes_key_expand(key_enc, 32)) == NULL) {
- rc = SCRYPT_EOPENSSL;
- goto err1;
- }
- if ((AES = crypto_aesctr_init(key_enc_exp, 0)) == NULL) {
- crypto_aes_key_free(key_enc_exp);
- rc = SCRYPT_ENOMEM;
- goto err1;
- }
- crypto_aesctr_stream(AES, &inbuf[96], outbuf, inbuflen - 128);
- crypto_aesctr_free(AES);
- crypto_aes_key_free(key_enc_exp);
- *outlen = inbuflen - 128;
- /* Verify signature. */
- HMAC_SHA256_Init(&hctx, key_hmac, 32);
- HMAC_SHA256_Update(&hctx, inbuf, inbuflen - 32);
- HMAC_SHA256_Final(hbuf, &hctx);
- if (crypto_verify_bytes(hbuf, &inbuf[inbuflen - 32], 32)) {
- rc = SCRYPT_EINVAL;
- goto err1;
- }
- /* Zero sensitive data. */
- insecure_memzero(dk, 64);
- /* Success! */
- return (SCRYPT_OK);
- err1:
- insecure_memzero(dk, 64);
- err0:
- /* Failure! */
- return (rc);
- }
- /**
- * scryptenc_file(infile, outfile, passwd, passwdlen, params, verbose, force):
- * Read a stream from ${infile} and encrypt it, writing the resulting stream
- * to ${outfile}. If ${force} is 1, do not check whether decryption will
- * exceed the estimated available memory or time. The explicit parameters
- * within ${params} must be zero or must all be non-zero. If explicit
- * parameters are used and the computation is estimated to exceed resource
- * limits, print a warning instead of returning an error. Return the explicit
- * parameters used via ${params}.
- */
- int
- scryptenc_file(FILE * infile, FILE * outfile,
- const uint8_t * passwd, size_t passwdlen,
- struct scryptenc_params * P, int verbose, int force)
- {
- uint8_t buf[ENCBLOCK];
- uint8_t dk[64];
- uint8_t hbuf[32];
- uint8_t header[96];
- uint8_t * key_enc = dk;
- uint8_t * key_hmac = &dk[32];
- size_t readlen;
- HMAC_SHA256_CTX hctx;
- struct crypto_aes_key * key_enc_exp;
- struct crypto_aesctr * AES;
- int rc;
- /* The explicit parameters must be zero, or all non-zero. */
- assert(((P->logN == 0) && (P->r == 0) && (P->p == 0)) ||
- ((P->logN != 0) && (P->r != 0) && (P->p != 0)));
- /* Generate the header and derived key. */
- if ((rc = scryptenc_setup(header, dk, passwd, passwdlen,
- P, verbose, force)) != 0)
- goto err1;
- /* Hash and write the header. */
- HMAC_SHA256_Init(&hctx, key_hmac, 32);
- HMAC_SHA256_Update(&hctx, header, 96);
- if (fwrite(header, 96, 1, outfile) != 1) {
- rc = SCRYPT_EWRFILE;
- goto err1;
- }
- /*
- * Read blocks of data, encrypt them, and write them out; hash the
- * data as it is produced.
- */
- if ((key_enc_exp = crypto_aes_key_expand(key_enc, 32)) == NULL) {
- rc = SCRYPT_EOPENSSL;
- goto err1;
- }
- if ((AES = crypto_aesctr_init(key_enc_exp, 0)) == NULL) {
- crypto_aes_key_free(key_enc_exp);
- rc = SCRYPT_ENOMEM;
- goto err1;
- }
- do {
- if ((readlen = fread(buf, 1, ENCBLOCK, infile)) == 0)
- break;
- crypto_aesctr_stream(AES, buf, buf, readlen);
- HMAC_SHA256_Update(&hctx, buf, readlen);
- if (fwrite(buf, 1, readlen, outfile) < readlen) {
- crypto_aesctr_free(AES);
- rc = SCRYPT_EWRFILE;
- goto err1;
- }
- } while (1);
- crypto_aesctr_free(AES);
- crypto_aes_key_free(key_enc_exp);
- /* Did we exit the loop due to a read error? */
- if (ferror(infile)) {
- rc = SCRYPT_ERDFILE;
- goto err1;
- }
- /* Compute the final HMAC and output it. */
- HMAC_SHA256_Final(hbuf, &hctx);
- if (fwrite(hbuf, 32, 1, outfile) != 1) {
- rc = SCRYPT_EWRFILE;
- goto err1;
- }
- /* Zero sensitive data. */
- insecure_memzero(dk, 64);
- /* Success! */
- return (SCRYPT_OK);
- err1:
- insecure_memzero(dk, 64);
- /* Failure! */
- return (rc);
- }
- /**
- * scryptdec_file_cookie_free(cookie):
- * Free the ${cookie}.
- */
- void
- scryptdec_file_cookie_free(struct scryptdec_file_cookie * C)
- {
- /* Behave consistently with free(NULL). */
- if (C == NULL)
- return;
- /* Zero sensitive data. */
- insecure_memzero(C->dk, 64);
- /* We do not free C->infile because it is not owned by this cookie. */
- /* Free the cookie. */
- free(C);
- }
- /* Load the header and check the magic. */
- static int
- scryptdec_file_load_header(FILE * infile, uint8_t header[static 96])
- {
- int rc;
- /*
- * Read the first 7 bytes of the file; all future versions of scrypt
- * are guaranteed to have at least 7 bytes of header.
- */
- if (fread(header, 7, 1, infile) < 1) {
- if (ferror(infile)) {
- rc = SCRYPT_ERDFILE;
- goto err0;
- } else {
- rc = SCRYPT_EINVAL;
- goto err0;
- }
- }
- /* Do we have the right magic? */
- if (memcmp(header, "scrypt", 6)) {
- rc = SCRYPT_EINVAL;
- goto err0;
- }
- if (header[6] != 0) {
- rc = SCRYPT_EVERSION;
- goto err0;
- }
- /*
- * Read another 89 bytes of the file; version 0 of the scrypt file
- * format has a 96-byte header.
- */
- if (fread(&header[7], 89, 1, infile) < 1) {
- if (ferror(infile)) {
- rc = SCRYPT_ERDFILE;
- goto err0;
- } else {
- rc = SCRYPT_EINVAL;
- goto err0;
- }
- }
- /* Success! */
- return (SCRYPT_OK);
- err0:
- /* Failure! */
- return (rc);
- }
- /**
- * scryptdec_file_prep(infile, passwd, passwdlen, params, verbose, force,
- * cookie):
- * Prepare to decrypt ${infile}, including checking the passphrase. Allocate
- * a cookie at ${cookie}. After calling this function, ${infile} should not
- * be modified until the decryption is completed by scryptdec_file_copy().
- * If ${force} is 1, do not check whether decryption will exceed the estimated
- * available memory or time. The explicit parameters within ${params} must be
- * zero. Return the explicit parameters to be used via ${params}.
- */
- int
- scryptdec_file_prep(FILE * infile, const uint8_t * passwd,
- size_t passwdlen, struct scryptenc_params * P,
- int verbose, int force, struct scryptdec_file_cookie ** cookie)
- {
- struct scryptdec_file_cookie * C;
- int rc;
- /* The explicit parameters must be zero. */
- assert((P->logN == 0) && (P->r == 0) && (P->p == 0));
- /* Allocate the cookie. */
- if ((C = malloc(sizeof(struct scryptdec_file_cookie))) == NULL)
- return (SCRYPT_ENOMEM);
- C->infile = infile;
- /* Load the header. */
- if ((rc = scryptdec_file_load_header(infile, C->header)) != 0)
- goto err1;
- /* Parse the header and generate derived keys. */
- if ((rc = scryptdec_setup(C->header, C->dk, passwd, passwdlen,
- P, verbose, force)) != 0)
- goto err1;
- /* Set cookie for calling function. */
- *cookie = C;
- /* Success! */
- return (SCRYPT_OK);
- err1:
- scryptdec_file_cookie_free(C);
- /* Failure! */
- return (rc);
- }
- /**
- * scryptdec_file_copy(cookie, outfile):
- * Read a stream from the file that was passed into the ${cookie} by
- * scryptdec_file_prep(), decrypt it, and write the resulting stream to
- * ${outfile}. After this function completes, it is safe to modify/close
- * ${outfile} and the ${infile} which was given to scryptdec_file_prep().
- */
- int
- scryptdec_file_copy(struct scryptdec_file_cookie * C, FILE * outfile)
- {
- uint8_t buf[ENCBLOCK + 32];
- uint8_t hbuf[32];
- uint8_t * key_enc;
- uint8_t * key_hmac;
- size_t buflen = 0;
- size_t readlen;
- HMAC_SHA256_CTX hctx;
- struct crypto_aes_key * key_enc_exp;
- struct crypto_aesctr * AES;
- int rc;
- /* Sanity check. */
- assert(C != NULL);
- /* Use existing array for these pointers. */
- key_enc = C->dk;
- key_hmac = &C->dk[32];
- /* Start hashing with the header. */
- HMAC_SHA256_Init(&hctx, key_hmac, 32);
- HMAC_SHA256_Update(&hctx, C->header, 96);
- /*
- * We don't know how long the encrypted data block is (we can't know,
- * since data can be streamed into 'scrypt enc') so we need to read
- * data and decrypt all of it except the final 32 bytes, then check
- * if that final 32 bytes is the correct signature.
- */
- if ((key_enc_exp = crypto_aes_key_expand(key_enc, 32)) == NULL) {
- rc = SCRYPT_EOPENSSL;
- goto err0;
- }
- if ((AES = crypto_aesctr_init(key_enc_exp, 0)) == NULL) {
- crypto_aes_key_free(key_enc_exp);
- rc = SCRYPT_ENOMEM;
- goto err0;
- }
- do {
- /* Read data until we have more than 32 bytes of it. */
- if ((readlen = fread(&buf[buflen], 1,
- ENCBLOCK + 32 - buflen, C->infile)) == 0)
- break;
- buflen += readlen;
- if (buflen <= 32)
- continue;
- /*
- * Decrypt, hash, and output everything except the last 32
- * bytes out of what we have in our buffer.
- */
- HMAC_SHA256_Update(&hctx, buf, buflen - 32);
- crypto_aesctr_stream(AES, buf, buf, buflen - 32);
- if (fwrite(buf, 1, buflen - 32, outfile) < buflen - 32) {
- crypto_aesctr_free(AES);
- rc = SCRYPT_EWRFILE;
- goto err0;
- }
- /* Move the last 32 bytes to the start of the buffer. */
- memmove(buf, &buf[buflen - 32], 32);
- buflen = 32;
- } while (1);
- crypto_aesctr_free(AES);
- crypto_aes_key_free(key_enc_exp);
- /* Did we exit the loop due to a read error? */
- if (ferror(C->infile)) {
- rc = SCRYPT_ERDFILE;
- goto err0;
- }
- /* Did we read enough data that we *might* have a valid signature? */
- if (buflen < 32) {
- rc = SCRYPT_EINVAL;
- goto err0;
- }
- /* Verify signature. */
- HMAC_SHA256_Final(hbuf, &hctx);
- if (crypto_verify_bytes(hbuf, buf, 32)) {
- rc = SCRYPT_EINVAL;
- goto err0;
- }
- /* Success! */
- return (SCRYPT_OK);
- err0:
- /* Failure! */
- return (rc);
- }
- /**
- * scryptdec_file(infile, outfile, passwd, passwdlen, params, verbose, force):
- * Read a stream from ${infile} and decrypt it, writing the resulting stream
- * to ${outfile}. If ${force} is 1, do not check whether decryption
- * will exceed the estimated available memory or time. The explicit
- * parameters within ${params} must be zero. Return the explicit parameters
- * used via ${params}.
- */
- int
- scryptdec_file(FILE * infile, FILE * outfile, const uint8_t * passwd,
- size_t passwdlen, struct scryptenc_params * P,
- int verbose, int force)
- {
- struct scryptdec_file_cookie * C;
- int rc;
- /* The explicit parameters must be zero. */
- assert((P->logN == 0) && (P->r == 0) && (P->p == 0));
- /* Check header, including passphrase. */
- if ((rc = scryptdec_file_prep(infile, passwd, passwdlen, P,
- verbose, force, &C)) != 0)
- goto err0;
- /* Copy unencrypted data to outfile. */
- if ((rc = scryptdec_file_copy(C, outfile)) != 0)
- goto err1;
- /* Clean up cookie, attempting to zero sensitive data. */
- scryptdec_file_cookie_free(C);
- /* Success! */
- return (SCRYPT_OK);
- err1:
- scryptdec_file_cookie_free(C);
- err0:
- /* Failure! */
- return (rc);
- }
|