コード例 #1
0
int get_random(uint8_t *buffer, size_t len){
	int i;
	uint8_t shabuf[SHA256_DIGEST_LEN];
	HMAC_SHA256_CTX ctx;
	size_t left;

	for (i=0, left=len; left > 0 ; ++i){
		HMAC_SHA256_Init(&ctx, entropy_pool, 32);
		HMAC_SHA256_Update(&ctx, "generate", 8);
		HMAC_SHA256_Final(shabuf, &ctx);

		HMAC_SHA256_Init(&ctx, entropy_pool, 32);
		HMAC_SHA256_Update(&ctx, "reseed", 6);
		HMAC_SHA256_Final(entropy_pool, &ctx);

		memcpy(buffer + i*SHA256_DIGEST_LEN, shabuf,
				left > SHA256_DIGEST_LEN ? SHA256_DIGEST_LEN: left);
		if (left > SHA256_DIGEST_LEN)
			left -= SHA256_DIGEST_LEN;
		else
			left = 0;
	}
	ZERO(shabuf);
	ZERO(ctx);

	return len;
}
コード例 #2
0
ファイル: sha256.c プロジェクト: 10xEngineer/My-Wallet-iPhone
/**
 * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
 * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
 * write the output to buf.  The value dkLen must be at most 32 * (2^32 - 1).
 */
void
PBKDF2_SHA256(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt,
    size_t saltlen, uint64_t c, uint8_t * buf, size_t dkLen)
{
	HMAC_SHA256_CTX PShctx, hctx;
	size_t i;
	uint8_t ivec[4];
	uint8_t U[32];
	uint8_t T[32];
	uint64_t j;
	int k;
	size_t clen;

	/* Compute HMAC state after processing P and S. */
	HMAC_SHA256_Init(&PShctx, passwd, passwdlen);
	HMAC_SHA256_Update(&PShctx, salt, saltlen);

	/* Iterate through the blocks. */
	for (i = 0; i * 32 < dkLen; i++) {
		/* Generate INT(i + 1). */
		be32enc(ivec, (uint32_t)(i + 1));

		/* Compute U_1 = PRF(P, S || INT(i)). */
		memcpy(&hctx, &PShctx, sizeof(HMAC_SHA256_CTX));
		HMAC_SHA256_Update(&hctx, ivec, 4);
		HMAC_SHA256_Final(U, &hctx);

		/* T_i = U_1 ... */
		memcpy(T, U, 32);

		for (j = 2; j <= c; j++) {
			/* Compute U_j. */
			HMAC_SHA256_Init(&hctx, passwd, passwdlen);
			HMAC_SHA256_Update(&hctx, U, 32);
			HMAC_SHA256_Final(U, &hctx);

			/* ... xor U_j ... */
			for (k = 0; k < 32; k++)
				T[k] ^= U[k];
		}

		/* Copy as many bytes as necessary into buf. */
		clen = dkLen - i * 32;
		if (clen > 32)
			clen = 32;
		memcpy(&buf[i * 32], T, clen);
	}

	/* Clean PShctx, since we never called _Final on it. */
	memset(&PShctx, 0, sizeof(HMAC_SHA256_CTX));
}
コード例 #3
0
ファイル: proto_crypt.c プロジェクト: c0decafe/spiped
/**
 * proto_crypt_enc(ibuf, len, obuf, k):
 * Encrypt ${len} bytes from ${ibuf} into PCRYPT_ESZ bytes using the keys in
 * ${k}, and write the result into ${obuf}.
 */
void
proto_crypt_enc(uint8_t * ibuf, size_t len, uint8_t obuf[PCRYPT_ESZ],
    struct proto_keys * k)
{
	HMAC_SHA256_CTX ctx;
	uint8_t pnum_exp[8];

	/* Sanity-check the length. */
	assert(len <= PCRYPT_MAXDSZ);

	/* Copy the decrypted data into the encrypted buffer. */
	memcpy(obuf, ibuf, len);

	/* Pad up to PCRYPT_MAXDSZ with zeroes. */
	memset(&obuf[len], 0, PCRYPT_MAXDSZ - len);

	/* Add the length. */
	be32enc(&obuf[PCRYPT_MAXDSZ], len);

	/* Encrypt the buffer in-place. */
	crypto_aesctr_buf(k->k_aes, k->pnum, obuf, obuf, PCRYPT_MAXDSZ + 4);

	/* Append an HMAC. */
	be64enc(pnum_exp, k->pnum);
	HMAC_SHA256_Init(&ctx, k->k_hmac, 32);
	HMAC_SHA256_Update(&ctx, obuf, PCRYPT_MAXDSZ + 4);
	HMAC_SHA256_Update(&ctx, pnum_exp, 8);
	HMAC_SHA256_Final(&obuf[PCRYPT_MAXDSZ + 4], &ctx);

	/* Increment packet number. */
	k->pnum += 1;
}
コード例 #4
0
ファイル: scryptenc.c プロジェクト: AVVS/node-scrypt
/**
 * scryptdec_buf(inbuf, inbuflen, outbuf, outlen, passwd, passwdlen,
 *     maxmem, maxmemfrac, maxtime):
 * 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.
 */
int
scryptdec_buf(const uint8_t * inbuf, size_t inbuflen, uint8_t * outbuf,
    size_t * outlen, const uint8_t * passwd, size_t passwdlen,
    size_t maxmem, double maxmemfrac, double maxtime)
{
	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;

	/*
	 * 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))
		return (7);

	/* Check the format. */
	if (inbuf[6] != 0)
		return (8);

	/* We must have at least 128 bytes. */
	if (inbuflen < 128)
		return (7);

	/* Parse the header and generate derived keys. */
	if ((rc = scryptdec_setup(inbuf, dk, passwd, passwdlen,
	    maxmem, maxmemfrac, maxtime)) != 0)
		return (rc);

	/* Decrypt data. */
	if ((key_enc_exp = crypto_aes_key_expand(key_enc, 32)) == NULL)
		return (5);
	if ((AES = crypto_aesctr_init(key_enc_exp, 0)) == NULL)
		return (6);
	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 (memcmp(hbuf, &inbuf[inbuflen - 32], 32))
		return (7);

	/* Zero sensitive data. */
	insecure_memzero(dk, 64);

	/* Success! */
	return (0);
}
コード例 #5
0
ファイル: scryptenc.c プロジェクト: AVVS/node-scrypt
static int
scryptenc_setup(uint8_t header[96], uint8_t dk[64],
    const uint8_t * passwd, size_t passwdlen,
    size_t maxmem, double maxmemfrac, double maxtime)
{
	uint8_t salt[32];
	uint8_t hbuf[32];
	int logN;
	uint64_t N;
	uint32_t r;
	uint32_t p;
	SHA256_CTX ctx;
	uint8_t * key_hmac = &dk[32];
	HMAC_SHA256_CTX hctx;
	int rc;

	/* Pick values for N, r, p. */
	if ((rc = pickparams(maxmem, maxmemfrac, maxtime,
	    &logN, &r, &p)) != 0)
		return (rc);
	N = (uint64_t)(1) << logN;

	/* Get some salt. */
	if (crypto_entropy_read(salt, 32))
		return (4);

	/* Generate the derived keys. */
	if (crypto_scrypt(passwd, passwdlen, salt, 32, N, r, p, dk, 64))
		return (3);

	/* Construct the file header. */
	memcpy(header, "scrypt", 6);
	header[6] = 0;
	header[7] = logN;
	be32enc(&header[8], r);
	be32enc(&header[12], 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 (0);
}
コード例 #6
0
ファイル: scryptenc.c プロジェクト: carriercomm/tarsnap
static int
scryptdec_setup(const uint8_t header[96], uint8_t dk[64],
                const uint8_t * passwd, size_t passwdlen,
                size_t maxmem, double maxmemfrac, double maxtime, int verbose)
{
    uint8_t salt[32];
    uint8_t hbuf[32];
    int logN;
    uint32_t r;
    uint32_t p;
    uint64_t N;
    SHA256_CTX ctx;
    uint8_t * key_hmac = &dk[32];
    HMAC_SHA256_CTX hctx;
    int rc;

    /* Parse N, r, p, salt. */
    logN = header[7];
    r = be32dec(&header[8]);
    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 (memcmp(&header[48], hbuf, 16))
        return (7);

    /*
     * Check whether the provided parameters are valid and whether the
     * key derivation function can be computed within the allowed memory
     * and CPU time.
     */
    if ((rc = checkparams(maxmem, maxmemfrac, maxtime, logN, r, p,
                          verbose)) != 0)
        return (rc);

    /* Compute the derived keys. */
    N = (uint64_t)(1) << logN;
    if (crypto_scrypt(passwd, passwdlen, salt, 32, N, r, p, dk, 64))
        return (3);

    /* 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 (memcmp(hbuf, &header[64], 32))
        return (11);

    /* Success! */
    return (0);
}
コード例 #7
0
ファイル: crypto_hash.c プロジェクト: carriercomm/tarsnap
/**
 * crypto_hash_data_key_2(key, keylen, data0, len0, data1, len1, buf):
 * Hash the concatenation of two buffers with the provided HMAC-SHA256 key.
 */
void
crypto_hash_data_key_2(const uint8_t * key, size_t keylen,
    const uint8_t * data0, size_t len0,
    const uint8_t * data1, size_t len1, uint8_t buf[32])
{
	HMAC_SHA256_CTX hctx;

	/* Do the hashing. */
	HMAC_SHA256_Init(&hctx, key, keylen);
	HMAC_SHA256_Update(&hctx, data0, len0);
	HMAC_SHA256_Update(&hctx, data1, len1);
	HMAC_SHA256_Final(buf, &hctx);

	/* Clean the stack. */
	memset(&hctx, 0, sizeof(HMAC_SHA256_CTX));
}
コード例 #8
0
ファイル: scryptenc.c プロジェクト: AVVS/node-scrypt
/**
 * scryptenc_buf(inbuf, inbuflen, outbuf, passwd, passwdlen,
 *     maxmem, maxmemfrac, maxtime):
 * Encrypt inbuflen bytes from inbuf, writing the resulting inbuflen + 128
 * bytes to outbuf.
 */
int
scryptenc_buf(const uint8_t * inbuf, size_t inbuflen, uint8_t * outbuf,
    const uint8_t * passwd, size_t passwdlen,
    size_t maxmem, double maxmemfrac, double maxtime)
{
	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;

	/* Generate the header and derived key. */
	if ((rc = scryptenc_setup(header, dk, passwd, passwdlen,
	    maxmem, maxmemfrac, maxtime)) != 0)
		return (rc);

	/* Copy header into output buffer. */
	memcpy(outbuf, header, 96);

	/* Encrypt data. */
	if ((key_enc_exp = crypto_aes_key_expand(key_enc, 32)) == NULL)
		return (5);
	if ((AES = crypto_aesctr_init(key_enc_exp, 0)) == NULL)
		return (6);
	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 (0);
}
コード例 #9
0
ファイル: hkdf.c プロジェクト: davidlamprea/candado
bool hkdf(const uint8_t *salt, size_t salt_len, const uint8_t *key,
          size_t key_len, const uint8_t *info, size_t info_len, uint8_t *out,
          size_t out_len) {
    uint8_t prk[HASH_LEN];
    HMAC_SHA256_CTX ctx;

    // Performs the extract phase. Notice that |salt| is used as the key and
    // |key| as the message.
    HMAC_SHA256_Init(&ctx, salt, salt_len);
    HMAC_SHA256_Update(&ctx, key, key_len);
    HMAC_SHA256_Final(prk, &ctx);

    // Performs the expand phase.
    if (!hkdf_expand(prk, HASH_LEN, info, info_len, out, out_len))
        return false;

    explicit_bzero(prk, HASH_LEN);
    return true;
}
コード例 #10
0
ファイル: hkdf.c プロジェクト: davidlamprea/candado
bool hkdf_expand(const uint8_t *key, size_t key_len, const uint8_t *info,
                 size_t info_len, uint8_t *out, size_t out_len) {
    uint8_t previous[HASH_LEN];
    uint8_t previous_len = 0;
    HMAC_SHA256_CTX ctx;

    // The RFC states that the counter has only one byte, so we can’t produce
    // more output than this (which is already too much for any real
    // application).
    if (out_len > HASH_LEN * 255) {
        errno = EOVERFLOW;
        return false;
    }

    for (uint8_t i = 1;; ++i) {
        HMAC_SHA256_Init(&ctx, key, key_len);
        HMAC_SHA256_Update(&ctx, previous, previous_len);
        HMAC_SHA256_Update(&ctx, info, info_len);
        HMAC_SHA256_Update(&ctx, &i, 1);
        HMAC_SHA256_Final(previous, &ctx);

        if (previous_len == 0)
            previous_len = HASH_LEN;

        if (out_len <= HASH_LEN) {
            // Copies the last bytes to |out| and we’re done.
            memcpy(out, previous, out_len);
            break;
        } else {
            // Copies the HMAC() output to |out| and prepares for the next
            // round.
            memcpy(out, previous, HASH_LEN);
            out += HASH_LEN;
            out_len -= HASH_LEN;
        }
    }

    return true;
}
コード例 #11
0
ファイル: crypto_hash.c プロジェクト: carriercomm/tarsnap
/**
 * crypto_hash_data_2(key, data0, len0, data1, len1, buf):
 * Hash the concatenation of two buffers, as in crypto_hash_data.
 */
int
crypto_hash_data_2(int key, const uint8_t * data0, size_t len0,
    const uint8_t * data1, size_t len1, uint8_t buf[32])
{
	HMAC_SHA256_CTX hctx;
	SHA256_CTX ctx;
	struct crypto_hmac_key * hkey;

	if (key == CRYPTO_KEY_HMAC_SHA256) {
		/* Hash the data. */
		SHA256_Init(&ctx);
		SHA256_Update(&ctx, data0, len0);
		SHA256_Update(&ctx, data1, len1);
		SHA256_Final(buf, &ctx);

		/* Clean the stack. */
		memset(&ctx, 0, sizeof(SHA256_CTX));
	} else {
		if ((hkey = crypto_keys_lookup_HMAC(key)) == NULL)
			goto err0;

		/* Do the HMAC. */
		HMAC_SHA256_Init(&hctx, hkey->key, hkey->len);
		HMAC_SHA256_Update(&hctx, data0, len0);
		HMAC_SHA256_Update(&hctx, data1, len1);
		HMAC_SHA256_Final(buf, &hctx);

		/* Clean the stack. */
		memset(&hctx, 0, sizeof(HMAC_SHA256_CTX));
	}

	/* Success! */
	return (0);

err0:
	/* Failure! */
	return (-1);
}
コード例 #12
0
ファイル: keyderivation.c プロジェクト: AVVS/node-scrypt
//
//  Verifies password hash (also ensures hash integrity at same time)
//
int
Verify(const uint8_t* kdf, const uint8_t* passwd, size_t passwdSize) {
  uint64_t N=0;
  uint32_t r=0, p=0;
  uint8_t dk[64],
          salt[32],
          hbuf[32];
  uint8_t * key_hmac = &dk[32];
  HMAC_SHA256_CTX hctx;
  SHA256_CTX ctx;

  /* Parse N, r, p, salt. */
  N = (uint64_t)1 << kdf[7]; //Remember, kdf[7] is actually LogN
  r = be32dec(&kdf[8]);
  p = be32dec(&kdf[12]);
  memcpy(salt, &kdf[16], 32);

  /* Verify hash checksum. */
  SHA256_Init(&ctx);
  SHA256_Update(&ctx, kdf, 48);
  SHA256_Final(hbuf, &ctx);
  if (memcmp(&kdf[48], hbuf, 16))
    return (7);

  /* Compute Derived Key */
  if (ScryptHashFunction(passwd, passwdSize, salt, 32, N, r, p, dk, 64))
    return (3);

  /* Check hash signature (i.e., verify password). */
  HMAC_SHA256_Init(&hctx, key_hmac, 32);
  HMAC_SHA256_Update(&hctx, kdf, 64);
  HMAC_SHA256_Final(hbuf, &hctx);
  if (memcmp(hbuf, &kdf[64], 32))
    return (11);

  return (0); //Success
}
コード例 #13
0
ファイル: keyderivation.c プロジェクト: AVVS/node-scrypt
//
// Creates a password hash. This is the actual key derivation function
//
unsigned int
KDF(const uint8_t* passwd, size_t passwdSize, uint8_t* kdf, uint32_t logN, uint32_t r, uint32_t p, const uint8_t* salt) {
  uint64_t N=1;
  uint8_t dk[64],
          hbuf[32];
  uint8_t *key_hmac = &dk[32];
  SHA256_CTX ctx;
  HMAC_SHA256_CTX hctx;

  /* Generate the derived keys. */
  N <<= logN;
  if (ScryptHashFunction(passwd, passwdSize, salt, 32, N, r, p, dk, 64))
    return (3);

  /* Construct the hash. */
  memcpy(kdf, "scrypt", 6); //Sticking with Colin Percival's format of putting scrypt at the beginning
  kdf[6] = 0;
  kdf[7] = logN;
  be32enc(&kdf[8], r);
  be32enc(&kdf[12], p);
  memcpy(&kdf[16], salt, 32);

  /* Add hash checksum. */
  SHA256_Init(&ctx);
  SHA256_Update(&ctx, kdf, 48);
  SHA256_Final(hbuf, &ctx);
  memcpy(&kdf[48], hbuf, 16);

  /* Add hash signature (used for verifying password). */
  HMAC_SHA256_Init(&hctx, key_hmac, 32);
  HMAC_SHA256_Update(&hctx, kdf, 64);
  HMAC_SHA256_Final(hbuf, &hctx);
  memcpy(&kdf[64], hbuf, 32);

  return 0; //success
}
コード例 #14
0
ファイル: proto_crypt.c プロジェクト: c0decafe/spiped
/**
 * proto_crypt_dec(ibuf, obuf, k):
 * Decrypt PCRYPT_ESZ bytes from ${ibuf} using the keys in ${k}.  If the data
 * is valid, write it into ${obuf} and return the length; otherwise, return
 * -1.
 */
ssize_t proto_crypt_dec(uint8_t ibuf[PCRYPT_ESZ], uint8_t * obuf,
    struct proto_keys * k)
{
	HMAC_SHA256_CTX ctx;
	uint8_t hbuf[32];
	uint8_t pnum_exp[8];
	size_t len;

	/* Verify HMAC. */
	be64enc(pnum_exp, k->pnum);
	HMAC_SHA256_Init(&ctx, k->k_hmac, 32);
	HMAC_SHA256_Update(&ctx, ibuf, PCRYPT_MAXDSZ + 4);
	HMAC_SHA256_Update(&ctx, pnum_exp, 8);
	HMAC_SHA256_Final(hbuf, &ctx);
	if (crypto_verify_bytes(hbuf, &ibuf[PCRYPT_MAXDSZ + 4], 32))
		return (-1);

	/* Decrypt the buffer in-place. */
	crypto_aesctr_buf(k->k_aes, k->pnum, ibuf, ibuf, PCRYPT_MAXDSZ + 4);

	/* Increment packet number. */
	k->pnum += 1;

	/* Parse length. */
	len = be32dec(&ibuf[PCRYPT_MAXDSZ]);

	/* Make sure nobody is being evil here... */
	if ((len == 0) || (len > PCRYPT_MAXDSZ))
		return (-1);

	/* Copy the bytes into the output buffer. */
	memcpy(obuf, ibuf, len);

	/* Return the decrypted length. */
	return (len);
}
コード例 #15
0
ファイル: scryptenc.c プロジェクト: AVVS/node-scrypt
/**
 * scryptdec_file(infile, outfile, passwd, passwdlen,
 *     maxmem, maxmemfrac, maxtime):
 * Read a stream from infile and decrypt it, writing the resulting stream to
 * outfile.
 */
int
scryptdec_file(FILE * infile, FILE * outfile,
    const uint8_t * passwd, size_t passwdlen,
    size_t maxmem, double maxmemfrac, double maxtime)
{
	uint8_t buf[ENCBLOCK + 32];
	uint8_t header[96];
	uint8_t hbuf[32];
	uint8_t dk[64];
	uint8_t * key_enc = dk;
	uint8_t * key_hmac = &dk[32];
	size_t buflen = 0;
	size_t readlen;
	HMAC_SHA256_CTX hctx;
	struct crypto_aes_key * key_enc_exp;
	struct crypto_aesctr * AES;
	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))
			return (13);
		else
			return (7);
	}

	/* Do we have the right magic? */
	if (memcmp(header, "scrypt", 6))
		return (7);
	if (header[6] != 0)
		return (8);

	/*
	 * 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))
			return (13);
		else
			return (7);
	}

	/* Parse the header and generate derived keys. */
	if ((rc = scryptdec_setup(header, dk, passwd, passwdlen,
	    maxmem, maxmemfrac, maxtime)) != 0)
		return (rc);

	/* Start hashing with the header. */
	HMAC_SHA256_Init(&hctx, key_hmac, 32);
	HMAC_SHA256_Update(&hctx, 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)
		return (5);
	if ((AES = crypto_aesctr_init(key_enc_exp, 0)) == NULL)
		return (6);
	do {
		/* Read data until we have more than 32 bytes of it. */
		if ((readlen = fread(&buf[buflen], 1,
		    ENCBLOCK + 32 - buflen, 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);
			return (12);
		}

		/* 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(infile))
		return (13);

	/* Did we read enough data that we *might* have a valid signature? */
	if (buflen < 32)
		return (7);

	/* Verify signature. */
	HMAC_SHA256_Final(hbuf, &hctx);
	if (memcmp(hbuf, buf, 32))
		return (7);

	/* Zero sensitive data. */
	insecure_memzero(dk, 64);

	return (0);
}
コード例 #16
0
ファイル: scryptenc.c プロジェクト: AVVS/node-scrypt
/**
 * scryptenc_file(infile, outfile, passwd, passwdlen,
 *     maxmem, maxmemfrac, maxtime):
 * Read a stream from infile and encrypt it, writing the resulting stream to
 * outfile.
 */
int
scryptenc_file(FILE * infile, FILE * outfile,
    const uint8_t * passwd, size_t passwdlen,
    size_t maxmem, double maxmemfrac, double maxtime)
{
	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;

	/* Generate the header and derived key. */
	if ((rc = scryptenc_setup(header, dk, passwd, passwdlen,
	    maxmem, maxmemfrac, maxtime)) != 0)
		return (rc);

	/* 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)
		return (12);

	/*
	 * 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)
		return (5);
	if ((AES = crypto_aesctr_init(key_enc_exp, 0)) == NULL)
		return (6);
	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);
			return (12);
		}
	} 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))
		return (13);

	/* Compute the final HMAC and output it. */
	HMAC_SHA256_Final(hbuf, &hctx);
	if (fwrite(hbuf, 32, 1, outfile) != 1)
		return (12);

	/* Zero sensitive data. */
	insecure_memzero(dk, 64);

	/* Success! */
	return (0);
}