示例#1
0
/**
 * 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);
}
示例#2
0
/**
 * proto_crypt_free(k):
 * Free the protocol key structure ${k}.
 */
void
proto_crypt_free(struct proto_keys * k)
{

	/* Be compatible with free(NULL). */
	if (k == NULL)
		return;

	/* Free the AES key. */
	crypto_aes_key_free(k->k_aes);

	/* Free the key structure. */
	free(k);
}
示例#3
0
/**
 * 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);
}
示例#4
0
/**
 * 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);
}
示例#5
0
/**
 * 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);
}