X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fevp%2Fp5_crpt2.c;h=ac5b974e5457cf09bcd7e8e13af32a7a8dbe381d;hp=2e45aa3bd8ecf8a67cf3997450f5af706a877d63;hb=3a9b3d2d93017014032d1bbed3e4193bb423eaae;hpb=6286757141a8c6e14d647ec733634ae0c83d9887 diff --git a/crypto/evp/p5_crpt2.c b/crypto/evp/p5_crpt2.c index 2e45aa3bd8..ac5b974e54 100644 --- a/crypto/evp/p5_crpt2.c +++ b/crypto/evp/p5_crpt2.c @@ -1,7 +1,7 @@ /* - * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html @@ -10,115 +10,61 @@ #include #include #include "internal/cryptlib.h" -# include -# include -# include -# include "evp_locl.h" - -/* set this to print out info about the keygen algorithm */ -/* #define OPENSSL_DEBUG_PKCS5V2 */ - -# ifdef OPENSSL_DEBUG_PKCS5V2 -static void h__dump(const unsigned char *p, int len); -# endif - -/* - * This is an implementation of PKCS#5 v2.0 password based encryption key - * derivation function PBKDF2. SHA1 version verified against test vectors - * posted by Peter Gutmann to the PKCS-TNG - * mailing list. - */ +#include +#include +#include +#include +#include +#include "internal/evp_int.h" +#include "evp_locl.h" int PKCS5_PBKDF2_HMAC(const char *pass, int passlen, const unsigned char *salt, int saltlen, int iter, const EVP_MD *digest, int keylen, unsigned char *out) { - unsigned char digtmp[EVP_MAX_MD_SIZE], *p, itmp[4]; - int cplen, j, k, tkeylen, mdlen; - unsigned long i = 1; - HMAC_CTX *hctx_tpl = NULL, *hctx = NULL; + const char *empty = ""; + int rv = 1; + EVP_KDF_CTX *kctx; - mdlen = EVP_MD_size(digest); - if (mdlen < 0) - return 0; - - hctx_tpl = HMAC_CTX_new(); - if (hctx_tpl == NULL) - return 0; - p = out; - tkeylen = keylen; - if (!pass) + /* Keep documented behaviour. */ + if (pass == NULL) { + pass = empty; passlen = 0; - else if (passlen == -1) + } else if (passlen == -1) { passlen = strlen(pass); - if (!HMAC_Init_ex(hctx_tpl, pass, passlen, digest, NULL)) { - HMAC_CTX_free(hctx_tpl); - return 0; } - hctx = HMAC_CTX_new(); - if (hctx == NULL) { - HMAC_CTX_free(hctx_tpl); + if (salt == NULL && saltlen == 0) + salt = (unsigned char *)empty; + + kctx = EVP_KDF_CTX_new_id(EVP_KDF_PBKDF2); + if (kctx == NULL) return 0; - } - while (tkeylen) { - if (tkeylen > mdlen) - cplen = mdlen; - else - cplen = tkeylen; - /* - * We are unlikely to ever use more than 256 blocks (5120 bits!) but - * just in case... - */ - itmp[0] = (unsigned char)((i >> 24) & 0xff); - itmp[1] = (unsigned char)((i >> 16) & 0xff); - itmp[2] = (unsigned char)((i >> 8) & 0xff); - itmp[3] = (unsigned char)(i & 0xff); - if (!HMAC_CTX_copy(hctx, hctx_tpl)) { - HMAC_CTX_free(hctx); - HMAC_CTX_free(hctx_tpl); - return 0; - } - if (!HMAC_Update(hctx, salt, saltlen) - || !HMAC_Update(hctx, itmp, 4) - || !HMAC_Final(hctx, digtmp, NULL)) { - HMAC_CTX_free(hctx); - HMAC_CTX_free(hctx_tpl); - return 0; - } - HMAC_CTX_reset(hctx); - memcpy(p, digtmp, cplen); - for (j = 1; j < iter; j++) { - if (!HMAC_CTX_copy(hctx, hctx_tpl)) { - HMAC_CTX_free(hctx); - HMAC_CTX_free(hctx_tpl); - return 0; - } - if (!HMAC_Update(hctx, digtmp, mdlen) - || !HMAC_Final(hctx, digtmp, NULL)) { - HMAC_CTX_free(hctx); - HMAC_CTX_free(hctx_tpl); - return 0; - } - HMAC_CTX_reset(hctx); - for (k = 0; k < cplen; k++) - p[k] ^= digtmp[k]; - } - tkeylen -= cplen; - i++; - p += cplen; - } - HMAC_CTX_free(hctx); - HMAC_CTX_free(hctx_tpl); -# ifdef OPENSSL_DEBUG_PKCS5V2 - fprintf(stderr, "Password:\n"); - h__dump(pass, passlen); - fprintf(stderr, "Salt:\n"); - h__dump(salt, saltlen); - fprintf(stderr, "Iteration count %d\n", iter); - fprintf(stderr, "Key:\n"); - h__dump(out, keylen); -# endif - return 1; + if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_PASS, pass, (size_t)passlen) != 1 + || EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SALT, + salt, (size_t)saltlen) != 1 + || EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_ITER, iter) != 1 + || EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MD, digest) != 1 + || EVP_KDF_derive(kctx, out, keylen) != 1) + rv = 0; + + EVP_KDF_CTX_free(kctx); + + OSSL_TRACE_BEGIN(PKCS5V2) { + BIO_printf(trc_out, "Password:\n"); + BIO_hex_string(trc_out, + 0, passlen, pass, passlen); + BIO_printf(trc_out, "\n"); + BIO_printf(trc_out, "Salt:\n"); + BIO_hex_string(trc_out, + 0, saltlen, salt, saltlen); + BIO_printf(trc_out, "\n"); + BIO_printf(trc_out, "Iteration count %d\n", iter); + BIO_printf(trc_out, "Key:\n"); + BIO_hex_string(trc_out, + 0, keylen, out, keylen); + BIO_printf(trc_out, "\n"); + } OSSL_TRACE_END(PKCS5V2); + return rv; } int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen, @@ -129,18 +75,6 @@ int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen, keylen, out); } -# ifdef DO_TEST -main() -{ - unsigned char out[4]; - unsigned char salt[] = { 0x12, 0x34, 0x56, 0x78 }; - PKCS5_PBKDF2_HMAC_SHA1("password", -1, salt, 4, 5, 4, out); - fprintf(stderr, "Out %02X %02X %02X %02X\n", - out[0], out[1], out[2], out[3]); -} - -# endif - /* * Now the key derivation function itself. This is a bit evil because it has * to check the ASN1 parameters are valid: and there are quite a few of @@ -212,7 +146,7 @@ int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, goto err; } keylen = EVP_CIPHER_CTX_key_length(ctx); - OPENSSL_assert(keylen <= sizeof key); + OPENSSL_assert(keylen <= sizeof(key)); /* Decode parameter */ @@ -266,12 +200,3 @@ int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, PBKDF2PARAM_free(kdf); return rv; } - -# ifdef OPENSSL_DEBUG_PKCS5V2 -static void h__dump(const unsigned char *p, int len) -{ - for (; len--; p++) - fprintf(stderr, "%02X ", *p); - fprintf(stderr, "\n"); -} -# endif