diff --git a/crypto/hmac/hmac.c b/crypto/hmac/hmac.c index be2dccec..bccc5c02 100644 --- a/crypto/hmac/hmac.c +++ b/crypto/hmac/hmac.c @@ -59,6 +59,7 @@ #include #include +#include #include @@ -115,8 +116,8 @@ int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, size_t key_len, * case. Fix to API to avoid this. */ if (md != ctx->md || key != NULL) { size_t i; - uint8_t pad[HMAC_MAX_MD_CBLOCK]; - uint8_t key_block[HMAC_MAX_MD_CBLOCK]; + uint8_t pad[EVP_MAX_MD_BLOCK_SIZE]; + uint8_t key_block[EVP_MAX_MD_BLOCK_SIZE]; unsigned key_block_len; size_t block_size = EVP_MD_block_size(md); @@ -134,11 +135,11 @@ int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, size_t key_len, key_block_len = (unsigned)key_len; } /* Keys are then padded with zeros. */ - if (key_block_len != HMAC_MAX_MD_CBLOCK) { + if (key_block_len != EVP_MAX_MD_BLOCK_SIZE) { memset(&key_block[key_block_len], 0, sizeof(key_block) - key_block_len); } - for (i = 0; i < HMAC_MAX_MD_CBLOCK; i++) { + for (i = 0; i < EVP_MAX_MD_BLOCK_SIZE; i++) { pad[i] = 0x36 ^ key_block[i]; } if (!EVP_DigestInit_ex(&ctx->i_ctx, md, impl) || @@ -146,7 +147,7 @@ int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, size_t key_len, return 0; } - for (i = 0; i < HMAC_MAX_MD_CBLOCK; i++) { + for (i = 0; i < EVP_MAX_MD_BLOCK_SIZE; i++) { pad[i] = 0x5c ^ key_block[i]; } if (!EVP_DigestInit_ex(&ctx->o_ctx, md, impl) || diff --git a/crypto/pkcs8/pkcs8.c b/crypto/pkcs8/pkcs8.c index 3825522b..4ecf17f8 100644 --- a/crypto/pkcs8/pkcs8.c +++ b/crypto/pkcs8/pkcs8.c @@ -60,7 +60,6 @@ #include #include -#include #include #include #include @@ -107,112 +106,122 @@ static int ascii_to_ucs2(const char *ascii, size_t ascii_len, static int pkcs12_key_gen_raw(const uint8_t *pass_raw, size_t pass_raw_len, const uint8_t *salt, size_t salt_len, - int id, int iterations, + uint8_t id, int iterations, size_t out_len, uint8_t *out, - const EVP_MD *md_type) { - uint8_t *B, *D, *I, *p, *Ai; - int Slen, Plen, Ilen, Ijlen; - int i, j, v; - size_t u; - int ret = 0; - BIGNUM *Ij, *Bpl1; /* These hold Ij and B + 1 */ - EVP_MD_CTX ctx; + const EVP_MD *md) { + /* See https://tools.ietf.org/html/rfc7292#appendix-B. Quoted parts of the + * specification have errata applied and other typos fixed. */ + if (iterations < 1) { + OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_ITERATION_COUNT); + return 0; + } + + /* In the spec, |block_size| is called "v", but measured in bits. */ + size_t block_size = EVP_MD_block_size(md); + + /* 1. Construct a string, D (the "diversifier"), by concatenating v/8 copies + * of ID. */ + uint8_t D[EVP_MAX_MD_BLOCK_SIZE]; + memset(D, id, block_size); + + /* 2. Concatenate copies of the salt together to create a string S of length + * v(ceiling(s/v)) bits (the final copy of the salt may be truncated to + * create S). Note that if the salt is the empty string, then so is S. + * + * 3. Concatenate copies of the password together to create a string P of + * length v(ceiling(p/v)) bits (the final copy of the password may be + * truncated to create P). Note that if the password is the empty string, + * then so is P. + * + * 4. Set I=S||P to be the concatenation of S and P. */ + if (salt_len + block_size - 1 < salt_len || + pass_raw_len + block_size - 1 < pass_raw_len) { + OPENSSL_PUT_ERROR(PKCS8, ERR_R_OVERFLOW); + return 0; + } + size_t S_len = block_size * ((salt_len + block_size - 1) / block_size); + size_t P_len = block_size * ((pass_raw_len + block_size - 1) / block_size); + size_t I_len = S_len + P_len; + if (I_len < S_len) { + OPENSSL_PUT_ERROR(PKCS8, ERR_R_OVERFLOW); + return 0; + } + + uint8_t *I = OPENSSL_malloc(I_len); + if (I_len != 0 && I == NULL) { + OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE); + return 0; + } + + size_t i; + for (i = 0; i < S_len; i++) { + I[i] = salt[i % salt_len]; + } + for (i = 0; i < P_len; i++) { + I[i + S_len] = pass_raw[i % pass_raw_len]; + } + + int ret = 0; + EVP_MD_CTX ctx; EVP_MD_CTX_init(&ctx); - v = EVP_MD_block_size(md_type); - u = EVP_MD_size(md_type); - D = OPENSSL_malloc(v); - Ai = OPENSSL_malloc(u); - B = OPENSSL_malloc(v + 1); - Slen = v * ((salt_len + v - 1) / v); - if (pass_raw_len) { - Plen = v * ((pass_raw_len + v - 1) / v); - } else { - Plen = 0; - } - Ilen = Slen + Plen; - I = OPENSSL_malloc(Ilen); - Ij = BN_new(); - Bpl1 = BN_new(); - if (!D || !Ai || !B || !I || !Ij || !Bpl1) { - goto err; - } - for (i = 0; i < v; i++) { - D[i] = id; - } - p = I; - for (i = 0; i < Slen; i++) { - *p++ = salt[i % salt_len]; - } - for (i = 0; i < Plen; i++) { - *p++ = pass_raw[i % pass_raw_len]; - } - for (;;) { - if (!EVP_DigestInit_ex(&ctx, md_type, NULL) || - !EVP_DigestUpdate(&ctx, D, v) || - !EVP_DigestUpdate(&ctx, I, Ilen) || - !EVP_DigestFinal_ex(&ctx, Ai, NULL)) { + + while (out_len != 0) { + /* A. Set A_i=H^r(D||I). (i.e., the r-th hash of D||I, + * H(H(H(... H(D||I)))) */ + uint8_t A[EVP_MAX_MD_SIZE]; + unsigned A_len; + if (!EVP_DigestInit_ex(&ctx, md, NULL) || + !EVP_DigestUpdate(&ctx, D, block_size) || + !EVP_DigestUpdate(&ctx, I, I_len) || + !EVP_DigestFinal_ex(&ctx, A, &A_len)) { goto err; } - for (j = 1; j < iterations; j++) { - if (!EVP_DigestInit_ex(&ctx, md_type, NULL) || - !EVP_DigestUpdate(&ctx, Ai, u) || - !EVP_DigestFinal_ex(&ctx, Ai, NULL)) { + int iter; + for (iter = 1; iter < iterations; iter++) { + if (!EVP_DigestInit_ex(&ctx, md, NULL) || + !EVP_DigestUpdate(&ctx, A, A_len) || + !EVP_DigestFinal_ex(&ctx, A, &A_len)) { goto err; } } - memcpy(out, Ai, out_len < u ? out_len : u); - if (u >= out_len) { - ret = 1; - goto end; + + size_t todo = out_len < A_len ? out_len : A_len; + memcpy(out, A, todo); + out += todo; + out_len -= todo; + if (out_len == 0) { + break; } - out_len -= u; - out += u; - for (j = 0; j < v; j++) { - B[j] = Ai[j % u]; + + /* B. Concatenate copies of A_i to create a string B of length v bits (the + * final copy of A_i may be truncated to create B). */ + uint8_t B[EVP_MAX_MD_BLOCK_SIZE]; + for (i = 0; i < block_size; i++) { + B[i] = A[i % A_len]; } - /* Work out B + 1 first then can use B as tmp space */ - if (!BN_bin2bn(B, v, Bpl1) || - !BN_add_word(Bpl1, 1)) { - goto err; - } - for (j = 0; j < Ilen; j += v) { - if (!BN_bin2bn(I + j, v, Ij) || - !BN_add(Ij, Ij, Bpl1) || - !BN_bn2bin(Ij, B)) { - goto err; - } - Ijlen = BN_num_bytes(Ij); - /* If more than 2^(v*8) - 1 cut off MSB */ - if (Ijlen > v) { - if (!BN_bn2bin(Ij, B)) { - goto err; - } - memcpy(I + j, B + 1, v); - /* If less than v bytes pad with zeroes */ - } else if (Ijlen < v) { - memset(I + j, 0, v - Ijlen); - if (!BN_bn2bin(Ij, I + j + v - Ijlen)) { - goto err; - } - } else if (!BN_bn2bin(Ij, I + j)) { - goto err; + + /* C. Treating I as a concatenation I_0, I_1, ..., I_(k-1) of v-bit blocks, + * where k=ceiling(s/v)+ceiling(p/v), modify I by setting I_j=(I_j+B+1) mod + * 2^v for each j. */ + assert(I_len % block_size == 0); + for (i = 0; i < I_len; i += block_size) { + unsigned carry = 1; + size_t j; + for (j = block_size - 1; j < block_size; j--) { + carry += I[i + j] + B[j]; + I[i + j] = (uint8_t)carry; + carry >>= 8; } } } + ret = 1; + err: - OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE); - -end: - OPENSSL_free(Ai); - OPENSSL_free(B); - OPENSSL_free(D); + OPENSSL_cleanse(I, I_len); OPENSSL_free(I); - BN_free(Ij); - BN_free(Bpl1); EVP_MD_CTX_cleanup(&ctx); - return ret; } diff --git a/include/openssl/digest.h b/include/openssl/digest.h index 9a5ec511..db3ead71 100644 --- a/include/openssl/digest.h +++ b/include/openssl/digest.h @@ -143,6 +143,9 @@ OPENSSL_EXPORT int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *data, * at least this much space. */ #define EVP_MAX_MD_SIZE 64 /* SHA-512 is the longest so far. */ +/* EVP_MAX_MD_BLOCK_SIZE is the largest digest block size supported, in bytes. */ +#define EVP_MAX_MD_BLOCK_SIZE 128 /* SHA-512 is the longest so far. */ + /* EVP_DigestFinal_ex finishes the digest in |ctx| and writes the output to * |md_out|. At most |EVP_MAX_MD_SIZE| bytes are written. If |out_size| is not * NULL then |*out_size| is set to the number of bytes written. It returns one. diff --git a/include/openssl/hmac.h b/include/openssl/hmac.h index e521212d..5a4e9c7f 100644 --- a/include/openssl/hmac.h +++ b/include/openssl/hmac.h @@ -143,8 +143,6 @@ OPENSSL_EXPORT int HMAC_CTX_copy(HMAC_CTX *dest, const HMAC_CTX *src); /* Private functions */ -#define HMAC_MAX_MD_CBLOCK 128 /* largest known is SHA512 */ - struct hmac_ctx_st { const EVP_MD *md; EVP_MD_CTX md_ctx;