Added new EVP/KDF API.

Changed PKEY/KDF API to call the new API.
Added wrappers for PKCS5_PBKDF2_HMAC() and EVP_PBE_scrypt() to call the new EVP KDF APIs.
Documentation updated.

Reviewed-by: Paul Dale <paul.dale@oracle.com>
Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/6674)
This commit is contained in:
David Makepeace 2018-06-22 07:16:18 +10:00 committed by Richard Levitte
parent e0ae0585be
commit 5a285addbf
40 changed files with 3229 additions and 827 deletions

View file

@ -9,6 +9,13 @@
Changes between 1.1.1 and 3.0.0 [xx XXX xxxx]
*) Added EVP_KDF, an EVP layer KDF API, to simplify adding KDF and PRF
implementations. This includes an EVP_PKEY to EVP_KDF bridge for
those algorithms that were already supported through the EVP_PKEY API
(scrypt, TLS1 PRF and HKDF). The low-level KDF functions for PBKDF2
and scrypt are now wrappers that call EVP_KDF.
[David Makepeace]
*) Build devcrypto engine as a dynamic engine.
[Eneas U de Queiroz]

View file

@ -753,6 +753,9 @@ EVP_F_EVP_DIGESTINIT_EX:128:EVP_DigestInit_ex
EVP_F_EVP_ENCRYPTDECRYPTUPDATE:219:evp_EncryptDecryptUpdate
EVP_F_EVP_ENCRYPTFINAL_EX:127:EVP_EncryptFinal_ex
EVP_F_EVP_ENCRYPTUPDATE:167:EVP_EncryptUpdate
EVP_F_EVP_KDF_CTRL:224:EVP_KDF_ctrl
EVP_F_EVP_KDF_CTRL_STR:225:EVP_KDF_ctrl_str
EVP_F_EVP_KDF_CTX_NEW_ID:226:EVP_KDF_CTX_new_id
EVP_F_EVP_MAC_CTRL:209:EVP_MAC_ctrl
EVP_F_EVP_MAC_CTRL_STR:210:EVP_MAC_ctrl_str
EVP_F_EVP_MAC_CTX_COPY:211:EVP_MAC_CTX_copy
@ -823,6 +826,7 @@ EVP_F_PKCS5_PBE_KEYIVGEN:117:PKCS5_PBE_keyivgen
EVP_F_PKCS5_V2_PBE_KEYIVGEN:118:PKCS5_v2_PBE_keyivgen
EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN:164:PKCS5_v2_PBKDF2_keyivgen
EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN:180:PKCS5_v2_scrypt_keyivgen
EVP_F_PKEY_KDF_CTRL:227:pkey_kdf_ctrl
EVP_F_PKEY_MAC_INIT:214:pkey_mac_init
EVP_F_PKEY_SET_TYPE:158:pkey_set_type
EVP_F_POLY1305_CTRL:216:poly1305_ctrl
@ -830,7 +834,25 @@ EVP_F_RC2_MAGIC_TO_METH:109:rc2_magic_to_meth
EVP_F_RC5_CTRL:125:rc5_ctrl
EVP_F_S390X_AES_GCM_CTRL:201:s390x_aes_gcm_ctrl
EVP_F_S390X_AES_GCM_TLS_CIPHER:208:s390x_aes_gcm_tls_cipher
EVP_F_SCRYPT_ALG:228:scrypt_alg
EVP_F_UPDATE:173:update
KDF_F_HKDF_EXTRACT:112:HKDF_Extract
KDF_F_KDF_HKDF_DERIVE:113:kdf_hkdf_derive
KDF_F_KDF_HKDF_NEW:114:kdf_hkdf_new
KDF_F_KDF_HKDF_SIZE:115:kdf_hkdf_size
KDF_F_KDF_MD2CTRL:116:kdf_md2ctrl
KDF_F_KDF_PBKDF2_CTRL_STR:117:kdf_pbkdf2_ctrl_str
KDF_F_KDF_PBKDF2_DERIVE:118:kdf_pbkdf2_derive
KDF_F_KDF_PBKDF2_NEW:119:kdf_pbkdf2_new
KDF_F_KDF_SCRYPT_CTRL_STR:120:kdf_scrypt_ctrl_str
KDF_F_KDF_SCRYPT_CTRL_UINT32:121:kdf_scrypt_ctrl_uint32
KDF_F_KDF_SCRYPT_CTRL_UINT64:122:kdf_scrypt_ctrl_uint64
KDF_F_KDF_SCRYPT_DERIVE:123:kdf_scrypt_derive
KDF_F_KDF_SCRYPT_NEW:124:kdf_scrypt_new
KDF_F_KDF_TLS1_PRF_CTRL_STR:125:kdf_tls1_prf_ctrl_str
KDF_F_KDF_TLS1_PRF_DERIVE:126:kdf_tls1_prf_derive
KDF_F_KDF_TLS1_PRF_NEW:127:kdf_tls1_prf_new
KDF_F_PBKDF2_SET_MEMBUF:128:pbkdf2_set_membuf
KDF_F_PKEY_HKDF_CTRL_STR:103:pkey_hkdf_ctrl_str
KDF_F_PKEY_HKDF_DERIVE:102:pkey_hkdf_derive
KDF_F_PKEY_HKDF_INIT:108:pkey_hkdf_init
@ -842,6 +864,7 @@ KDF_F_PKEY_SCRYPT_SET_MEMBUF:107:pkey_scrypt_set_membuf
KDF_F_PKEY_TLS1_PRF_CTRL_STR:100:pkey_tls1_prf_ctrl_str
KDF_F_PKEY_TLS1_PRF_DERIVE:101:pkey_tls1_prf_derive
KDF_F_PKEY_TLS1_PRF_INIT:110:pkey_tls1_prf_init
KDF_F_SCRYPT_SET_MEMBUF:129:scrypt_set_membuf
KDF_F_TLS1_PRF_ALG:111:tls1_prf_alg
OBJ_F_OBJ_ADD_OBJECT:105:OBJ_add_object
OBJ_F_OBJ_ADD_SIGID:107:OBJ_add_sigid
@ -2284,6 +2307,7 @@ EVP_R_ONLY_ONESHOT_SUPPORTED:177:only oneshot supported
EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE:150:\
operation not supported for this keytype
EVP_R_OPERATON_NOT_INITIALIZED:151:operaton not initialized
EVP_R_PARAMETER_TOO_LARGE:187:parameter too large
EVP_R_PARTIALLY_OVERLAPPING:162:partially overlapping buffers
EVP_R_PBKDF2_ERROR:181:pbkdf2 error
EVP_R_PKEY_APPLICATION_ASN1_METHOD_ALREADY_REGISTERED:179:\
@ -2320,6 +2344,7 @@ KDF_R_MISSING_SEED:106:missing seed
KDF_R_UNKNOWN_PARAMETER_TYPE:103:unknown parameter type
KDF_R_VALUE_ERROR:108:value error
KDF_R_VALUE_MISSING:102:value missing
KDF_R_WRONG_OUTPUT_BUFFER_SIZE:112:wrong output buffer size
OBJ_R_OID_EXISTS:102:oid exists
OBJ_R_UNKNOWN_NID:101:unknown nid
OCSP_R_CERTIFICATE_VERIFY_ERROR:101:certificate verify error

View file

@ -9,7 +9,8 @@ SOURCE[../../libcrypto]=\
p_open.c p_seal.c p_sign.c p_verify.c p_lib.c p_enc.c p_dec.c \
bio_md.c bio_b64.c bio_enc.c evp_err.c e_null.c \
c_allc.c c_alld.c evp_lib.c bio_ok.c \
evp_pkey.c evp_pbe.c p5_crpt.c p5_crpt2.c pbe_scrypt.c \
evp_pkey.c kdf_lib.c evp_pbe.c p5_crpt.c p5_crpt2.c pbe_scrypt.c \
pkey_kdf.c \
e_old.c pmeth_lib.c pmeth_fn.c pmeth_gn.c m_sigver.c \
e_aes_cbc_hmac_sha1.c e_aes_cbc_hmac_sha256.c e_rc4_hmac_md5.c \
e_chacha20_poly1305.c cmeth_lib.c \

View file

@ -14,8 +14,8 @@
# include <openssl/evp.h>
# include <openssl/objects.h>
# include "evp_locl.h"
# include "internal/evp_int.h"
# include "evp_locl.h"
# include "internal/chacha.h"
typedef struct {

View file

@ -11,8 +11,8 @@
#include <limits.h>
#include "internal/cryptlib.h"
#include <openssl/evp.h>
#include "evp_locl.h"
#include "internal/evp_int.h"
#include "evp_locl.h"
static unsigned char conv_ascii2bin(unsigned char a,
const unsigned char *table);

View file

@ -1,6 +1,6 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* 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
@ -60,6 +60,9 @@ static const ERR_STRING_DATA EVP_str_functs[] = {
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_ENCRYPTFINAL_EX, 0),
"EVP_EncryptFinal_ex"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_ENCRYPTUPDATE, 0), "EVP_EncryptUpdate"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_KDF_CTRL, 0), "EVP_KDF_ctrl"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_KDF_CTRL_STR, 0), "EVP_KDF_ctrl_str"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_KDF_CTX_NEW_ID, 0), "EVP_KDF_CTX_new_id"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MAC_CTRL, 0), "EVP_MAC_ctrl"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MAC_CTRL_STR, 0), "EVP_MAC_ctrl_str"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MAC_CTX_COPY, 0), "EVP_MAC_CTX_copy"},
@ -159,6 +162,7 @@ static const ERR_STRING_DATA EVP_str_functs[] = {
"PKCS5_v2_PBKDF2_keyivgen"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN, 0),
"PKCS5_v2_scrypt_keyivgen"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_PKEY_KDF_CTRL, 0), "pkey_kdf_ctrl"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_PKEY_MAC_INIT, 0), "pkey_mac_init"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_PKEY_SET_TYPE, 0), "pkey_set_type"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_POLY1305_CTRL, 0), "poly1305_ctrl"},
@ -167,6 +171,7 @@ static const ERR_STRING_DATA EVP_str_functs[] = {
{ERR_PACK(ERR_LIB_EVP, EVP_F_S390X_AES_GCM_CTRL, 0), "s390x_aes_gcm_ctrl"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_S390X_AES_GCM_TLS_CIPHER, 0),
"s390x_aes_gcm_tls_cipher"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_SCRYPT_ALG, 0), "scrypt_alg"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_UPDATE, 0), "update"},
{0, NULL}
};
@ -254,6 +259,8 @@ static const ERR_STRING_DATA EVP_str_reasons[] = {
"operation not supported for this keytype"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_OPERATON_NOT_INITIALIZED),
"operaton not initialized"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_PARAMETER_TOO_LARGE),
"parameter too large"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_PARTIALLY_OVERLAPPING),
"partially overlapping buffers"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_PBKDF2_ERROR), "pbkdf2 error"},

View file

@ -46,6 +46,11 @@ struct evp_mac_ctx_st {
void *data; /* Individual method data */
} /* EVP_MAC_CTX */;
struct evp_kdf_ctx_st {
const EVP_KDF_METHOD *kmeth;
EVP_KDF_IMPL *impl; /* Algorithm-specific data */
} /* EVP_KDF_CTX */ ;
int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
int passlen, ASN1_TYPE *param,
const EVP_CIPHER *c, const EVP_MD *md,

View file

@ -12,6 +12,7 @@
#include <openssl/evp.h>
#include <openssl/pkcs12.h>
#include <openssl/x509.h>
#include "internal/evp_int.h"
#include "evp_locl.h"
/* Password based encryption (PBE) functions */

165
crypto/evp/kdf_lib.c Normal file
View file

@ -0,0 +1,165 @@
/*
* Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
*
* 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
*/
#include <stdio.h>
#include <stdlib.h>
#include "internal/cryptlib.h"
#include <openssl/engine.h>
#include <openssl/evp.h>
#include <openssl/x509v3.h>
#include <openssl/kdf.h>
#include "internal/asn1_int.h"
#include "internal/evp_int.h"
#include "internal/numbers.h"
#include "evp_locl.h"
typedef int sk_cmp_fn_type(const char *const *a, const char *const *b);
/* This array needs to be in order of NIDs */
static const EVP_KDF_METHOD *standard_methods[] = {
&pbkdf2_kdf_meth,
#ifndef OPENSSL_NO_SCRYPT
&scrypt_kdf_meth,
#endif
&tls1_prf_kdf_meth,
&hkdf_kdf_meth
};
DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_KDF_METHOD *, const EVP_KDF_METHOD *,
kmeth);
static int kmeth_cmp(const EVP_KDF_METHOD *const *a,
const EVP_KDF_METHOD *const *b)
{
return ((*a)->type - (*b)->type);
}
IMPLEMENT_OBJ_BSEARCH_CMP_FN(const EVP_KDF_METHOD *, const EVP_KDF_METHOD *,
kmeth);
static const EVP_KDF_METHOD *kdf_meth_find(int type)
{
EVP_KDF_METHOD tmp;
const EVP_KDF_METHOD *t = &tmp, **ret;
tmp.type = type;
ret = OBJ_bsearch_kmeth(&t, standard_methods,
OSSL_NELEM(standard_methods));
if (ret == NULL || *ret == NULL)
return NULL;
return *ret;
}
EVP_KDF_CTX *EVP_KDF_CTX_new_id(int id)
{
EVP_KDF_CTX *ret;
const EVP_KDF_METHOD *kmeth;
kmeth = kdf_meth_find(id);
if (kmeth == NULL) {
EVPerr(EVP_F_EVP_KDF_CTX_NEW_ID, EVP_R_UNSUPPORTED_ALGORITHM);
return NULL;
}
ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
EVPerr(EVP_F_EVP_KDF_CTX_NEW_ID, ERR_R_MALLOC_FAILURE);
return NULL;
}
if (kmeth->new != NULL && (ret->impl = kmeth->new()) == NULL) {
EVP_KDF_CTX_free(ret);
return NULL;
}
ret->kmeth = kmeth;
return ret;
}
void EVP_KDF_CTX_free(EVP_KDF_CTX *ctx)
{
if (ctx == NULL)
return;
ctx->kmeth->free(ctx->impl);
OPENSSL_free(ctx);
}
void EVP_KDF_reset(EVP_KDF_CTX *ctx)
{
if (ctx == NULL)
return;
if (ctx->kmeth->reset != NULL)
ctx->kmeth->reset(ctx->impl);
}
int EVP_KDF_ctrl(EVP_KDF_CTX *ctx, int cmd, ...)
{
int ret;
va_list args;
va_start(args, cmd);
ret = EVP_KDF_vctrl(ctx, cmd, args);
va_end(args);
if (ret == -2)
EVPerr(EVP_F_EVP_KDF_CTRL, EVP_R_COMMAND_NOT_SUPPORTED);
return ret;
}
int EVP_KDF_vctrl(EVP_KDF_CTX *ctx, int cmd, va_list args)
{
if (ctx == NULL)
return 0;
return ctx->kmeth->ctrl(ctx->impl, cmd, args);
}
int EVP_KDF_ctrl_str(EVP_KDF_CTX *ctx, const char *type, const char *value)
{
int ret;
if (ctx == NULL)
return 0;
if (ctx->kmeth->ctrl_str == NULL) {
EVPerr(EVP_F_EVP_KDF_CTRL_STR, EVP_R_COMMAND_NOT_SUPPORTED);
return -2;
}
ret = ctx->kmeth->ctrl_str(ctx->impl, type, value);
if (ret == -2)
EVPerr(EVP_F_EVP_KDF_CTRL_STR, EVP_R_COMMAND_NOT_SUPPORTED);
return ret;
}
size_t EVP_KDF_size(EVP_KDF_CTX *ctx)
{
if (ctx == NULL)
return 0;
if (ctx->kmeth->size == NULL)
return SIZE_MAX;
return ctx->kmeth->size(ctx->impl);
}
int EVP_KDF_derive(EVP_KDF_CTX *ctx, unsigned char *key, size_t keylen)
{
if (ctx == NULL)
return 0;
return ctx->kmeth->derive(ctx->impl, key, keylen);
}

View file

@ -1,5 +1,5 @@
/*
* Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* 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
@ -10,105 +10,51 @@
#include <stdio.h>
#include <stdlib.h>
#include "internal/cryptlib.h"
# include <openssl/x509.h>
# include <openssl/evp.h>
# include <openssl/hmac.h>
# include "evp_locl.h"
#include <openssl/x509.h>
#include <openssl/evp.h>
#include <openssl/kdf.h>
#include <openssl/hmac.h>
#include "internal/evp_int.h"
#include "evp_locl.h"
/* set this to print out info about the keygen algorithm */
/* #define OPENSSL_DEBUG_PKCS5V2 */
# ifdef 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.
*/
#endif
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)
{
const char *empty = "";
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;
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;
/* Keep documented behaviour. */
if (pass == NULL) {
pass = empty;
passlen = 0;
} else if (passlen == -1) {
passlen = strlen(pass);
}
if (!HMAC_Init_ex(hctx_tpl, pass, passlen, digest, 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;
}
hctx = HMAC_CTX_new();
if (hctx == NULL) {
HMAC_CTX_free(hctx_tpl);
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;
}
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;
}
for (k = 0; k < cplen; k++)
p[k] ^= digtmp[k];
}
tkeylen -= cplen;
i++;
p += cplen;
}
HMAC_CTX_free(hctx);
HMAC_CTX_free(hctx_tpl);
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);
# ifdef OPENSSL_DEBUG_PKCS5V2
fprintf(stderr, "Password:\n");
h__dump(pass, passlen);
@ -118,7 +64,7 @@ int PKCS5_PBKDF2_HMAC(const char *pass, int passlen,
fprintf(stderr, "Key:\n");
h__dump(out, keylen);
# endif
return 1;
return rv;
}
int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen,

View file

@ -7,135 +7,12 @@
* https://www.openssl.org/source/license.html
*/
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include "internal/numbers.h"
#include <openssl/kdf.h>
#ifndef OPENSSL_NO_SCRYPT
#define R(a,b) (((a) << (b)) | ((a) >> (32 - (b))))
static void salsa208_word_specification(uint32_t inout[16])
{
int i;
uint32_t x[16];
memcpy(x, inout, sizeof(x));
for (i = 8; i > 0; i -= 2) {
x[4] ^= R(x[0] + x[12], 7);
x[8] ^= R(x[4] + x[0], 9);
x[12] ^= R(x[8] + x[4], 13);
x[0] ^= R(x[12] + x[8], 18);
x[9] ^= R(x[5] + x[1], 7);
x[13] ^= R(x[9] + x[5], 9);
x[1] ^= R(x[13] + x[9], 13);
x[5] ^= R(x[1] + x[13], 18);
x[14] ^= R(x[10] + x[6], 7);
x[2] ^= R(x[14] + x[10], 9);
x[6] ^= R(x[2] + x[14], 13);
x[10] ^= R(x[6] + x[2], 18);
x[3] ^= R(x[15] + x[11], 7);
x[7] ^= R(x[3] + x[15], 9);
x[11] ^= R(x[7] + x[3], 13);
x[15] ^= R(x[11] + x[7], 18);
x[1] ^= R(x[0] + x[3], 7);
x[2] ^= R(x[1] + x[0], 9);
x[3] ^= R(x[2] + x[1], 13);
x[0] ^= R(x[3] + x[2], 18);
x[6] ^= R(x[5] + x[4], 7);
x[7] ^= R(x[6] + x[5], 9);
x[4] ^= R(x[7] + x[6], 13);
x[5] ^= R(x[4] + x[7], 18);
x[11] ^= R(x[10] + x[9], 7);
x[8] ^= R(x[11] + x[10], 9);
x[9] ^= R(x[8] + x[11], 13);
x[10] ^= R(x[9] + x[8], 18);
x[12] ^= R(x[15] + x[14], 7);
x[13] ^= R(x[12] + x[15], 9);
x[14] ^= R(x[13] + x[12], 13);
x[15] ^= R(x[14] + x[13], 18);
}
for (i = 0; i < 16; ++i)
inout[i] += x[i];
OPENSSL_cleanse(x, sizeof(x));
}
static void scryptBlockMix(uint32_t *B_, uint32_t *B, uint64_t r)
{
uint64_t i, j;
uint32_t X[16], *pB;
memcpy(X, B + (r * 2 - 1) * 16, sizeof(X));
pB = B;
for (i = 0; i < r * 2; i++) {
for (j = 0; j < 16; j++)
X[j] ^= *pB++;
salsa208_word_specification(X);
memcpy(B_ + (i / 2 + (i & 1) * r) * 16, X, sizeof(X));
}
OPENSSL_cleanse(X, sizeof(X));
}
static void scryptROMix(unsigned char *B, uint64_t r, uint64_t N,
uint32_t *X, uint32_t *T, uint32_t *V)
{
unsigned char *pB;
uint32_t *pV;
uint64_t i, k;
/* Convert from little endian input */
for (pV = V, i = 0, pB = B; i < 32 * r; i++, pV++) {
*pV = *pB++;
*pV |= *pB++ << 8;
*pV |= *pB++ << 16;
*pV |= (uint32_t)*pB++ << 24;
}
for (i = 1; i < N; i++, pV += 32 * r)
scryptBlockMix(pV, pV - 32 * r, r);
scryptBlockMix(X, V + (N - 1) * 32 * r, r);
for (i = 0; i < N; i++) {
uint32_t j;
j = X[16 * (2 * r - 1)] % N;
pV = V + 32 * r * j;
for (k = 0; k < 32 * r; k++)
T[k] = X[k] ^ *pV++;
scryptBlockMix(X, T, r);
}
/* Convert output to little endian */
for (i = 0, pB = B; i < 32 * r; i++) {
uint32_t xtmp = X[i];
*pB++ = xtmp & 0xff;
*pB++ = (xtmp >> 8) & 0xff;
*pB++ = (xtmp >> 16) & 0xff;
*pB++ = (xtmp >> 24) & 0xff;
}
}
#ifndef SIZE_MAX
# define SIZE_MAX ((size_t)-1)
#endif
/*
* Maximum power of two that will fit in uint64_t: this should work on
* most (all?) platforms.
*/
#define LOG2_UINT64_MAX (sizeof(uint64_t) * 8 - 1)
/*
* Maximum value of p * r:
* p <= ((2^32-1) * hLen) / MFLen =>
* p <= ((2^32-1) * 32) / (128 * r) =>
* p * r <= (2^30-1)
*
*/
#define SCRYPT_PR_MAX ((1 << 30) - 1)
/*
* Maximum permitted memory allow this to be overridden with Configuration
* option: e.g. -DSCRYPT_MAX_MEM=0 for maximum possible.
@ -160,107 +37,38 @@ int EVP_PBE_scrypt(const char *pass, size_t passlen,
uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem,
unsigned char *key, size_t keylen)
{
int rv = 0;
unsigned char *B;
uint32_t *X, *V, *T;
uint64_t i, Blen, Vlen;
const char *empty = "";
int rv = 1;
EVP_KDF_CTX *kctx;
/* Sanity check parameters */
/* initial check, r,p must be non zero, N >= 2 and a power of 2 */
if (r == 0 || p == 0 || N < 2 || (N & (N - 1)))
return 0;
/* Check p * r < SCRYPT_PR_MAX avoiding overflow */
if (p > SCRYPT_PR_MAX / r) {
EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_MEMORY_LIMIT_EXCEEDED);
return 0;
/* Maintain existing behaviour. */
if (pass == NULL) {
pass = empty;
passlen = 0;
}
/*
* Need to check N: if 2^(128 * r / 8) overflows limit this is
* automatically satisfied since N <= UINT64_MAX.
*/
if (16 * r <= LOG2_UINT64_MAX) {
if (N >= (((uint64_t)1) << (16 * r))) {
EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_MEMORY_LIMIT_EXCEEDED);
return 0;
}
}
/* Memory checks: check total allocated buffer size fits in uint64_t */
/*
* B size in section 5 step 1.S
* Note: we know p * 128 * r < UINT64_MAX because we already checked
* p * r < SCRYPT_PR_MAX
*/
Blen = p * 128 * r;
/*
* Yet we pass it as integer to PKCS5_PBKDF2_HMAC... [This would
* have to be revised when/if PKCS5_PBKDF2_HMAC accepts size_t.]
*/
if (Blen > INT_MAX) {
EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_MEMORY_LIMIT_EXCEEDED);
return 0;
}
/*
* Check 32 * r * (N + 2) * sizeof(uint32_t) fits in uint64_t
* This is combined size V, X and T (section 4)
*/
i = UINT64_MAX / (32 * sizeof(uint32_t));
if (N + 2 > i / r) {
EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_MEMORY_LIMIT_EXCEEDED);
return 0;
}
Vlen = 32 * r * (N + 2) * sizeof(uint32_t);
/* check total allocated size fits in uint64_t */
if (Blen > UINT64_MAX - Vlen) {
EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_MEMORY_LIMIT_EXCEEDED);
return 0;
}
if (maxmem == 0)
maxmem = SCRYPT_MAX_MEM;
/* Check that the maximum memory doesn't exceed a size_t limits */
if (maxmem > SIZE_MAX)
maxmem = SIZE_MAX;
kctx = EVP_KDF_CTX_new_id(EVP_KDF_SCRYPT);
if (kctx == NULL)
return 0;
if (Blen + Vlen > maxmem) {
EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_MEMORY_LIMIT_EXCEEDED);
if (r > UINT32_MAX || p > UINT32_MAX) {
EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_PARAMETER_TOO_LARGE);
return 0;
}
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_SCRYPT_N, N) != 1
|| EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SCRYPT_R, (uint32_t)r) != 1
|| EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SCRYPT_P, (uint32_t)p) != 1
|| EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MAXMEM_BYTES, maxmem) != 1
|| EVP_KDF_derive(kctx, key, keylen) != 1)
rv = 0;
/* If no key return to indicate parameters are OK */
if (key == NULL)
return 1;
B = OPENSSL_malloc((size_t)(Blen + Vlen));
if (B == NULL) {
EVPerr(EVP_F_EVP_PBE_SCRYPT, ERR_R_MALLOC_FAILURE);
return 0;
}
X = (uint32_t *)(B + Blen);
T = X + 32 * r;
V = T + 32 * r;
if (PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, 1, EVP_sha256(),
(int)Blen, B) == 0)
goto err;
for (i = 0; i < p; i++)
scryptROMix(B + 128 * r * i, r, N, X, T, V);
if (PKCS5_PBKDF2_HMAC(pass, passlen, B, (int)Blen, 1, EVP_sha256(),
keylen, key) == 0)
goto err;
rv = 1;
err:
if (rv == 0)
EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_PBKDF2_ERROR);
OPENSSL_clear_free(B, (size_t)(Blen + Vlen));
EVP_KDF_CTX_free(kctx);
return rv;
}
#endif

255
crypto/evp/pkey_kdf.c Normal file
View file

@ -0,0 +1,255 @@
/*
* Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
*
* 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
*/
#include <string.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/kdf.h>
#include "internal/evp_int.h"
static int pkey_kdf_init(EVP_PKEY_CTX *ctx)
{
EVP_KDF_CTX *kctx;
kctx = EVP_KDF_CTX_new_id(ctx->pmeth->pkey_id);
if (kctx == NULL)
return 0;
ctx->data = kctx;
return 1;
}
static void pkey_kdf_cleanup(EVP_PKEY_CTX *ctx)
{
EVP_KDF_CTX *kctx = ctx->data;
EVP_KDF_CTX_free(kctx);
}
static int pkey_kdf_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
{
EVP_KDF_CTX *kctx = ctx->data;
uint64_t u64_value;
int cmd;
int ret;
switch (type) {
case EVP_PKEY_CTRL_PASS:
cmd = EVP_KDF_CTRL_SET_PASS;
break;
case EVP_PKEY_CTRL_HKDF_SALT:
case EVP_PKEY_CTRL_SCRYPT_SALT:
cmd = EVP_KDF_CTRL_SET_SALT;
break;
case EVP_PKEY_CTRL_TLS_MD:
case EVP_PKEY_CTRL_HKDF_MD:
cmd = EVP_KDF_CTRL_SET_MD;
break;
case EVP_PKEY_CTRL_TLS_SECRET:
cmd = EVP_KDF_CTRL_SET_TLS_SECRET;
ret = EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_RESET_TLS_SEED);
if (ret < 1)
return ret;
break;
case EVP_PKEY_CTRL_TLS_SEED:
cmd = EVP_KDF_CTRL_ADD_TLS_SEED;
break;
case EVP_PKEY_CTRL_HKDF_KEY:
cmd = EVP_KDF_CTRL_SET_KEY;
break;
case EVP_PKEY_CTRL_HKDF_INFO:
cmd = EVP_KDF_CTRL_ADD_HKDF_INFO;
break;
case EVP_PKEY_CTRL_HKDF_MODE:
cmd = EVP_KDF_CTRL_SET_HKDF_MODE;
break;
case EVP_PKEY_CTRL_SCRYPT_N:
cmd = EVP_KDF_CTRL_SET_SCRYPT_N;
break;
case EVP_PKEY_CTRL_SCRYPT_R:
cmd = EVP_KDF_CTRL_SET_SCRYPT_R;
break;
case EVP_PKEY_CTRL_SCRYPT_P:
cmd = EVP_KDF_CTRL_SET_SCRYPT_P;
break;
case EVP_PKEY_CTRL_SCRYPT_MAXMEM_BYTES:
cmd = EVP_KDF_CTRL_SET_MAXMEM_BYTES;
break;
default:
return -2;
}
switch (cmd) {
case EVP_KDF_CTRL_SET_PASS:
case EVP_KDF_CTRL_SET_SALT:
case EVP_KDF_CTRL_SET_KEY:
case EVP_KDF_CTRL_SET_TLS_SECRET:
case EVP_KDF_CTRL_ADD_TLS_SEED:
case EVP_KDF_CTRL_ADD_HKDF_INFO:
return EVP_KDF_ctrl(kctx, cmd, (const unsigned char *)p2, (size_t)p1);
case EVP_KDF_CTRL_SET_MD:
return EVP_KDF_ctrl(kctx, cmd, (const EVP_MD *)p2);
case EVP_KDF_CTRL_SET_HKDF_MODE:
return EVP_KDF_ctrl(kctx, cmd, (int)p1);
case EVP_KDF_CTRL_SET_SCRYPT_R:
case EVP_KDF_CTRL_SET_SCRYPT_P:
u64_value = *(uint64_t *)p2;
if (u64_value > UINT32_MAX) {
EVPerr(EVP_F_PKEY_KDF_CTRL, EVP_R_PARAMETER_TOO_LARGE);
return 0;
}
return EVP_KDF_ctrl(kctx, cmd, (uint32_t)u64_value);
case EVP_KDF_CTRL_SET_SCRYPT_N:
case EVP_KDF_CTRL_SET_MAXMEM_BYTES:
return EVP_KDF_ctrl(kctx, cmd, *(uint64_t *)p2);
default:
return 0;
}
}
static int pkey_kdf_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
const char *value)
{
EVP_KDF_CTX *kctx = ctx->data;
if (strcmp(type, "md") == 0)
return EVP_KDF_ctrl_str(kctx, "digest", value);
return EVP_KDF_ctrl_str(kctx, type, value);
}
static int pkey_kdf_derive_init(EVP_PKEY_CTX *ctx)
{
EVP_KDF_CTX *kctx = ctx->data;
EVP_KDF_reset(kctx);
return 1;
}
/*
* For fixed-output algorithms the keylen parameter is an "out" parameter
* otherwise it is an "in" parameter.
*/
static int pkey_kdf_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
size_t *keylen)
{
EVP_KDF_CTX *kctx = ctx->data;
size_t outlen = EVP_KDF_size(kctx);
if (outlen == 0 || outlen == SIZE_MAX) {
/* Variable-output algorithm */
if (key == NULL)
return 0;
} else {
/* Fixed-output algorithm */
*keylen = outlen;
if (key == NULL)
return 1;
}
return EVP_KDF_derive(kctx, key, *keylen);
}
#ifndef OPENSSL_NO_SCRYPT
const EVP_PKEY_METHOD scrypt_pkey_meth = {
EVP_PKEY_SCRYPT,
0,
pkey_kdf_init,
0,
pkey_kdf_cleanup,
0, 0,
0, 0,
0,
0,
0,
0,
0, 0,
0, 0, 0, 0,
0, 0,
0, 0,
pkey_kdf_derive_init,
pkey_kdf_derive,
pkey_kdf_ctrl,
pkey_kdf_ctrl_str
};
#endif
const EVP_PKEY_METHOD tls1_prf_pkey_meth = {
EVP_PKEY_TLS1_PRF,
0,
pkey_kdf_init,
0,
pkey_kdf_cleanup,
0, 0,
0, 0,
0,
0,
0,
0,
0, 0,
0, 0, 0, 0,
0, 0,
0, 0,
pkey_kdf_derive_init,
pkey_kdf_derive,
pkey_kdf_ctrl,
pkey_kdf_ctrl_str
};
const EVP_PKEY_METHOD hkdf_pkey_meth = {
EVP_PKEY_HKDF,
0,
pkey_kdf_init,
0,
pkey_kdf_cleanup,
0, 0,
0, 0,
0,
0,
0,
0,
0, 0,
0, 0, 0, 0,
0, 0,
0, 0,
pkey_kdf_derive_init,
pkey_kdf_derive,
pkey_kdf_ctrl,
pkey_kdf_ctrl_str
};

View file

@ -151,6 +151,24 @@ const EVP_MD *evp_keccak_kmac256(void);
*/
int EVP_add_mac(const EVP_MAC *mac);
/* struct evp_kdf_impl_st is defined by the implementation */
typedef struct evp_kdf_impl_st EVP_KDF_IMPL;
typedef struct {
int type;
EVP_KDF_IMPL *(*new) (void);
void (*free) (EVP_KDF_IMPL *impl);
void (*reset) (EVP_KDF_IMPL *impl);
int (*ctrl) (EVP_KDF_IMPL *impl, int cmd, va_list args);
int (*ctrl_str) (EVP_KDF_IMPL *impl, const char *type, const char *value);
size_t (*size) (EVP_KDF_IMPL *impl);
int (*derive) (EVP_KDF_IMPL *impl, unsigned char *key, size_t keylen);
} EVP_KDF_METHOD;
extern const EVP_KDF_METHOD pbkdf2_kdf_meth;
extern const EVP_KDF_METHOD scrypt_kdf_meth;
extern const EVP_KDF_METHOD tls1_prf_kdf_meth;
extern const EVP_KDF_METHOD hkdf_kdf_meth;
struct evp_md_st {
int type;
int pkey_type;

View file

@ -1,3 +1,3 @@
LIBS=../../libcrypto
SOURCE[../../libcrypto]=\
tls1_prf.c kdf_err.c hkdf.c scrypt.c
tls1_prf.c kdf_err.c kdf_util.c hkdf.c scrypt.c pbkdf2.c

View file

@ -8,32 +8,33 @@
*/
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <openssl/hmac.h>
#include <openssl/kdf.h>
#include <openssl/evp.h>
#include <openssl/kdf.h>
#include "internal/cryptlib.h"
#include "internal/evp_int.h"
#include "kdf_local.h"
#define HKDF_MAXBUF 1024
static unsigned char *HKDF(const EVP_MD *evp_md,
const unsigned char *salt, size_t salt_len,
const unsigned char *key, size_t key_len,
const unsigned char *info, size_t info_len,
unsigned char *okm, size_t okm_len);
static void kdf_hkdf_reset(EVP_KDF_IMPL *impl);
static int HKDF(const EVP_MD *evp_md,
const unsigned char *salt, size_t salt_len,
const unsigned char *key, size_t key_len,
const unsigned char *info, size_t info_len,
unsigned char *okm, size_t okm_len);
static int HKDF_Extract(const EVP_MD *evp_md,
const unsigned char *salt, size_t salt_len,
const unsigned char *key, size_t key_len,
unsigned char *prk, size_t prk_len);
static int HKDF_Expand(const EVP_MD *evp_md,
const unsigned char *prk, size_t prk_len,
const unsigned char *info, size_t info_len,
unsigned char *okm, size_t okm_len);
static unsigned char *HKDF_Extract(const EVP_MD *evp_md,
const unsigned char *salt, size_t salt_len,
const unsigned char *key, size_t key_len,
unsigned char *prk, size_t *prk_len);
static unsigned char *HKDF_Expand(const EVP_MD *evp_md,
const unsigned char *prk, size_t prk_len,
const unsigned char *info, size_t info_len,
unsigned char *okm, size_t okm_len);
typedef struct {
struct evp_kdf_impl_st {
int mode;
const EVP_MD *md;
unsigned char *salt;
@ -42,230 +43,208 @@ typedef struct {
size_t key_len;
unsigned char info[HKDF_MAXBUF];
size_t info_len;
} HKDF_PKEY_CTX;
};
static int pkey_hkdf_init(EVP_PKEY_CTX *ctx)
static EVP_KDF_IMPL *kdf_hkdf_new(void)
{
HKDF_PKEY_CTX *kctx;
EVP_KDF_IMPL *impl;
if ((kctx = OPENSSL_zalloc(sizeof(*kctx))) == NULL) {
KDFerr(KDF_F_PKEY_HKDF_INIT, ERR_R_MALLOC_FAILURE);
return 0;
}
ctx->data = kctx;
return 1;
if ((impl = OPENSSL_zalloc(sizeof(*impl))) == NULL)
KDFerr(KDF_F_KDF_HKDF_NEW, ERR_R_MALLOC_FAILURE);
return impl;
}
static void pkey_hkdf_cleanup(EVP_PKEY_CTX *ctx)
static void kdf_hkdf_free(EVP_KDF_IMPL *impl)
{
HKDF_PKEY_CTX *kctx = ctx->data;
OPENSSL_clear_free(kctx->salt, kctx->salt_len);
OPENSSL_clear_free(kctx->key, kctx->key_len);
OPENSSL_cleanse(kctx->info, kctx->info_len);
OPENSSL_free(kctx);
kdf_hkdf_reset(impl);
OPENSSL_free(impl);
}
static int pkey_hkdf_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
static void kdf_hkdf_reset(EVP_KDF_IMPL *impl)
{
HKDF_PKEY_CTX *kctx = ctx->data;
OPENSSL_free(impl->salt);
OPENSSL_clear_free(impl->key, impl->key_len);
OPENSSL_cleanse(impl->info, impl->info_len);
memset(impl, 0, sizeof(*impl));
}
switch (type) {
case EVP_PKEY_CTRL_HKDF_MD:
if (p2 == NULL)
static int kdf_hkdf_ctrl(EVP_KDF_IMPL *impl, int cmd, va_list args)
{
const unsigned char *p;
size_t len;
const EVP_MD *md;
switch (cmd) {
case EVP_KDF_CTRL_SET_MD:
md = va_arg(args, const EVP_MD *);
if (md == NULL)
return 0;
kctx->md = p2;
impl->md = md;
return 1;
case EVP_PKEY_CTRL_HKDF_MODE:
kctx->mode = p1;
case EVP_KDF_CTRL_SET_HKDF_MODE:
impl->mode = va_arg(args, int);
return 1;
case EVP_PKEY_CTRL_HKDF_SALT:
if (p1 == 0 || p2 == NULL)
case EVP_KDF_CTRL_SET_SALT:
p = va_arg(args, const unsigned char *);
len = va_arg(args, size_t);
if (len == 0 || p == NULL)
return 1;
if (p1 < 0)
OPENSSL_free(impl->salt);
impl->salt = OPENSSL_memdup(p, len);
if (impl->salt == NULL)
return 0;
if (kctx->salt != NULL)
OPENSSL_clear_free(kctx->salt, kctx->salt_len);
kctx->salt = OPENSSL_memdup(p2, p1);
if (kctx->salt == NULL)
return 0;
kctx->salt_len = p1;
impl->salt_len = len;
return 1;
case EVP_PKEY_CTRL_HKDF_KEY:
if (p1 < 0)
case EVP_KDF_CTRL_SET_KEY:
p = va_arg(args, const unsigned char *);
len = va_arg(args, size_t);
OPENSSL_clear_free(impl->key, impl->key_len);
impl->key = OPENSSL_memdup(p, len);
if (impl->key == NULL)
return 0;
if (kctx->key != NULL)
OPENSSL_clear_free(kctx->key, kctx->key_len);
kctx->key = OPENSSL_memdup(p2, p1);
if (kctx->key == NULL)
return 0;
kctx->key_len = p1;
impl->key_len = len;
return 1;
case EVP_PKEY_CTRL_HKDF_INFO:
if (p1 == 0 || p2 == NULL)
case EVP_KDF_CTRL_RESET_HKDF_INFO:
OPENSSL_cleanse(impl->info, impl->info_len);
impl->info_len = 0;
return 1;
case EVP_KDF_CTRL_ADD_HKDF_INFO:
p = va_arg(args, const unsigned char *);
len = va_arg(args, size_t);
if (len == 0 || p == NULL)
return 1;
if (p1 < 0 || p1 > (int)(HKDF_MAXBUF - kctx->info_len))
if (len > (HKDF_MAXBUF - impl->info_len))
return 0;
memcpy(kctx->info + kctx->info_len, p2, p1);
kctx->info_len += p1;
memcpy(impl->info + impl->info_len, p, len);
impl->info_len += len;
return 1;
default:
return -2;
}
}
static int pkey_hkdf_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
const char *value)
static int kdf_hkdf_ctrl_str(EVP_KDF_IMPL *impl, const char *type,
const char *value)
{
if (strcmp(type, "mode") == 0) {
int mode;
if (strcmp(value, "EXTRACT_AND_EXPAND") == 0)
mode = EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND;
mode = EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND;
else if (strcmp(value, "EXTRACT_ONLY") == 0)
mode = EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY;
mode = EVP_KDF_HKDF_MODE_EXTRACT_ONLY;
else if (strcmp(value, "EXPAND_ONLY") == 0)
mode = EVP_PKEY_HKDEF_MODE_EXPAND_ONLY;
mode = EVP_KDF_HKDF_MODE_EXPAND_ONLY;
else
return 0;
return EVP_PKEY_CTX_hkdf_mode(ctx, mode);
return call_ctrl(kdf_hkdf_ctrl, impl, EVP_KDF_CTRL_SET_HKDF_MODE, mode);
}
if (strcmp(type, "md") == 0)
return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_DERIVE,
EVP_PKEY_CTRL_HKDF_MD, value);
if (strcmp(type, "digest") == 0)
return kdf_md2ctrl(impl, kdf_hkdf_ctrl, EVP_KDF_CTRL_SET_MD, value);
if (strcmp(type, "salt") == 0)
return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_HKDF_SALT, value);
return kdf_str2ctrl(impl, kdf_hkdf_ctrl, EVP_KDF_CTRL_SET_SALT, value);
if (strcmp(type, "hexsalt") == 0)
return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_HKDF_SALT, value);
return kdf_hex2ctrl(impl, kdf_hkdf_ctrl, EVP_KDF_CTRL_SET_SALT, value);
if (strcmp(type, "key") == 0)
return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_HKDF_KEY, value);
return kdf_str2ctrl(impl, kdf_hkdf_ctrl, EVP_KDF_CTRL_SET_KEY, value);
if (strcmp(type, "hexkey") == 0)
return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_HKDF_KEY, value);
return kdf_hex2ctrl(impl, kdf_hkdf_ctrl, EVP_KDF_CTRL_SET_KEY, value);
if (strcmp(type, "info") == 0)
return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_HKDF_INFO, value);
return kdf_str2ctrl(impl, kdf_hkdf_ctrl, EVP_KDF_CTRL_ADD_HKDF_INFO,
value);
if (strcmp(type, "hexinfo") == 0)
return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_HKDF_INFO, value);
return kdf_hex2ctrl(impl, kdf_hkdf_ctrl, EVP_KDF_CTRL_ADD_HKDF_INFO,
value);
KDFerr(KDF_F_PKEY_HKDF_CTRL_STR, KDF_R_UNKNOWN_PARAMETER_TYPE);
return -2;
}
static int pkey_hkdf_derive_init(EVP_PKEY_CTX *ctx)
static size_t kdf_hkdf_size(EVP_KDF_IMPL *impl)
{
HKDF_PKEY_CTX *kctx = ctx->data;
if (impl->mode != EVP_KDF_HKDF_MODE_EXTRACT_ONLY)
return SIZE_MAX;
OPENSSL_clear_free(kctx->key, kctx->key_len);
OPENSSL_clear_free(kctx->salt, kctx->salt_len);
OPENSSL_cleanse(kctx->info, kctx->info_len);
memset(kctx, 0, sizeof(*kctx));
return 1;
if (impl->md == NULL) {
KDFerr(KDF_F_KDF_HKDF_SIZE, KDF_R_MISSING_MESSAGE_DIGEST);
return 0;
}
return EVP_MD_size(impl->md);
}
static int pkey_hkdf_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
size_t *keylen)
static int kdf_hkdf_derive(EVP_KDF_IMPL *impl, unsigned char *key,
size_t keylen)
{
HKDF_PKEY_CTX *kctx = ctx->data;
if (kctx->md == NULL) {
KDFerr(KDF_F_PKEY_HKDF_DERIVE, KDF_R_MISSING_MESSAGE_DIGEST);
if (impl->md == NULL) {
KDFerr(KDF_F_KDF_HKDF_DERIVE, KDF_R_MISSING_MESSAGE_DIGEST);
return 0;
}
if (kctx->key == NULL) {
KDFerr(KDF_F_PKEY_HKDF_DERIVE, KDF_R_MISSING_KEY);
if (impl->key == NULL) {
KDFerr(KDF_F_KDF_HKDF_DERIVE, KDF_R_MISSING_KEY);
return 0;
}
switch (kctx->mode) {
case EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND:
return HKDF(kctx->md, kctx->salt, kctx->salt_len, kctx->key,
kctx->key_len, kctx->info, kctx->info_len, key,
*keylen) != NULL;
switch (impl->mode) {
case EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND:
return HKDF(impl->md, impl->salt, impl->salt_len, impl->key,
impl->key_len, impl->info, impl->info_len, key,
keylen);
case EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY:
if (key == NULL) {
*keylen = EVP_MD_size(kctx->md);
return 1;
}
return HKDF_Extract(kctx->md, kctx->salt, kctx->salt_len, kctx->key,
kctx->key_len, key, keylen) != NULL;
case EVP_KDF_HKDF_MODE_EXTRACT_ONLY:
return HKDF_Extract(impl->md, impl->salt, impl->salt_len, impl->key,
impl->key_len, key, keylen);
case EVP_PKEY_HKDEF_MODE_EXPAND_ONLY:
return HKDF_Expand(kctx->md, kctx->key, kctx->key_len, kctx->info,
kctx->info_len, key, *keylen) != NULL;
case EVP_KDF_HKDF_MODE_EXPAND_ONLY:
return HKDF_Expand(impl->md, impl->key, impl->key_len, impl->info,
impl->info_len, key, keylen);
default:
return 0;
}
}
const EVP_PKEY_METHOD hkdf_pkey_meth = {
EVP_PKEY_HKDF,
0,
pkey_hkdf_init,
0,
pkey_hkdf_cleanup,
0, 0,
0, 0,
0,
0,
0,
0,
0, 0,
0, 0, 0, 0,
0, 0,
0, 0,
pkey_hkdf_derive_init,
pkey_hkdf_derive,
pkey_hkdf_ctrl,
pkey_hkdf_ctrl_str
const EVP_KDF_METHOD hkdf_kdf_meth = {
EVP_KDF_HKDF,
kdf_hkdf_new,
kdf_hkdf_free,
kdf_hkdf_reset,
kdf_hkdf_ctrl,
kdf_hkdf_ctrl_str,
kdf_hkdf_size,
kdf_hkdf_derive
};
static unsigned char *HKDF(const EVP_MD *evp_md,
const unsigned char *salt, size_t salt_len,
const unsigned char *key, size_t key_len,
const unsigned char *info, size_t info_len,
unsigned char *okm, size_t okm_len)
static int HKDF(const EVP_MD *evp_md,
const unsigned char *salt, size_t salt_len,
const unsigned char *key, size_t key_len,
const unsigned char *info, size_t info_len,
unsigned char *okm, size_t okm_len)
{
unsigned char prk[EVP_MAX_MD_SIZE];
unsigned char *ret;
size_t prk_len;
int ret;
size_t prk_len = EVP_MD_size(evp_md);
if (!HKDF_Extract(evp_md, salt, salt_len, key, key_len, prk, &prk_len))
return NULL;
if (!HKDF_Extract(evp_md, salt, salt_len, key, key_len, prk, prk_len))
return 0;
ret = HKDF_Expand(evp_md, prk, prk_len, info, info_len, okm, okm_len);
OPENSSL_cleanse(prk, sizeof(prk));
@ -273,43 +252,38 @@ static unsigned char *HKDF(const EVP_MD *evp_md,
return ret;
}
static unsigned char *HKDF_Extract(const EVP_MD *evp_md,
const unsigned char *salt, size_t salt_len,
const unsigned char *key, size_t key_len,
unsigned char *prk, size_t *prk_len)
static int HKDF_Extract(const EVP_MD *evp_md,
const unsigned char *salt, size_t salt_len,
const unsigned char *key, size_t key_len,
unsigned char *prk, size_t prk_len)
{
unsigned int tmp_len;
if (!HMAC(evp_md, salt, salt_len, key, key_len, prk, &tmp_len))
return NULL;
*prk_len = tmp_len;
return prk;
if (prk_len != (size_t)EVP_MD_size(evp_md)) {
KDFerr(KDF_F_HKDF_EXTRACT, KDF_R_WRONG_OUTPUT_BUFFER_SIZE);
return 0;
}
return HMAC(evp_md, salt, salt_len, key, key_len, prk, NULL) != NULL;
}
static unsigned char *HKDF_Expand(const EVP_MD *evp_md,
const unsigned char *prk, size_t prk_len,
const unsigned char *info, size_t info_len,
unsigned char *okm, size_t okm_len)
static int HKDF_Expand(const EVP_MD *evp_md,
const unsigned char *prk, size_t prk_len,
const unsigned char *info, size_t info_len,
unsigned char *okm, size_t okm_len)
{
HMAC_CTX *hmac;
unsigned char *ret = NULL;
int ret = 0;
unsigned int i;
unsigned char prev[EVP_MAX_MD_SIZE];
size_t done_len = 0, dig_len = EVP_MD_size(evp_md);
size_t n = okm_len / dig_len;
if (okm_len % dig_len)
n++;
if (n > 255 || okm == NULL)
return NULL;
return 0;
if ((hmac = HMAC_CTX_new()) == NULL)
return NULL;
return 0;
if (!HMAC_Init_ex(hmac, prk, prk_len, evp_md, NULL))
goto err;
@ -343,7 +317,7 @@ static unsigned char *HKDF_Expand(const EVP_MD *evp_md,
done_len += copy_len;
}
ret = okm;
ret = 1;
err:
OPENSSL_cleanse(prev, sizeof(prev));

View file

@ -1,6 +1,6 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* 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
@ -14,6 +14,29 @@
#ifndef OPENSSL_NO_ERR
static const ERR_STRING_DATA KDF_str_functs[] = {
{ERR_PACK(ERR_LIB_KDF, KDF_F_HKDF_EXTRACT, 0), "HKDF_Extract"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_HKDF_DERIVE, 0), "kdf_hkdf_derive"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_HKDF_NEW, 0), "kdf_hkdf_new"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_HKDF_SIZE, 0), "kdf_hkdf_size"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_MD2CTRL, 0), "kdf_md2ctrl"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_PBKDF2_CTRL_STR, 0),
"kdf_pbkdf2_ctrl_str"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_PBKDF2_DERIVE, 0), "kdf_pbkdf2_derive"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_PBKDF2_NEW, 0), "kdf_pbkdf2_new"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_SCRYPT_CTRL_STR, 0),
"kdf_scrypt_ctrl_str"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_SCRYPT_CTRL_UINT32, 0),
"kdf_scrypt_ctrl_uint32"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_SCRYPT_CTRL_UINT64, 0),
"kdf_scrypt_ctrl_uint64"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_SCRYPT_DERIVE, 0), "kdf_scrypt_derive"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_SCRYPT_NEW, 0), "kdf_scrypt_new"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_TLS1_PRF_CTRL_STR, 0),
"kdf_tls1_prf_ctrl_str"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_TLS1_PRF_DERIVE, 0),
"kdf_tls1_prf_derive"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_TLS1_PRF_NEW, 0), "kdf_tls1_prf_new"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_PBKDF2_SET_MEMBUF, 0), "pbkdf2_set_membuf"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_HKDF_CTRL_STR, 0), "pkey_hkdf_ctrl_str"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_HKDF_DERIVE, 0), "pkey_hkdf_derive"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_HKDF_INIT, 0), "pkey_hkdf_init"},
@ -30,6 +53,7 @@ static const ERR_STRING_DATA KDF_str_functs[] = {
{ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_TLS1_PRF_DERIVE, 0),
"pkey_tls1_prf_derive"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_TLS1_PRF_INIT, 0), "pkey_tls1_prf_init"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_SCRYPT_SET_MEMBUF, 0), "scrypt_set_membuf"},
{ERR_PACK(ERR_LIB_KDF, KDF_F_TLS1_PRF_ALG, 0), "tls1_prf_alg"},
{0, NULL}
};
@ -50,6 +74,8 @@ static const ERR_STRING_DATA KDF_str_reasons[] = {
"unknown parameter type"},
{ERR_PACK(ERR_LIB_KDF, 0, KDF_R_VALUE_ERROR), "value error"},
{ERR_PACK(ERR_LIB_KDF, 0, KDF_R_VALUE_MISSING), "value missing"},
{ERR_PACK(ERR_LIB_KDF, 0, KDF_R_WRONG_OUTPUT_BUFFER_SIZE),
"wrong output buffer size"},
{0, NULL}
};

22
crypto/kdf/kdf_local.h Normal file
View file

@ -0,0 +1,22 @@
/*
* Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
*
* 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
*/
int call_ctrl(int (*ctrl)(EVP_KDF_IMPL *impl, int cmd, va_list args),
EVP_KDF_IMPL *impl, int cmd, ...);
int kdf_str2ctrl(EVP_KDF_IMPL *impl,
int (*ctrl)(EVP_KDF_IMPL *impl, int cmd, va_list args),
int cmd, const char *str);
int kdf_hex2ctrl(EVP_KDF_IMPL *impl,
int (*ctrl)(EVP_KDF_IMPL *impl, int cmd, va_list args),
int cmd, const char *hex);
int kdf_md2ctrl(EVP_KDF_IMPL *impl,
int (*ctrl)(EVP_KDF_IMPL *impl, int cmd, va_list args),
int cmd, const char *md_name);

73
crypto/kdf/kdf_util.c Normal file
View file

@ -0,0 +1,73 @@
/*
* Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
*
* 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
*/
#include <string.h>
#include <stdarg.h>
#include <openssl/kdf.h>
#include <openssl/evp.h>
#include "internal/cryptlib.h"
#include "internal/evp_int.h"
#include "internal/numbers.h"
#include "kdf_local.h"
int call_ctrl(int (*ctrl)(EVP_KDF_IMPL *impl, int cmd, va_list args),
EVP_KDF_IMPL *impl, int cmd, ...)
{
int ret;
va_list args;
va_start(args, cmd);
ret = ctrl(impl, cmd, args);
va_end(args);
return ret;
}
/* Utility functions to send a string or hex string to a ctrl */
int kdf_str2ctrl(EVP_KDF_IMPL *impl,
int (*ctrl)(EVP_KDF_IMPL *impl, int cmd, va_list args),
int cmd, const char *str)
{
return call_ctrl(ctrl, impl, cmd, (const unsigned char *)str, strlen(str));
}
int kdf_hex2ctrl(EVP_KDF_IMPL *impl,
int (*ctrl)(EVP_KDF_IMPL *impl, int cmd, va_list args),
int cmd, const char *hex)
{
unsigned char *bin;
long binlen;
int ret = -1;
bin = OPENSSL_hexstr2buf(hex, &binlen);
if (bin == NULL)
return 0;
if (binlen <= INT_MAX)
ret = call_ctrl(ctrl, impl, cmd, bin, (size_t)binlen);
OPENSSL_free(bin);
return ret;
}
/* Pass a message digest to a ctrl */
int kdf_md2ctrl(EVP_KDF_IMPL *impl,
int (*ctrl)(EVP_KDF_IMPL *impl, int cmd, va_list args),
int cmd, const char *md_name)
{
const EVP_MD *md;
if (md_name == NULL || (md = EVP_get_digestbyname(md_name)) == NULL) {
KDFerr(KDF_F_KDF_MD2CTRL, KDF_R_INVALID_DIGEST);
return 0;
}
return call_ctrl(ctrl, impl, cmd, md);
}

264
crypto/kdf/pbkdf2.c Normal file
View file

@ -0,0 +1,264 @@
/*
* Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
*
* 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
*/
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <openssl/hmac.h>
#include <openssl/evp.h>
#include <openssl/kdf.h>
#include "internal/cryptlib.h"
#include "internal/evp_int.h"
#include "kdf_local.h"
static void kdf_pbkdf2_reset(EVP_KDF_IMPL *impl);
static void kdf_pbkdf2_init(EVP_KDF_IMPL *impl);
static int pkcs5_pbkdf2_alg(const char *pass, size_t passlen,
const unsigned char *salt, int saltlen, int iter,
const EVP_MD *digest, unsigned char *key,
size_t keylen);
struct evp_kdf_impl_st {
unsigned char *pass;
size_t pass_len;
unsigned char *salt;
size_t salt_len;
int iter;
const EVP_MD *md;
};
static EVP_KDF_IMPL *kdf_pbkdf2_new(void)
{
EVP_KDF_IMPL *impl;
impl = OPENSSL_zalloc(sizeof(*impl));
if (impl == NULL) {
KDFerr(KDF_F_KDF_PBKDF2_NEW, ERR_R_MALLOC_FAILURE);
return NULL;
}
kdf_pbkdf2_init(impl);
return impl;
}
static void kdf_pbkdf2_free(EVP_KDF_IMPL *impl)
{
kdf_pbkdf2_reset(impl);
OPENSSL_free(impl);
}
static void kdf_pbkdf2_reset(EVP_KDF_IMPL *impl)
{
OPENSSL_free(impl->salt);
OPENSSL_clear_free(impl->pass, impl->pass_len);
memset(impl, 0, sizeof(*impl));
kdf_pbkdf2_init(impl);
}
static void kdf_pbkdf2_init(EVP_KDF_IMPL *impl)
{
impl->iter = PKCS5_DEFAULT_ITER;
impl->md = EVP_sha1();
}
static int pbkdf2_set_membuf(unsigned char **buffer, size_t *buflen,
const unsigned char *new_buffer,
size_t new_buflen)
{
if (new_buffer == NULL)
return 1;
OPENSSL_clear_free(*buffer, *buflen);
if (new_buflen > 0) {
*buffer = OPENSSL_memdup(new_buffer, new_buflen);
} else {
*buffer = OPENSSL_malloc(1);
}
if (*buffer == NULL) {
KDFerr(KDF_F_PBKDF2_SET_MEMBUF, ERR_R_MALLOC_FAILURE);
return 0;
}
*buflen = new_buflen;
return 1;
}
static int kdf_pbkdf2_ctrl(EVP_KDF_IMPL *impl, int cmd, va_list args)
{
int iter;
const unsigned char *p;
size_t len;
const EVP_MD *md;
switch (cmd) {
case EVP_KDF_CTRL_SET_PASS:
p = va_arg(args, const unsigned char *);
len = va_arg(args, size_t);
return pbkdf2_set_membuf(&impl->pass, &impl->pass_len, p, len);
case EVP_KDF_CTRL_SET_SALT:
p = va_arg(args, const unsigned char *);
len = va_arg(args, size_t);
return pbkdf2_set_membuf(&impl->salt, &impl->salt_len, p, len);
case EVP_KDF_CTRL_SET_ITER:
iter = va_arg(args, int);
if (iter < 1)
return 0;
impl->iter = iter;
return 1;
case EVP_KDF_CTRL_SET_MD:
md = va_arg(args, const EVP_MD *);
if (md == NULL)
return 0;
impl->md = md;
return 1;
default:
return -2;
}
}
static int kdf_pbkdf2_ctrl_str(EVP_KDF_IMPL *impl, const char *type,
const char *value)
{
if (value == NULL) {
KDFerr(KDF_F_KDF_PBKDF2_CTRL_STR, KDF_R_VALUE_MISSING);
return 0;
}
if (strcmp(type, "pass") == 0)
return kdf_str2ctrl(impl, kdf_pbkdf2_ctrl, EVP_KDF_CTRL_SET_PASS,
value);
if (strcmp(type, "hexpass") == 0)
return kdf_hex2ctrl(impl, kdf_pbkdf2_ctrl, EVP_KDF_CTRL_SET_PASS,
value);
if (strcmp(type, "salt") == 0)
return kdf_str2ctrl(impl, kdf_pbkdf2_ctrl, EVP_KDF_CTRL_SET_SALT,
value);
if (strcmp(type, "hexsalt") == 0)
return kdf_hex2ctrl(impl, kdf_pbkdf2_ctrl, EVP_KDF_CTRL_SET_SALT,
value);
if (strcmp(type, "iter") == 0)
return call_ctrl(kdf_pbkdf2_ctrl, impl, EVP_KDF_CTRL_SET_ITER,
atoi(value));
if (strcmp(type, "digest") == 0)
return kdf_md2ctrl(impl, kdf_pbkdf2_ctrl, EVP_KDF_CTRL_SET_MD, value);
return -2;
}
static int kdf_pbkdf2_derive(EVP_KDF_IMPL *impl, unsigned char *key,
size_t keylen)
{
if (impl->pass == NULL) {
KDFerr(KDF_F_KDF_PBKDF2_DERIVE, KDF_R_MISSING_PASS);
return 0;
}
if (impl->salt == NULL) {
KDFerr(KDF_F_KDF_PBKDF2_DERIVE, KDF_R_MISSING_SALT);
return 0;
}
return pkcs5_pbkdf2_alg((char *)impl->pass, impl->pass_len,
impl->salt, impl->salt_len, impl->iter,
impl->md, key, keylen);
}
const EVP_KDF_METHOD pbkdf2_kdf_meth = {
EVP_KDF_PBKDF2,
kdf_pbkdf2_new,
kdf_pbkdf2_free,
kdf_pbkdf2_reset,
kdf_pbkdf2_ctrl,
kdf_pbkdf2_ctrl_str,
NULL,
kdf_pbkdf2_derive
};
/*
* 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.
*/
static int pkcs5_pbkdf2_alg(const char *pass, size_t passlen,
const unsigned char *salt, int saltlen, int iter,
const EVP_MD *digest, unsigned char *key,
size_t keylen)
{
int ret = 0;
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;
mdlen = EVP_MD_size(digest);
if (mdlen < 0)
return 0;
hctx_tpl = HMAC_CTX_new();
if (hctx_tpl == NULL)
return 0;
p = key;
tkeylen = keylen;
if (!HMAC_Init_ex(hctx_tpl, pass, passlen, digest, NULL))
goto err;
hctx = HMAC_CTX_new();
if (hctx == NULL)
goto err;
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))
goto err;
if (!HMAC_Update(hctx, salt, saltlen)
|| !HMAC_Update(hctx, itmp, 4)
|| !HMAC_Final(hctx, digtmp, NULL))
goto err;
memcpy(p, digtmp, cplen);
for (j = 1; j < iter; j++) {
if (!HMAC_CTX_copy(hctx, hctx_tpl))
goto err;
if (!HMAC_Update(hctx, digtmp, mdlen)
|| !HMAC_Final(hctx, digtmp, NULL))
goto err;
for (k = 0; k < cplen; k++)
p[k] ^= digtmp[k];
}
tkeylen -= cplen;
i++;
p += cplen;
}
ret = 1;
err:
HMAC_CTX_free(hctx);
HMAC_CTX_free(hctx_tpl);
return ret;
}

View file

@ -8,25 +8,34 @@
*/
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <openssl/hmac.h>
#include <openssl/kdf.h>
#include <openssl/evp.h>
#include "internal/cryptlib.h"
#include <openssl/kdf.h>
#include <openssl/err.h>
#include "internal/evp_int.h"
#include "internal/numbers.h"
#include "kdf_local.h"
#ifndef OPENSSL_NO_SCRYPT
static void kdf_scrypt_reset(EVP_KDF_IMPL *impl);
static void kdf_scrypt_init(EVP_KDF_IMPL *impl);
static int atou64(const char *nptr, uint64_t *result);
static int scrypt_alg(const char *pass, size_t passlen,
const unsigned char *salt, size_t saltlen,
uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem,
unsigned char *key, size_t keylen);
typedef struct {
struct evp_kdf_impl_st {
unsigned char *pass;
size_t pass_len;
unsigned char *salt;
size_t salt_len;
uint64_t N, r, p;
uint64_t N;
uint32_t r, p;
uint64_t maxmem_bytes;
} SCRYPT_PKEY_CTX;
};
/* Custom uint64_t parser since we do not have strtoull */
static int atou64(const char *nptr, uint64_t *result)
@ -53,51 +62,53 @@ static int atou64(const char *nptr, uint64_t *result)
return 1;
}
static int pkey_scrypt_init(EVP_PKEY_CTX *ctx)
static EVP_KDF_IMPL *kdf_scrypt_new(void)
{
SCRYPT_PKEY_CTX *kctx;
EVP_KDF_IMPL *impl;
kctx = OPENSSL_zalloc(sizeof(*kctx));
if (kctx == NULL) {
KDFerr(KDF_F_PKEY_SCRYPT_INIT, ERR_R_MALLOC_FAILURE);
return 0;
impl = OPENSSL_zalloc(sizeof(*impl));
if (impl == NULL) {
KDFerr(KDF_F_KDF_SCRYPT_NEW, ERR_R_MALLOC_FAILURE);
return NULL;
}
kdf_scrypt_init(impl);
return impl;
}
static void kdf_scrypt_free(EVP_KDF_IMPL *impl)
{
kdf_scrypt_reset(impl);
OPENSSL_free(impl);
}
static void kdf_scrypt_reset(EVP_KDF_IMPL *impl)
{
OPENSSL_free(impl->salt);
OPENSSL_clear_free(impl->pass, impl->pass_len);
memset(impl, 0, sizeof(*impl));
kdf_scrypt_init(impl);
}
static void kdf_scrypt_init(EVP_KDF_IMPL *impl)
{
/* Default values are the most conservative recommendation given in the
* original paper of C. Percival. Derivation uses roughly 1 GiB of memory
* for this parameter choice (approx. 128 * r * (N + p) bytes).
* for this parameter choice (approx. 128 * r * N * p bytes).
*/
kctx->N = 1 << 20;
kctx->r = 8;
kctx->p = 1;
kctx->maxmem_bytes = 1025 * 1024 * 1024;
ctx->data = kctx;
return 1;
impl->N = 1 << 20;
impl->r = 8;
impl->p = 1;
impl->maxmem_bytes = 1025 * 1024 * 1024;
}
static void pkey_scrypt_cleanup(EVP_PKEY_CTX *ctx)
{
SCRYPT_PKEY_CTX *kctx = ctx->data;
OPENSSL_clear_free(kctx->salt, kctx->salt_len);
OPENSSL_clear_free(kctx->pass, kctx->pass_len);
OPENSSL_free(kctx);
}
static int pkey_scrypt_set_membuf(unsigned char **buffer, size_t *buflen,
const unsigned char *new_buffer,
const int new_buflen)
static int scrypt_set_membuf(unsigned char **buffer, size_t *buflen,
const unsigned char *new_buffer,
size_t new_buflen)
{
if (new_buffer == NULL)
return 1;
if (new_buflen < 0)
return 0;
if (*buffer != NULL)
OPENSSL_clear_free(*buffer, *buflen);
OPENSSL_clear_free(*buffer, *buflen);
if (new_buflen > 0) {
*buffer = OPENSSL_memdup(new_buffer, new_buflen);
@ -105,7 +116,7 @@ static int pkey_scrypt_set_membuf(unsigned char **buffer, size_t *buflen,
*buffer = OPENSSL_malloc(1);
}
if (*buffer == NULL) {
KDFerr(KDF_F_PKEY_SCRYPT_SET_MEMBUF, ERR_R_MALLOC_FAILURE);
KDFerr(KDF_F_SCRYPT_SET_MEMBUF, ERR_R_MALLOC_FAILURE);
return 0;
}
@ -118,149 +129,378 @@ static int is_power_of_two(uint64_t value)
return (value != 0) && ((value & (value - 1)) == 0);
}
static int pkey_scrypt_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
static int kdf_scrypt_ctrl(EVP_KDF_IMPL *impl, int cmd, va_list args)
{
SCRYPT_PKEY_CTX *kctx = ctx->data;
uint64_t u64_value;
uint32_t value;
const unsigned char *p;
size_t len;
switch (type) {
case EVP_PKEY_CTRL_PASS:
return pkey_scrypt_set_membuf(&kctx->pass, &kctx->pass_len, p2, p1);
switch (cmd) {
case EVP_KDF_CTRL_SET_PASS:
p = va_arg(args, const unsigned char *);
len = va_arg(args, size_t);
return scrypt_set_membuf(&impl->pass, &impl->pass_len, p, len);
case EVP_PKEY_CTRL_SCRYPT_SALT:
return pkey_scrypt_set_membuf(&kctx->salt, &kctx->salt_len, p2, p1);
case EVP_KDF_CTRL_SET_SALT:
p = va_arg(args, const unsigned char *);
len = va_arg(args, size_t);
return scrypt_set_membuf(&impl->salt, &impl->salt_len, p, len);
case EVP_PKEY_CTRL_SCRYPT_N:
u64_value = *((uint64_t *)p2);
case EVP_KDF_CTRL_SET_SCRYPT_N:
u64_value = va_arg(args, uint64_t);
if ((u64_value <= 1) || !is_power_of_two(u64_value))
return 0;
kctx->N = u64_value;
impl->N = u64_value;
return 1;
case EVP_PKEY_CTRL_SCRYPT_R:
u64_value = *((uint64_t *)p2);
if (u64_value < 1)
case EVP_KDF_CTRL_SET_SCRYPT_R:
value = va_arg(args, uint32_t);
if (value < 1)
return 0;
kctx->r = u64_value;
impl->r = value;
return 1;
case EVP_PKEY_CTRL_SCRYPT_P:
u64_value = *((uint64_t *)p2);
if (u64_value < 1)
case EVP_KDF_CTRL_SET_SCRYPT_P:
value = va_arg(args, uint32_t);
if (value < 1)
return 0;
kctx->p = u64_value;
impl->p = value;
return 1;
case EVP_PKEY_CTRL_SCRYPT_MAXMEM_BYTES:
u64_value = *((uint64_t *)p2);
case EVP_KDF_CTRL_SET_MAXMEM_BYTES:
u64_value = va_arg(args, uint64_t);
if (u64_value < 1)
return 0;
kctx->maxmem_bytes = u64_value;
impl->maxmem_bytes = u64_value;
return 1;
default:
return -2;
}
}
static int pkey_scrypt_ctrl_uint64(EVP_PKEY_CTX *ctx, int type,
const char *value)
static int kdf_scrypt_ctrl_uint32(EVP_KDF_IMPL *impl, int cmd,
const char *value)
{
uint64_t int_value;
int int_value = atoi(value);
if (!atou64(value, &int_value)) {
KDFerr(KDF_F_PKEY_SCRYPT_CTRL_UINT64, KDF_R_VALUE_ERROR);
if (int_value < 0 || (uint64_t)int_value > UINT32_MAX) {
KDFerr(KDF_F_KDF_SCRYPT_CTRL_UINT32, KDF_R_VALUE_ERROR);
return 0;
}
return pkey_scrypt_ctrl(ctx, type, 0, &int_value);
return call_ctrl(kdf_scrypt_ctrl, impl, cmd, (uint32_t)int_value);
}
static int pkey_scrypt_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
const char *value)
static int kdf_scrypt_ctrl_uint64(EVP_KDF_IMPL *impl, int cmd,
const char *value)
{
uint64_t u64_value;
if (!atou64(value, &u64_value)) {
KDFerr(KDF_F_KDF_SCRYPT_CTRL_UINT64, KDF_R_VALUE_ERROR);
return 0;
}
return call_ctrl(kdf_scrypt_ctrl, impl, cmd, u64_value);
}
static int kdf_scrypt_ctrl_str(EVP_KDF_IMPL *impl, const char *type,
const char *value)
{
if (value == NULL) {
KDFerr(KDF_F_PKEY_SCRYPT_CTRL_STR, KDF_R_VALUE_MISSING);
KDFerr(KDF_F_KDF_SCRYPT_CTRL_STR, KDF_R_VALUE_MISSING);
return 0;
}
if (strcmp(type, "pass") == 0)
return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_PASS, value);
return kdf_str2ctrl(impl, kdf_scrypt_ctrl, EVP_KDF_CTRL_SET_PASS,
value);
if (strcmp(type, "hexpass") == 0)
return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_PASS, value);
return kdf_hex2ctrl(impl, kdf_scrypt_ctrl, EVP_KDF_CTRL_SET_PASS,
value);
if (strcmp(type, "salt") == 0)
return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_SCRYPT_SALT, value);
return kdf_str2ctrl(impl, kdf_scrypt_ctrl, EVP_KDF_CTRL_SET_SALT,
value);
if (strcmp(type, "hexsalt") == 0)
return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_SCRYPT_SALT, value);
return kdf_hex2ctrl(impl, kdf_scrypt_ctrl, EVP_KDF_CTRL_SET_SALT,
value);
if (strcmp(type, "N") == 0)
return pkey_scrypt_ctrl_uint64(ctx, EVP_PKEY_CTRL_SCRYPT_N, value);
return kdf_scrypt_ctrl_uint64(impl, EVP_KDF_CTRL_SET_SCRYPT_N, value);
if (strcmp(type, "r") == 0)
return pkey_scrypt_ctrl_uint64(ctx, EVP_PKEY_CTRL_SCRYPT_R, value);
return kdf_scrypt_ctrl_uint32(impl, EVP_KDF_CTRL_SET_SCRYPT_R, value);
if (strcmp(type, "p") == 0)
return pkey_scrypt_ctrl_uint64(ctx, EVP_PKEY_CTRL_SCRYPT_P, value);
return kdf_scrypt_ctrl_uint32(impl, EVP_KDF_CTRL_SET_SCRYPT_P, value);
if (strcmp(type, "maxmem_bytes") == 0)
return pkey_scrypt_ctrl_uint64(ctx, EVP_PKEY_CTRL_SCRYPT_MAXMEM_BYTES,
value);
return kdf_scrypt_ctrl_uint64(impl, EVP_KDF_CTRL_SET_MAXMEM_BYTES,
value);
KDFerr(KDF_F_PKEY_SCRYPT_CTRL_STR, KDF_R_UNKNOWN_PARAMETER_TYPE);
return -2;
}
static int pkey_scrypt_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
size_t *keylen)
static int kdf_scrypt_derive(EVP_KDF_IMPL *impl, unsigned char *key,
size_t keylen)
{
SCRYPT_PKEY_CTX *kctx = ctx->data;
if (kctx->pass == NULL) {
KDFerr(KDF_F_PKEY_SCRYPT_DERIVE, KDF_R_MISSING_PASS);
if (impl->pass == NULL) {
KDFerr(KDF_F_KDF_SCRYPT_DERIVE, KDF_R_MISSING_PASS);
return 0;
}
if (kctx->salt == NULL) {
KDFerr(KDF_F_PKEY_SCRYPT_DERIVE, KDF_R_MISSING_SALT);
if (impl->salt == NULL) {
KDFerr(KDF_F_KDF_SCRYPT_DERIVE, KDF_R_MISSING_SALT);
return 0;
}
return EVP_PBE_scrypt((char *)kctx->pass, kctx->pass_len, kctx->salt,
kctx->salt_len, kctx->N, kctx->r, kctx->p,
kctx->maxmem_bytes, key, *keylen);
return scrypt_alg((char *)impl->pass, impl->pass_len, impl->salt,
impl->salt_len, impl->N, impl->r, impl->p,
impl->maxmem_bytes, key, keylen);
}
const EVP_PKEY_METHOD scrypt_pkey_meth = {
EVP_PKEY_SCRYPT,
0,
pkey_scrypt_init,
0,
pkey_scrypt_cleanup,
0, 0,
0, 0,
0,
0,
0,
0,
0, 0,
0, 0, 0, 0,
0, 0,
0, 0,
0,
pkey_scrypt_derive,
pkey_scrypt_ctrl,
pkey_scrypt_ctrl_str
const EVP_KDF_METHOD scrypt_kdf_meth = {
EVP_KDF_SCRYPT,
kdf_scrypt_new,
kdf_scrypt_free,
kdf_scrypt_reset,
kdf_scrypt_ctrl,
kdf_scrypt_ctrl_str,
NULL,
kdf_scrypt_derive
};
#define R(a,b) (((a) << (b)) | ((a) >> (32 - (b))))
static void salsa208_word_specification(uint32_t inout[16])
{
int i;
uint32_t x[16];
memcpy(x, inout, sizeof(x));
for (i = 8; i > 0; i -= 2) {
x[4] ^= R(x[0] + x[12], 7);
x[8] ^= R(x[4] + x[0], 9);
x[12] ^= R(x[8] + x[4], 13);
x[0] ^= R(x[12] + x[8], 18);
x[9] ^= R(x[5] + x[1], 7);
x[13] ^= R(x[9] + x[5], 9);
x[1] ^= R(x[13] + x[9], 13);
x[5] ^= R(x[1] + x[13], 18);
x[14] ^= R(x[10] + x[6], 7);
x[2] ^= R(x[14] + x[10], 9);
x[6] ^= R(x[2] + x[14], 13);
x[10] ^= R(x[6] + x[2], 18);
x[3] ^= R(x[15] + x[11], 7);
x[7] ^= R(x[3] + x[15], 9);
x[11] ^= R(x[7] + x[3], 13);
x[15] ^= R(x[11] + x[7], 18);
x[1] ^= R(x[0] + x[3], 7);
x[2] ^= R(x[1] + x[0], 9);
x[3] ^= R(x[2] + x[1], 13);
x[0] ^= R(x[3] + x[2], 18);
x[6] ^= R(x[5] + x[4], 7);
x[7] ^= R(x[6] + x[5], 9);
x[4] ^= R(x[7] + x[6], 13);
x[5] ^= R(x[4] + x[7], 18);
x[11] ^= R(x[10] + x[9], 7);
x[8] ^= R(x[11] + x[10], 9);
x[9] ^= R(x[8] + x[11], 13);
x[10] ^= R(x[9] + x[8], 18);
x[12] ^= R(x[15] + x[14], 7);
x[13] ^= R(x[12] + x[15], 9);
x[14] ^= R(x[13] + x[12], 13);
x[15] ^= R(x[14] + x[13], 18);
}
for (i = 0; i < 16; ++i)
inout[i] += x[i];
OPENSSL_cleanse(x, sizeof(x));
}
static void scryptBlockMix(uint32_t *B_, uint32_t *B, uint64_t r)
{
uint64_t i, j;
uint32_t X[16], *pB;
memcpy(X, B + (r * 2 - 1) * 16, sizeof(X));
pB = B;
for (i = 0; i < r * 2; i++) {
for (j = 0; j < 16; j++)
X[j] ^= *pB++;
salsa208_word_specification(X);
memcpy(B_ + (i / 2 + (i & 1) * r) * 16, X, sizeof(X));
}
OPENSSL_cleanse(X, sizeof(X));
}
static void scryptROMix(unsigned char *B, uint64_t r, uint64_t N,
uint32_t *X, uint32_t *T, uint32_t *V)
{
unsigned char *pB;
uint32_t *pV;
uint64_t i, k;
/* Convert from little endian input */
for (pV = V, i = 0, pB = B; i < 32 * r; i++, pV++) {
*pV = *pB++;
*pV |= *pB++ << 8;
*pV |= *pB++ << 16;
*pV |= (uint32_t)*pB++ << 24;
}
for (i = 1; i < N; i++, pV += 32 * r)
scryptBlockMix(pV, pV - 32 * r, r);
scryptBlockMix(X, V + (N - 1) * 32 * r, r);
for (i = 0; i < N; i++) {
uint32_t j;
j = X[16 * (2 * r - 1)] % N;
pV = V + 32 * r * j;
for (k = 0; k < 32 * r; k++)
T[k] = X[k] ^ *pV++;
scryptBlockMix(X, T, r);
}
/* Convert output to little endian */
for (i = 0, pB = B; i < 32 * r; i++) {
uint32_t xtmp = X[i];
*pB++ = xtmp & 0xff;
*pB++ = (xtmp >> 8) & 0xff;
*pB++ = (xtmp >> 16) & 0xff;
*pB++ = (xtmp >> 24) & 0xff;
}
}
#ifndef SIZE_MAX
# define SIZE_MAX ((size_t)-1)
#endif
/*
* Maximum power of two that will fit in uint64_t: this should work on
* most (all?) platforms.
*/
#define LOG2_UINT64_MAX (sizeof(uint64_t) * 8 - 1)
/*
* Maximum value of p * r:
* p <= ((2^32-1) * hLen) / MFLen =>
* p <= ((2^32-1) * 32) / (128 * r) =>
* p * r <= (2^30-1)
*/
#define SCRYPT_PR_MAX ((1 << 30) - 1)
static int scrypt_alg(const char *pass, size_t passlen,
const unsigned char *salt, size_t saltlen,
uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem,
unsigned char *key, size_t keylen)
{
int rv = 0;
unsigned char *B;
uint32_t *X, *V, *T;
uint64_t i, Blen, Vlen;
/* Sanity check parameters */
/* initial check, r,p must be non zero, N >= 2 and a power of 2 */
if (r == 0 || p == 0 || N < 2 || (N & (N - 1)))
return 0;
/* Check p * r < SCRYPT_PR_MAX avoiding overflow */
if (p > SCRYPT_PR_MAX / r) {
EVPerr(EVP_F_SCRYPT_ALG, EVP_R_MEMORY_LIMIT_EXCEEDED);
return 0;
}
/*
* Need to check N: if 2^(128 * r / 8) overflows limit this is
* automatically satisfied since N <= UINT64_MAX.
*/
if (16 * r <= LOG2_UINT64_MAX) {
if (N >= (((uint64_t)1) << (16 * r))) {
EVPerr(EVP_F_SCRYPT_ALG, EVP_R_MEMORY_LIMIT_EXCEEDED);
return 0;
}
}
/* Memory checks: check total allocated buffer size fits in uint64_t */
/*
* B size in section 5 step 1.S
* Note: we know p * 128 * r < UINT64_MAX because we already checked
* p * r < SCRYPT_PR_MAX
*/
Blen = p * 128 * r;
/*
* Yet we pass it as integer to PKCS5_PBKDF2_HMAC... [This would
* have to be revised when/if PKCS5_PBKDF2_HMAC accepts size_t.]
*/
if (Blen > INT_MAX) {
EVPerr(EVP_F_SCRYPT_ALG, EVP_R_MEMORY_LIMIT_EXCEEDED);
return 0;
}
/*
* Check 32 * r * (N + 2) * sizeof(uint32_t) fits in uint64_t
* This is combined size V, X and T (section 4)
*/
i = UINT64_MAX / (32 * sizeof(uint32_t));
if (N + 2 > i / r) {
EVPerr(EVP_F_SCRYPT_ALG, EVP_R_MEMORY_LIMIT_EXCEEDED);
return 0;
}
Vlen = 32 * r * (N + 2) * sizeof(uint32_t);
/* check total allocated size fits in uint64_t */
if (Blen > UINT64_MAX - Vlen) {
EVPerr(EVP_F_SCRYPT_ALG, EVP_R_MEMORY_LIMIT_EXCEEDED);
return 0;
}
/* Check that the maximum memory doesn't exceed a size_t limits */
if (maxmem > SIZE_MAX)
maxmem = SIZE_MAX;
if (Blen + Vlen > maxmem) {
EVPerr(EVP_F_SCRYPT_ALG, EVP_R_MEMORY_LIMIT_EXCEEDED);
return 0;
}
/* If no key return to indicate parameters are OK */
if (key == NULL)
return 1;
B = OPENSSL_malloc((size_t)(Blen + Vlen));
if (B == NULL) {
EVPerr(EVP_F_SCRYPT_ALG, ERR_R_MALLOC_FAILURE);
return 0;
}
X = (uint32_t *)(B + Blen);
T = X + 32 * r;
V = T + 32 * r;
if (PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, 1, EVP_sha256(),
(int)Blen, B) == 0)
goto err;
for (i = 0; i < p; i++)
scryptROMix(B + 128 * r * i, r, N, X, T, V);
if (PKCS5_PBKDF2_HMAC(pass, passlen, B, (int)Blen, 1, EVP_sha256(),
keylen, key) == 0)
goto err;
rv = 1;
err:
if (rv == 0)
EVPerr(EVP_F_SCRYPT_ALG, EVP_R_PBKDF2_ERROR);
OPENSSL_clear_free(B, (size_t)(Blen + Vlen));
return rv;
}
#endif

View file

@ -8,11 +8,15 @@
*/
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include "internal/cryptlib.h"
#include <openssl/kdf.h>
#include <openssl/evp.h>
#include <openssl/kdf.h>
#include "internal/evp_int.h"
#include "kdf_local.h"
static void kdf_tls1_prf_reset(EVP_KDF_IMPL *impl);
static int tls1_prf_alg(const EVP_MD *md,
const unsigned char *sec, size_t slen,
const unsigned char *seed, size_t seed_len,
@ -20,9 +24,9 @@ static int tls1_prf_alg(const EVP_MD *md,
#define TLS1_PRF_MAXBUF 1024
/* TLS KDF pkey context structure */
/* TLS KDF kdf context structure */
typedef struct {
struct evp_kdf_impl_st {
/* Digest to use for PRF */
const EVP_MD *md;
/* Secret value to use for PRF */
@ -31,145 +35,137 @@ typedef struct {
/* Buffer of concatenated seed data */
unsigned char seed[TLS1_PRF_MAXBUF];
size_t seedlen;
} TLS1_PRF_PKEY_CTX;
};
static int pkey_tls1_prf_init(EVP_PKEY_CTX *ctx)
static EVP_KDF_IMPL *kdf_tls1_prf_new(void)
{
TLS1_PRF_PKEY_CTX *kctx;
EVP_KDF_IMPL *impl;
if ((kctx = OPENSSL_zalloc(sizeof(*kctx))) == NULL) {
KDFerr(KDF_F_PKEY_TLS1_PRF_INIT, ERR_R_MALLOC_FAILURE);
return 0;
}
ctx->data = kctx;
return 1;
if ((impl = OPENSSL_zalloc(sizeof(*impl))) == NULL)
KDFerr(KDF_F_KDF_TLS1_PRF_NEW, ERR_R_MALLOC_FAILURE);
return impl;
}
static void pkey_tls1_prf_cleanup(EVP_PKEY_CTX *ctx)
static void kdf_tls1_prf_free(EVP_KDF_IMPL *impl)
{
TLS1_PRF_PKEY_CTX *kctx = ctx->data;
OPENSSL_clear_free(kctx->sec, kctx->seclen);
OPENSSL_cleanse(kctx->seed, kctx->seedlen);
OPENSSL_free(kctx);
kdf_tls1_prf_reset(impl);
OPENSSL_free(impl);
}
static int pkey_tls1_prf_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
static void kdf_tls1_prf_reset(EVP_KDF_IMPL *impl)
{
TLS1_PRF_PKEY_CTX *kctx = ctx->data;
switch (type) {
case EVP_PKEY_CTRL_TLS_MD:
kctx->md = p2;
OPENSSL_clear_free(impl->sec, impl->seclen);
OPENSSL_cleanse(impl->seed, impl->seedlen);
memset(impl, 0, sizeof(*impl));
}
static int kdf_tls1_prf_ctrl(EVP_KDF_IMPL *impl, int cmd, va_list args)
{
const unsigned char *p;
size_t len;
const EVP_MD *md;
switch (cmd) {
case EVP_KDF_CTRL_SET_MD:
md = va_arg(args, const EVP_MD *);
if (md == NULL)
return 0;
impl->md = md;
return 1;
case EVP_PKEY_CTRL_TLS_SECRET:
if (p1 < 0)
case EVP_KDF_CTRL_SET_TLS_SECRET:
p = va_arg(args, const unsigned char *);
len = va_arg(args, size_t);
OPENSSL_clear_free(impl->sec, impl->seclen);
impl->sec = OPENSSL_memdup(p, len);
if (impl->sec == NULL)
return 0;
if (kctx->sec != NULL)
OPENSSL_clear_free(kctx->sec, kctx->seclen);
OPENSSL_cleanse(kctx->seed, kctx->seedlen);
kctx->seedlen = 0;
kctx->sec = OPENSSL_memdup(p2, p1);
if (kctx->sec == NULL)
return 0;
kctx->seclen = p1;
impl->seclen = len;
return 1;
case EVP_PKEY_CTRL_TLS_SEED:
if (p1 == 0 || p2 == NULL)
case EVP_KDF_CTRL_RESET_TLS_SEED:
OPENSSL_cleanse(impl->seed, impl->seedlen);
impl->seedlen = 0;
return 1;
case EVP_KDF_CTRL_ADD_TLS_SEED:
p = va_arg(args, const unsigned char *);
len = va_arg(args, size_t);
if (len == 0 || p == NULL)
return 1;
if (p1 < 0 || p1 > (int)(TLS1_PRF_MAXBUF - kctx->seedlen))
if (len > (TLS1_PRF_MAXBUF - impl->seedlen))
return 0;
memcpy(kctx->seed + kctx->seedlen, p2, p1);
kctx->seedlen += p1;
memcpy(impl->seed + impl->seedlen, p, len);
impl->seedlen += len;
return 1;
default:
return -2;
}
}
static int pkey_tls1_prf_ctrl_str(EVP_PKEY_CTX *ctx,
const char *type, const char *value)
static int kdf_tls1_prf_ctrl_str(EVP_KDF_IMPL *impl,
const char *type, const char *value)
{
if (value == NULL) {
KDFerr(KDF_F_PKEY_TLS1_PRF_CTRL_STR, KDF_R_VALUE_MISSING);
KDFerr(KDF_F_KDF_TLS1_PRF_CTRL_STR, KDF_R_VALUE_MISSING);
return 0;
}
if (strcmp(type, "md") == 0) {
TLS1_PRF_PKEY_CTX *kctx = ctx->data;
if (strcmp(type, "digest") == 0)
return kdf_md2ctrl(impl, kdf_tls1_prf_ctrl, EVP_KDF_CTRL_SET_MD, value);
const EVP_MD *md = EVP_get_digestbyname(value);
if (md == NULL) {
KDFerr(KDF_F_PKEY_TLS1_PRF_CTRL_STR, KDF_R_INVALID_DIGEST);
return 0;
}
kctx->md = md;
return 1;
}
if (strcmp(type, "secret") == 0)
return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_TLS_SECRET, value);
if (strcmp(type, "hexsecret") == 0)
return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_TLS_SECRET, value);
if (strcmp(type, "seed") == 0)
return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_TLS_SEED, value);
if (strcmp(type, "hexseed") == 0)
return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_TLS_SEED, value);
return kdf_str2ctrl(impl, kdf_tls1_prf_ctrl,
EVP_KDF_CTRL_SET_TLS_SECRET, value);
if (strcmp(type, "hexsecret") == 0)
return kdf_hex2ctrl(impl, kdf_tls1_prf_ctrl,
EVP_KDF_CTRL_SET_TLS_SECRET, value);
if (strcmp(type, "seed") == 0)
return kdf_str2ctrl(impl, kdf_tls1_prf_ctrl, EVP_KDF_CTRL_ADD_TLS_SEED,
value);
if (strcmp(type, "hexseed") == 0)
return kdf_hex2ctrl(impl, kdf_tls1_prf_ctrl, EVP_KDF_CTRL_ADD_TLS_SEED,
value);
KDFerr(KDF_F_PKEY_TLS1_PRF_CTRL_STR, KDF_R_UNKNOWN_PARAMETER_TYPE);
return -2;
}
static int pkey_tls1_prf_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
size_t *keylen)
static int kdf_tls1_prf_derive(EVP_KDF_IMPL *impl, unsigned char *key,
size_t keylen)
{
TLS1_PRF_PKEY_CTX *kctx = ctx->data;
if (kctx->md == NULL) {
KDFerr(KDF_F_PKEY_TLS1_PRF_DERIVE, KDF_R_MISSING_MESSAGE_DIGEST);
if (impl->md == NULL) {
KDFerr(KDF_F_KDF_TLS1_PRF_DERIVE, KDF_R_MISSING_MESSAGE_DIGEST);
return 0;
}
if (kctx->sec == NULL) {
KDFerr(KDF_F_PKEY_TLS1_PRF_DERIVE, KDF_R_MISSING_SECRET);
if (impl->sec == NULL) {
KDFerr(KDF_F_KDF_TLS1_PRF_DERIVE, KDF_R_MISSING_SECRET);
return 0;
}
if (kctx->seedlen == 0) {
KDFerr(KDF_F_PKEY_TLS1_PRF_DERIVE, KDF_R_MISSING_SEED);
if (impl->seedlen == 0) {
KDFerr(KDF_F_KDF_TLS1_PRF_DERIVE, KDF_R_MISSING_SEED);
return 0;
}
return tls1_prf_alg(kctx->md, kctx->sec, kctx->seclen,
kctx->seed, kctx->seedlen,
key, *keylen);
return tls1_prf_alg(impl->md, impl->sec, impl->seclen,
impl->seed, impl->seedlen,
key, keylen);
}
const EVP_PKEY_METHOD tls1_prf_pkey_meth = {
EVP_PKEY_TLS1_PRF,
0,
pkey_tls1_prf_init,
0,
pkey_tls1_prf_cleanup,
0, 0,
0, 0,
0,
0,
0,
0,
0, 0,
0, 0, 0, 0,
0, 0,
0, 0,
0,
pkey_tls1_prf_derive,
pkey_tls1_prf_ctrl,
pkey_tls1_prf_ctrl_str
const EVP_KDF_METHOD tls1_prf_kdf_meth = {
EVP_KDF_TLS1_PRF,
kdf_tls1_prf_new,
kdf_tls1_prf_free,
kdf_tls1_prf_reset,
kdf_tls1_prf_ctrl,
kdf_tls1_prf_ctrl_str,
NULL,
kdf_tls1_prf_derive
};
static int tls1_prf_P_hash(const EVP_MD *md,
@ -249,12 +245,11 @@ static int tls1_prf_alg(const EVP_MD *md,
const unsigned char *seed, size_t seed_len,
unsigned char *out, size_t olen)
{
if (EVP_MD_type(md) == NID_md5_sha1) {
size_t i;
unsigned char *tmp;
if (!tls1_prf_P_hash(EVP_md5(), sec, slen/2 + (slen & 1),
seed, seed_len, out, olen))
seed, seed_len, out, olen))
return 0;
if ((tmp = OPENSSL_malloc(olen)) == NULL) {
@ -262,7 +257,7 @@ static int tls1_prf_alg(const EVP_MD *md,
return 0;
}
if (!tls1_prf_P_hash(EVP_sha1(), sec + slen/2, slen/2 + (slen & 1),
seed, seed_len, tmp, olen)) {
seed, seed_len, tmp, olen)) {
OPENSSL_clear_free(tmp, olen);
return 0;
}

217
doc/man3/EVP_KDF_CTX.pod Normal file
View file

@ -0,0 +1,217 @@
=pod
=head1 NAME
EVP_KDF_CTX, EVP_KDF_CTX_new_id, EVP_KDF_CTX_free, EVP_KDF_reset,
EVP_KDF_ctrl, EVP_KDF_vctrl, EVP_KDF_ctrl_str, EVP_KDF_size,
EVP_KDF_derive - EVP KDF routines
=head1 SYNOPSIS
#include <openssl/kdf.h>
typedef struct evp_kdf_ctx_st EVP_KDF_CTX;
EVP_KDF_CTX *EVP_KDF_CTX_new_id(int id);
void EVP_KDF_CTX_free(EVP_KDF_CTX *ctx);
void EVP_KDF_reset(EVP_KDF_CTX *ctx);
int EVP_KDF_ctrl(EVP_KDF_CTX *ctx, int cmd, ...);
int EVP_KDF_vctrl(EVP_KDF_CTX *ctx, int cmd, va_list args);
int EVP_KDF_ctrl_str(EVP_KDF_CTX *ctx, const char *type, const char *value);
size_t EVP_KDF_size(EVP_KDF_CTX *ctx);
int EVP_KDF_derive(EVP_KDF_CTX *ctx, unsigned char *key, size_t keylen);
=head1 DESCRIPTION
The EVP KDF routines are a high level interface to Key Derivation Function
algorithms and should be used instead of algorithm-specific functions.
After creating a C<EVP_KDF_CTX> for the required algorithm using
EVP_KDF_CTX_new_id(), inputs to the algorithm are supplied using calls to
EVP_KDF_ctrl(), EVP_KDF_vctrl() or EVP_KDF_ctrl_str() before calling
EVP_KDF_derive() to derive the key.
=head2 Types
B<EVP_KDF_CTX> is a context type that holds the algorithm inputs.
=head2 Context manipulation functions
EVP_KDF_CTX_new_id() creates a KDF context for the algorithm identified by the
specified NID.
EVP_KDF_CTX_free() frees up the context C<ctx>. If C<ctx> is C<NULL>, nothing
is done.
=head2 Computing functions
EVP_KDF_reset() resets the context to the default state as if the context
had just been created.
EVP_KDF_ctrl() is used to provide inputs to the KDF algorithm prior to
EVP_KDF_derive() being called. The inputs that may be provided will vary
depending on the KDF algorithm or its implementation. This functions takes
variable arguments, the exact expected arguments depend on C<cmd>.
See L</CONTROLS> below for a description of standard controls.
EVP_KDF_vctrl() is the variant of EVP_KDF_ctrl() that takes a C<va_list>
argument instead of variadic arguments.
EVP_KDF_ctrl_str() allows an application to send an algorithm specific control
operation to a context C<ctx> in string form. This is intended to be used for
options specified on the command line or in text files.
EVP_KDF_size() returns the output size if the algorithm produces a fixed amount
of output and C<SIZE_MAX> otherwise. If an error occurs then 0 is returned.
For some algorithms an error may result if input parameters necessary to
calculate a fixed output size have not yet been supplied.
EVP_KDF_derive() derives C<keylen> bytes of key material and places it in the
C<key> buffer. If the algorithm produces a fixed amount of output then an
error will occur unless the C<keylen> parameter is equal to that output size,
as returned by EVP_KDF_size().
=head1 CONTROLS
The standard controls are:
=over 4
=item B<EVP_KDF_CTRL_SET_PASS>
This control expects two arguments: C<unsigned char *pass>, C<size_t passlen>
Some KDF implementations require a password. For those KDF implementations
that support it, this control sets the password.
EVP_KDF_ctrl_str() takes two type strings for this control:
=over 4
=item "pass"
The value string is used as is.
=item "hexpass"
The value string is expected to be a hexadecimal number, which will be
decoded before being passed on as the control value.
=back
=item B<EVP_KDF_CTRL_SET_SALT>
This control expects two arguments: C<unsigned char *salt>, C<size_t saltlen>
Some KDF implementations can take a salt. For those KDF implementations that
support it, this control sets the salt.
The default value, if any, is implementation dependent.
EVP_KDF_ctrl_str() takes two type strings for this control:
=over 4
=item "salt"
The value string is used as is.
=item "hexsalt"
The value string is expected to be a hexadecimal number, which will be
decoded before being passed on as the control value.
=back
=item B<EVP_KDF_CTRL_SET_ITER>
This control expects one argument: C<int iter>
Some KDF implementations require an iteration count. For those KDF implementations that support it, this control sets the iteration count.
The default value, if any, is implementation dependent.
EVP_KDF_ctrl_str() type string: "iter"
The value string is expected to be a decimal number.
=item B<EVP_KDF_CTRL_SET_MD>
This control expects one argument: C<EVP_MD *md>
For MAC implementations that use a message digest as an underlying computation
algorithm, this control set what the digest algorithm should be.
EVP_KDF_ctrl_str() type string: "md"
The value string is expected to be the name of a digest.
=item B<EVP_KDF_CTRL_SET_KEY>
This control expects two arguments: C<unsigned char *key>, C<size_t keylen>
Some KDF implementations require a key. For those KDF implementations that
support it, this control sets the key.
EVP_KDF_ctrl_str() takes two type strings for this control:
=over 4
=item "key"
The value string is used as is.
=item "hexkey"
The value string is expected to be a hexadecimal number, which will be
decoded before being passed on as the control value.
=back
=item B<EVP_KDF_CTRL_SET_MAXMEM_BYTES>
This control expects one argument: C<uint64_t maxmem_bytes>
Memory-hard password-based KDF algorithms, such as scrypt, use an amount of
memory that depends on the load factors provided as input. For those KDF
implementations that support it, this control sets an upper limit on the amount
of memory that may be consumed while performing a key derivation. If this
memory usage limit is exceeded because the load factors are chosen too high,
the key derivation will fail.
The default value is implementation dependent.
EVP_KDF_ctrl_str() type string: "maxmem_bytes"
The value string is expected to be a decimal number.
=back
=head1 RETURN VALUES
EVP_KDF_CTX_new_id() returns either the newly allocated C<EVP_KDF_CTX>
structure or C<NULL> if an error occurred.
EVP_KDF_CTX_free() and EVP_KDF_reset() do not return a value.
EVP_KDF_size() returns the output size. C<SIZE_MAX> is returned to indicate
that the algorithm produces a variable amount of output; 0 to indicate failure.
The remaining functions return 1 for success and 0 or a negative value for
failure. In particular, a return value of -2 indicates the operation is not
supported by the KDF algorithm.
=head1 SEE ALSO
L<EVP_KDF_SCRYPT(7)>
=head1 COPYRIGHT
Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
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
L<https://www.openssl.org/source/license.html>.
=cut

180
doc/man7/EVP_KDF_HKDF.pod Normal file
View file

@ -0,0 +1,180 @@
=pod
=head1 NAME
EVP_KDF_HKDF - The HKDF EVP_KDF implementation
=head1 DESCRIPTION
Support for computing the B<HKDF> KDF through the B<EVP_KDF> API.
The EVP_KDF_HKDF algorithm implements the HKDF key derivation function.
HKDF follows the "extract-then-expand" paradigm, where the KDF logically
consists of two modules. The first stage takes the input keying material
and "extracts" from it a fixed-length pseudorandom key K. The second stage
"expands" the key K into several additional pseudorandom keys (the output
of the KDF).
=head2 Numeric identity
B<EVP_KDF_HKDF> is the numeric identity for this implementation; it
can be used with the EVP_KDF_CTX_new_id() function.
=head2 Supported controls
The supported controls are:
=over 4
=item B<EVP_KDF_CTRL_SET_SALT>
=item B<EVP_KDF_CTRL_SET_MD>
=item B<EVP_KDF_CTRL_SET_KEY>
These controls work as described in L<EVP_KDF_CTX(3)/CONTROLS>.
=item B<EVP_KDF_CTRL_RESET_HKDF_INFO>
This control does not expect any arguments.
Resets the context info buffer to zero length.
=item B<EVP_KDF_CTRL_ADD_HKDF_INFO>
This control expects two arguments: C<unsigned char *info>, C<size_t infolen>
Sets the info value to the first B<infolen> bytes of the buffer B<info>. If a
value is already set, the contents of the buffer are appended to the existing
value.
The total length of the context info buffer cannot exceed 1024 bytes;
this should be more than enough for any normal use of HKDF.
EVP_KDF_ctrl_str() takes two type strings for this control:
=over 4
=item "info"
The value string is used as is.
=item "hexinfo"
The value string is expected to be a hexadecimal number, which will be
decoded before being passed on as the control value.
=back
=item B<EVP_KDF_CTRL_SET_HKDF_MODE>
This control expects one argument: C<int mode>
Sets the mode for the HKDF operation. There are three modes that are currently
defined:
=over 4
=item EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND
This is the default mode. Calling L<EVP_KDF_derive(3)> on an EVP_KDF_CTX set
up for HKDF will perform an extract followed by an expand operation in one go.
The derived key returned will be the result after the expand operation. The
intermediate fixed-length pseudorandom key K is not returned.
In this mode the digest, key, salt and info values must be set before a key is
derived otherwise an error will occur.
=item EVP_KDF_HKDF_MODE_EXTRACT_ONLY
In this mode calling L<EVP_KDF_derive(3)> will just perform the extract
operation. The value returned will be the intermediate fixed-length pseudorandom
key K. The C<keylen> parameter must match the size of K, which can be looked
up by calling EVP_KDF_size() after setting the mode and digest.
The digest, key and salt values must be set before a key is derived otherwise
an error will occur.
=item EVP_KDF_HKDF_MODE_EXPAND_ONLY
In this mode calling L<EVP_KDF_derive(3)> will just perform the expand
operation. The input key should be set to the intermediate fixed-length
pseudorandom key K returned from a previous extract operation.
The digest, key and info values must be set before a key is derived otherwise
an error will occur.
=back
EVP_KDF_ctrl_str() type string: "mode"
The value string is expected to be one of: "EXTRACT_AND_EXPAND", "EXTRACT_ONLY"
or "EXPAND_ONLY".
=back
=head1 NOTES
A context for HKDF can be obtained by calling:
EVP_KDF_CTX *kctx = EVP_KDF_CTX_new_id(EVP_KDF_HKDF);
The output length of an HKDF expand operation is specified via the C<keylen>
parameter to the L<EVP_KDF_derive(3)> function. When using
EVP_KDF_HKDF_MODE_EXTRACT_ONLY the C<keylen> parameter must equal the size of
the intermediate fixed-length pseudorandom key otherwise an error will occur.
For that mode, the fixed output size can be looked up by calling EVP_KDF_size()
after setting the mode and digest on the C<EVP_KDF_CTX>.
=head1 EXAMPLE
This example derives 10 bytes using SHA-256 with the secret key "secret",
salt value "salt" and info value "label":
EVP_KDF_CTX *kctx;
unsigned char out[10];
kctx = EVP_KDF_CTX_new_id(EVP_KDF_HKDF);
if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MD, EVP_sha256()) <= 0) {
error("EVP_KDF_CTRL_SET_MD");
}
if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SALT, "salt", (size_t)4) <= 0) {
error("EVP_KDF_CTRL_SET_SALT");
}
if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KEY, "secret", (size_t)6) <= 0) {
error("EVP_KDF_CTRL_SET_KEY");
}
if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_ADD_HKDF_INFO, "label", (size_t)5) <= 0) {
error("EVP_KDF_CTRL_ADD_HKDF_INFO");
}
if (EVP_KDF_derive(kctx, out, sizeof(out)) <= 0) {
error("EVP_KDF_derive");
}
EVP_KDF_CTX_free(kctx);
=head1 CONFORMING TO
RFC 5869
=head1 SEE ALSO
L<EVP_KDF_CTX>,
L<EVP_KDF_CTX_new_id(3)>,
L<EVP_KDF_CTX_free(3)>,
L<EVP_KDF_ctrl(3)>,
L<EVP_KDF_size(3)>,
L<EVP_KDF_derive(3)>,
L<EVP_KDF_CTX(3)/CONTROLS>
=head1 COPYRIGHT
Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
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
L<https://www.openssl.org/source/license.html>.
=cut

View file

@ -0,0 +1,78 @@
=pod
=head1 NAME
EVP_KDF_PBKDF2 - The PBKDF2 EVP_KDF implementation
=head1 DESCRIPTION
Support for computing the B<PBKDF2> password-based KDF through the B<EVP_KDF>
API.
The EVP_KDF_PBKDF2 algorithm implements the PBKDF2 password-based key
derivation function, as described in RFC 2898; it derives a key from a password
using a salt and iteration count.
=head2 Numeric identity
B<EVP_KDF_PBKDF2> is the numeric identity for this implementation; it
can be used with the EVP_KDF_CTX_new_id() function.
=head2 Supported controls
The supported controls are:
=over 4
=item B<EVP_KDF_CTRL_SET_PASS>
=item B<EVP_KDF_CTRL_SET_SALT>
=item B<EVP_KDF_CTRL_SET_ITER>
=item B<EVP_KDF_CTRL_SET_MD>
These controls work as described in L<EVP_KDF_CTX(3)/CONTROLS>.
B<iter> is the iteration count and its value should be greater than or equal to
1. RFC 2898 suggests an iteration count of at least 1000. The default value is
2048. Any B<iter> less than 1 is treated as a single iteration.
=back
=head1 NOTES
A typical application of this algorithm is to derive keying material for an
encryption algorithm from a password in the B<pass>, a salt in B<salt>,
and an iteration count.
Increasing the B<iter> parameter slows down the algorithm which makes it
harder for an attacker to perform a brute force attack using a large number
of candidate passwords.
No assumption is made regarding the given password; it is simply treated as a
byte sequence.
=head1 CONFORMING TO
RFC 2898
=head1 SEE ALSO
L<EVP_KDF_CTX>,
L<EVP_KDF_CTX_new_id(3)>,
L<EVP_KDF_CTX_free(3)>,
L<EVP_KDF_ctrl(3)>,
L<EVP_KDF_derive(3)>,
L<EVP_KDF_CTX(3)/CONTROLS>
=head1 COPYRIGHT
Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
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
L<https://www.openssl.org/source/license.html>.
=cut

View file

@ -2,11 +2,14 @@
=head1 NAME
scrypt - EVP_PKEY scrypt KDF support
EVP_KDF_SCRYPT - The scrypt EVP_KDF implementation
=head1 DESCRIPTION
The EVP_PKEY_SCRYPT algorithm implements the scrypt password based key
Support for computing the B<scrypt> password-based KDF through the B<EVP_KDF>
API.
The EVP_KDF_SCRYPT algorithm implements the scrypt password-based key
derivation function, as described in RFC 7914. It is memory-hard in the sense
that it deliberately requires a significant amount of RAM for efficient
computation. The intention of this is to render brute forcing of passwords on
@ -26,49 +29,82 @@ computation time of less than 5 seconds on a 2.5 GHz Intel Core 2 Duo are N =
2^20 = 1048576, r = 8, p = 1. Consequently, the required amount of memory for
this computation is roughly 1 GiB. On a more recent CPU (Intel i7-5930K at 3.5
GHz), this computation takes about 3 seconds. When N, r or p are not specified,
they default to 1048576, 8, and 1, respectively. The default amount of RAM that
they default to 1048576, 8, and 1, respectively. The maximum amount of RAM that
may be used by scrypt defaults to 1025 MiB.
=head2 Numeric identity
B<EVP_KDF_SCRYPT> is the numeric identity for this implementation; it
can be used with the EVP_KDF_CTX_new_id() function.
=head2 Supported controls
The supported controls are:
=over 4
=item B<EVP_KDF_CTRL_SET_PASS>
=item B<EVP_KDF_CTRL_SET_SALT>
These controls work as described in L<EVP_KDF_CTX(3)/CONTROLS>.
=item B<EVP_KDF_CTRL_SET_SCRYPT_N>
=item B<EVP_KDF_CTRL_SET_SCRYPT_R>
=item B<EVP_KDF_CTRL_SET_SCRYPT_P>
B<EVP_KDF_CTRL_SET_SCRYPT_N> expects one argument: C<uint64_t N>
B<EVP_KDF_CTRL_SET_SCRYPT_R> expects one argument: C<uint32_t r>
B<EVP_KDF_CTRL_SET_SCRYPT_P> expects one argument: C<uint32_t p>
These controls configure the scrypt work factors N, r and p.
EVP_KDF_ctrl_str() type strings: "N", "r" and "p", respectively.
The corresponding value strings are expected to be decimal numbers.
=back
=head1 NOTES
A context for scrypt can be obtained by calling:
EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_SCRYPT, NULL);
EVP_KDF_CTX *kctx = EVP_KDF_CTX_new_id(EVP_KDF_SCRYPT);
The output length of an scrypt key derivation is specified via the
length parameter to the L<EVP_PKEY_derive(3)> function.
B<keylen> parameter to the L<EVP_KDF_derive(3)> function.
=head1 EXAMPLE
This example derives a 64-byte long test vector using scrypt using the password
This example derives a 64-byte long test vector using scrypt with the password
"password", salt "NaCl" and N = 1024, r = 8, p = 16.
EVP_PKEY_CTX *pctx;
EVP_KDF_CTX *kctx;
unsigned char out[64];
size_t outlen = sizeof(out);
pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_SCRYPT, NULL);
kctx = EVP_KDF_CTX_new_id(EVP_KDF_SCRYPT);
if (EVP_PKEY_derive_init(pctx) <= 0) {
error("EVP_PKEY_derive_init");
if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_PASS, "password", (size_t)8) <= 0) {
error("EVP_KDF_CTRL_SET_PASS");
}
if (EVP_PKEY_CTX_set1_pbe_pass(pctx, "password", 8) <= 0) {
error("EVP_PKEY_CTX_set1_pbe_pass");
if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SALT, "NaCl", (size_t)4) <= 0) {
error("EVP_KDF_CTRL_SET_SALT");
}
if (EVP_PKEY_CTX_set1_scrypt_salt(pctx, "NaCl", 4) <= 0) {
error("EVP_PKEY_CTX_set1_scrypt_salt");
if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SCRYPT_N, (uint64_t)1024) <= 0) {
error("EVP_KDF_CTRL_SET_SCRYPT_N");
}
if (EVP_PKEY_CTX_set_scrypt_N(pctx, 1024) <= 0) {
error("EVP_PKEY_CTX_set_scrypt_N");
if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SCRYPT_R, (uint32_t)8) <= 0) {
error("EVP_KDF_CTRL_SET_SCRYPT_R");
}
if (EVP_PKEY_CTX_set_scrypt_r(pctx, 8) <= 0) {
error("EVP_PKEY_CTX_set_scrypt_r");
if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SCRYPT_P, (uint32_t)16) <= 0) {
error("EVP_KDF_CTRL_SET_SCRYPT_P");
}
if (EVP_PKEY_CTX_set_scrypt_p(pctx, 16) <= 0) {
error("EVP_PKEY_CTX_set_scrypt_p");
}
if (EVP_PKEY_derive(pctx, out, &outlen) <= 0) {
error("EVP_PKEY_derive");
if (EVP_KDF_derive(kctx, out, sizeof(out)) <= 0) {
error("EVP_KDF_derive");
}
{
@ -86,7 +122,7 @@ This example derives a 64-byte long test vector using scrypt using the password
assert(!memcmp(out, expected, sizeof(out)));
}
EVP_PKEY_CTX_free(pctx);
EVP_KDF_CTX_free(kctx);
=head1 CONFORMING TO
@ -94,14 +130,12 @@ RFC 7914
=head1 SEE ALSO
L<EVP_PKEY_CTX_set1_scrypt_salt(3)>,
L<EVP_PKEY_CTX_set_scrypt_N(3)>,
L<EVP_PKEY_CTX_set_scrypt_r(3)>,
L<EVP_PKEY_CTX_set_scrypt_p(3)>,
L<EVP_PKEY_CTX_set_scrypt_maxmem_bytes(3)>,
L<EVP_PKEY_CTX_new(3)>,
L<EVP_PKEY_CTX_ctrl_str(3)>,
L<EVP_PKEY_derive(3)>
L<EVP_KDF_CTX>,
L<EVP_KDF_CTX_new_id(3)>,
L<EVP_KDF_CTX_free(3)>,
L<EVP_KDF_ctrl(3)>,
L<EVP_KDF_derive(3)>,
L<EVP_KDF_CTX(3)/CONTROLS>
=head1 COPYRIGHT

View file

@ -0,0 +1,142 @@
=pod
=head1 NAME
EVP_KDF_TLS1_PRF - The TLS1 PRF EVP_KDF implementation
=head1 DESCRIPTION
Support for computing the B<TLS1> PRF through the B<EVP_KDF> API.
The EVP_KDF_TLS1_PRF algorithm implements the PRF used by TLS versions up to
and including TLS 1.2.
=head2 Numeric identity
B<EVP_KDF_TLS1_PRF> is the numeric identity for this implementation; it
can be used with the EVP_KDF_CTX_new_id() function.
=head2 Supported controls
The supported controls are:
=over 4
=item B<EVP_KDF_CTRL_SET_MD>
This control works as described in L<EVP_KDF_CTX(3)/CONTROLS>.
The C<EVP_KDF_CTRL_SET_MD> control is used to set the message digest associated
with the TLS PRF. EVP_md5_sha1() is treated as a special case which uses the
PRF algorithm using both B<MD5> and B<SHA1> as used in TLS 1.0 and 1.1.
=item B<EVP_KDF_CTRL_SET_TLS_SECRET>
This control expects two arguments: C<unsigned char *sec>, C<size_t seclen>
Sets the secret value of the TLS PRF to B<seclen> bytes of the buffer B<sec>.
Any existing secret value is replaced.
EVP_KDF_ctrl_str() takes two type strings for this control:
=over 4
=item "secret"
The value string is used as is.
=item "hexsecret"
The value string is expected to be a hexadecimal number, which will be
decoded before being passed on as the control value.
=back
=item B<EVP_KDF_CTRL_RESET_TLS_SEED>
This control does not expect any arguments.
Resets the context seed buffer to zero length.
=item B<EVP_KDF_CTRL_ADD_TLS_SEED>
This control expects two arguments: C<unsigned char *seed>, C<size_t seedlen>
Sets the seed to B<seedlen> bytes of B<seed>. If a seed is already set it is
appended to the existing value.
The total length of the context seed buffer cannot exceed 1024 bytes;
this should be more than enough for any normal use of the TLS PRF.
EVP_KDF_ctrl_str() takes two type strings for this control:
=over 4
=item "seed"
The value string is used as is.
=item "hexseed"
The value string is expected to be a hexadecimal number, which will be
decoded before being passed on as the control value.
=back
=back
=head1 NOTES
A context for the TLS PRF can be obtained by calling:
EVP_KDF_CTX *kctx = EVP_KDF_CTX_new_id(EVP_KDF_TLS1_PRF, NULL);
The digest, secret value and seed must be set before a key is derived otherwise
an error will occur.
The output length of the PRF is specified by the C<keylen> parameter to the
EVP_KDF_derive() function.
=head1 EXAMPLE
This example derives 10 bytes using SHA-256 with the secret key "secret"
and seed value "seed":
EVP_KDF_CTX *kctx;
unsigned char out[10];
kctx = EVP_KDF_CTX_new_id(EVP_KDF_TLS1_PRF);
if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MD, EVP_sha256()) <= 0) {
error("EVP_KDF_CTRL_SET_MD");
}
if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_TLS_SECRET,
"secret", (size_t)6) <= 0) {
error("EVP_KDF_CTRL_SET_TLS_SECRET");
}
if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_ADD_TLS_SEED, "seed", (size_t)4) <= 0) {
error("EVP_KDF_CTRL_ADD_TLS_SEED");
}
if (EVP_KDF_derive(kctx, out, sizeof(out)) <= 0) {
error("EVP_KDF_derive");
}
EVP_KDF_CTX_free(kctx);
=head1 SEE ALSO
L<EVP_KDF_CTX>,
L<EVP_KDF_CTX_new_id(3)>,
L<EVP_KDF_CTX_free(3)>,
L<EVP_KDF_ctrl(3)>,
L<EVP_KDF_derive(3)>,
L<EVP_KDF_CTX(3)/CONTROLS>
=head1 COPYRIGHT
Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
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
L<https://www.openssl.org/source/license.html>.
=cut

View file

@ -1,6 +1,6 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* 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
@ -55,6 +55,9 @@ int ERR_load_EVP_strings(void);
# define EVP_F_EVP_ENCRYPTDECRYPTUPDATE 219
# define EVP_F_EVP_ENCRYPTFINAL_EX 127
# define EVP_F_EVP_ENCRYPTUPDATE 167
# define EVP_F_EVP_KDF_CTRL 224
# define EVP_F_EVP_KDF_CTRL_STR 225
# define EVP_F_EVP_KDF_CTX_NEW_ID 226
# define EVP_F_EVP_MAC_CTRL 209
# define EVP_F_EVP_MAC_CTRL_STR 210
# define EVP_F_EVP_MAC_CTX_COPY 211
@ -125,6 +128,7 @@ int ERR_load_EVP_strings(void);
# define EVP_F_PKCS5_V2_PBE_KEYIVGEN 118
# define EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN 164
# define EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN 180
# define EVP_F_PKEY_KDF_CTRL 227
# define EVP_F_PKEY_MAC_INIT 214
# define EVP_F_PKEY_SET_TYPE 158
# define EVP_F_POLY1305_CTRL 216
@ -132,6 +136,7 @@ int ERR_load_EVP_strings(void);
# define EVP_F_RC5_CTRL 125
# define EVP_F_S390X_AES_GCM_CTRL 201
# define EVP_F_S390X_AES_GCM_TLS_CIPHER 208
# define EVP_F_SCRYPT_ALG 228
# define EVP_F_UPDATE 173
/*
@ -188,6 +193,7 @@ int ERR_load_EVP_strings(void);
# define EVP_R_ONLY_ONESHOT_SUPPORTED 177
# define EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE 150
# define EVP_R_OPERATON_NOT_INITIALIZED 151
# define EVP_R_PARAMETER_TOO_LARGE 187
# define EVP_R_PARTIALLY_OVERLAPPING 162
# define EVP_R_PBKDF2_ERROR 181
# define EVP_R_PKEY_APPLICATION_ASN1_METHOD_ALREADY_REGISTERED 179

View file

@ -10,10 +10,50 @@
#ifndef HEADER_KDF_H
# define HEADER_KDF_H
# include <openssl/ossl_typ.h>
# include <openssl/kdferr.h>
#ifdef __cplusplus
# ifdef __cplusplus
extern "C" {
#endif
# endif
# define EVP_KDF_PBKDF2 NID_id_pbkdf2
# define EVP_KDF_SCRYPT NID_id_scrypt
# define EVP_KDF_TLS1_PRF NID_tls1_prf
# define EVP_KDF_HKDF NID_hkdf
EVP_KDF_CTX *EVP_KDF_CTX_new_id(int id);
void EVP_KDF_CTX_free(EVP_KDF_CTX *ctx);
void EVP_KDF_reset(EVP_KDF_CTX *ctx);
int EVP_KDF_ctrl(EVP_KDF_CTX *ctx, int cmd, ...);
int EVP_KDF_vctrl(EVP_KDF_CTX *ctx, int cmd, va_list args);
int EVP_KDF_ctrl_str(EVP_KDF_CTX *ctx, const char *type, const char *value);
size_t EVP_KDF_size(EVP_KDF_CTX *ctx);
int EVP_KDF_derive(EVP_KDF_CTX *ctx, unsigned char *key, size_t keylen);
# define EVP_KDF_CTRL_SET_PASS 0x01 /* unsigned char *, size_t */
# define EVP_KDF_CTRL_SET_SALT 0x02 /* unsigned char *, size_t */
# define EVP_KDF_CTRL_SET_ITER 0x03 /* int */
# define EVP_KDF_CTRL_SET_MD 0x04 /* EVP_MD * */
# define EVP_KDF_CTRL_SET_KEY 0x05 /* unsigned char *, size_t */
# define EVP_KDF_CTRL_SET_MAXMEM_BYTES 0x06 /* uint64_t */
# define EVP_KDF_CTRL_SET_TLS_SECRET 0x07 /* unsigned char *, size_t */
# define EVP_KDF_CTRL_RESET_TLS_SEED 0x08
# define EVP_KDF_CTRL_ADD_TLS_SEED 0x09 /* unsigned char *, size_t */
# define EVP_KDF_CTRL_RESET_HKDF_INFO 0x0a
# define EVP_KDF_CTRL_ADD_HKDF_INFO 0x0b /* unsigned char *, size_t */
# define EVP_KDF_CTRL_SET_HKDF_MODE 0x0c /* int */
# define EVP_KDF_CTRL_SET_SCRYPT_N 0x0d /* uint64_t */
# define EVP_KDF_CTRL_SET_SCRYPT_R 0x0e /* uint32_t */
# define EVP_KDF_CTRL_SET_SCRYPT_P 0x0f /* uint32_t */
# define EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND 0
# define EVP_KDF_HKDF_MODE_EXTRACT_ONLY 1
# define EVP_KDF_HKDF_MODE_EXPAND_ONLY 2
/**** The legacy PKEY-based KDF API follows. ****/
# define EVP_PKEY_CTRL_TLS_MD (EVP_PKEY_ALG_CTRL)
# define EVP_PKEY_CTRL_TLS_SECRET (EVP_PKEY_ALG_CTRL + 1)
@ -30,9 +70,12 @@ extern "C" {
# define EVP_PKEY_CTRL_SCRYPT_P (EVP_PKEY_ALG_CTRL + 12)
# define EVP_PKEY_CTRL_SCRYPT_MAXMEM_BYTES (EVP_PKEY_ALG_CTRL + 13)
# define EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND 0
# define EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY 1
# define EVP_PKEY_HKDEF_MODE_EXPAND_ONLY 2
# define EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND \
EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND
# define EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY \
EVP_KDF_HKDF_MODE_EXTRACT_ONLY
# define EVP_PKEY_HKDEF_MODE_EXPAND_ONLY \
EVP_KDF_HKDF_MODE_EXPAND_ONLY
# define EVP_PKEY_CTX_set_tls1_prf_md(pctx, md) \
EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \
@ -91,7 +134,7 @@ extern "C" {
EVP_PKEY_CTRL_SCRYPT_MAXMEM_BYTES, maxmem_bytes)
# ifdef __cplusplus
# ifdef __cplusplus
}
# endif
#endif

View file

@ -1,6 +1,6 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* 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
@ -19,6 +19,23 @@ int ERR_load_KDF_strings(void);
/*
* KDF function codes.
*/
# define KDF_F_HKDF_EXTRACT 112
# define KDF_F_KDF_HKDF_DERIVE 113
# define KDF_F_KDF_HKDF_NEW 114
# define KDF_F_KDF_HKDF_SIZE 115
# define KDF_F_KDF_MD2CTRL 116
# define KDF_F_KDF_PBKDF2_CTRL_STR 117
# define KDF_F_KDF_PBKDF2_DERIVE 118
# define KDF_F_KDF_PBKDF2_NEW 119
# define KDF_F_KDF_SCRYPT_CTRL_STR 120
# define KDF_F_KDF_SCRYPT_CTRL_UINT32 121
# define KDF_F_KDF_SCRYPT_CTRL_UINT64 122
# define KDF_F_KDF_SCRYPT_DERIVE 123
# define KDF_F_KDF_SCRYPT_NEW 124
# define KDF_F_KDF_TLS1_PRF_CTRL_STR 125
# define KDF_F_KDF_TLS1_PRF_DERIVE 126
# define KDF_F_KDF_TLS1_PRF_NEW 127
# define KDF_F_PBKDF2_SET_MEMBUF 128
# define KDF_F_PKEY_HKDF_CTRL_STR 103
# define KDF_F_PKEY_HKDF_DERIVE 102
# define KDF_F_PKEY_HKDF_INIT 108
@ -30,6 +47,7 @@ int ERR_load_KDF_strings(void);
# define KDF_F_PKEY_TLS1_PRF_CTRL_STR 100
# define KDF_F_PKEY_TLS1_PRF_DERIVE 101
# define KDF_F_PKEY_TLS1_PRF_INIT 110
# define KDF_F_SCRYPT_SET_MEMBUF 129
# define KDF_F_TLS1_PRF_ALG 111
/*
@ -47,5 +65,6 @@ int ERR_load_KDF_strings(void);
# define KDF_R_UNKNOWN_PARAMETER_TYPE 103
# define KDF_R_VALUE_ERROR 108
# define KDF_R_VALUE_MISSING 102
# define KDF_R_WRONG_OUTPUT_BUFFER_SIZE 112
#endif

View file

@ -99,6 +99,8 @@ typedef struct evp_pkey_asn1_method_st EVP_PKEY_ASN1_METHOD;
typedef struct evp_pkey_method_st EVP_PKEY_METHOD;
typedef struct evp_pkey_ctx_st EVP_PKEY_CTX;
typedef struct evp_kdf_ctx_st EVP_KDF_CTX;
typedef struct evp_Encode_Ctx_st EVP_ENCODE_CTX;
typedef struct hmac_ctx_st HMAC_CTX;

View file

@ -38,7 +38,8 @@ IF[{- !$disabled{tests} -}]
ssl_test_ctx_test ssl_test x509aux cipherlist_test asynciotest \
bio_callback_test bio_memleak_test \
bioprinttest sslapitest dtlstest sslcorrupttest bio_enc_test \
pkey_meth_test pkey_meth_kdf_test uitest cipherbytes_test \
pkey_meth_test pkey_meth_kdf_test evp_kdf_test uitest \
cipherbytes_test \
asn1_encode_test asn1_decode_test asn1_string_table_test \
x509_time_test x509_dup_cert_test x509_check_cert_pkey_test \
recordlentest drbgtest sslbuffertest \
@ -330,6 +331,10 @@ IF[{- !$disabled{tests} -}]
INCLUDE[pkey_meth_kdf_test]=../include ../apps/include
DEPEND[pkey_meth_kdf_test]=../libcrypto libtestutil.a
SOURCE[evp_kdf_test]=evp_kdf_test.c
INCLUDE[evp_kdf_test]=../include
DEPEND[evp_kdf_test]=../libcrypto libtestutil.a
SOURCE[x509_time_test]=x509_time_test.c
INCLUDE[x509_time_test]=../include ../apps/include
DEPEND[x509_time_test]=../libcrypto libtestutil.a

237
test/evp_kdf_test.c Normal file
View file

@ -0,0 +1,237 @@
/*
* Copyright 2018-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2018-2019, Oracle and/or its affiliates. All rights reserved.
*
* 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
*/
/* Tests of the EVP_KDF_CTX APIs */
#include <stdio.h>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/kdf.h>
#include "testutil.h"
static int test_kdf_tls1_prf(void)
{
int ret = 0;
EVP_KDF_CTX *kctx;
unsigned char out[16];
if ((kctx = EVP_KDF_CTX_new_id(EVP_KDF_TLS1_PRF)) == NULL) {
TEST_error("EVP_KDF_TLS1_PRF");
goto err;
}
if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MD, EVP_sha256()) <= 0) {
TEST_error("EVP_KDF_CTRL_SET_MD");
goto err;
}
if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_TLS_SECRET,
"secret", (size_t)6) <= 0) {
TEST_error("EVP_KDF_CTRL_SET_TLS_SECRET");
goto err;
}
if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_ADD_TLS_SEED, "seed", (size_t)4) <= 0) {
TEST_error("EVP_KDF_CTRL_ADD_TLS_SEED");
goto err;
}
if (EVP_KDF_derive(kctx, out, sizeof(out)) <= 0) {
TEST_error("EVP_KDF_derive");
goto err;
}
{
const unsigned char expected[sizeof(out)] = {
0x8e, 0x4d, 0x93, 0x25, 0x30, 0xd7, 0x65, 0xa0,
0xaa, 0xe9, 0x74, 0xc3, 0x04, 0x73, 0x5e, 0xcc
};
if (!TEST_mem_eq(out, sizeof(out), expected, sizeof(expected))) {
goto err;
}
}
ret = 1;
err:
EVP_KDF_CTX_free(kctx);
return ret;
}
static int test_kdf_hkdf(void)
{
int ret = 0;
EVP_KDF_CTX *kctx;
unsigned char out[10];
if ((kctx = EVP_KDF_CTX_new_id(EVP_KDF_HKDF)) == NULL) {
TEST_error("EVP_KDF_HKDF");
goto err;
}
if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MD, EVP_sha256()) <= 0) {
TEST_error("EVP_KDF_CTRL_SET_MD");
goto err;
}
if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SALT, "salt", (size_t)4) <= 0) {
TEST_error("EVP_KDF_CTRL_SET_SALT");
goto err;
}
if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KEY, "secret", (size_t)6) <= 0) {
TEST_error("EVP_KDF_CTRL_SET_KEY");
goto err;
}
if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_ADD_HKDF_INFO,
"label", (size_t)5) <= 0) {
TEST_error("EVP_KDF_CTRL_ADD_HKDF_INFO");
goto err;
}
if (EVP_KDF_derive(kctx, out, sizeof(out)) <= 0) {
TEST_error("EVP_KDF_derive");
goto err;
}
{
const unsigned char expected[sizeof(out)] = {
0x2a, 0xc4, 0x36, 0x9f, 0x52, 0x59, 0x96, 0xf8, 0xde, 0x13
};
if (!TEST_mem_eq(out, sizeof(out), expected, sizeof(expected))) {
goto err;
}
}
ret = 1;
err:
EVP_KDF_CTX_free(kctx);
return ret;
}
static int test_kdf_pbkdf2(void)
{
int ret = 0;
EVP_KDF_CTX *kctx;
unsigned char out[32];
if ((kctx = EVP_KDF_CTX_new_id(EVP_KDF_PBKDF2)) == NULL) {
TEST_error("EVP_KDF_PBKDF2");
goto err;
}
if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_PASS, "password", (size_t)8) <= 0) {
TEST_error("EVP_KDF_CTRL_SET_PASS");
goto err;
}
if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SALT, "salt", (size_t)4) <= 0) {
TEST_error("EVP_KDF_CTRL_SET_SALT");
goto err;
}
if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_ITER, 2) <= 0) {
TEST_error("EVP_KDF_CTRL_SET_ITER");
goto err;
}
if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MD, EVP_sha256()) <= 0) {
TEST_error("EVP_KDF_CTRL_SET_MD");
goto err;
}
if (EVP_KDF_derive(kctx, out, sizeof(out)) <= 0) {
TEST_error("EVP_KDF_derive");
goto err;
}
{
const unsigned char expected[sizeof(out)] = {
0xae, 0x4d, 0x0c, 0x95, 0xaf, 0x6b, 0x46, 0xd3,
0x2d, 0x0a, 0xdf, 0xf9, 0x28, 0xf0, 0x6d, 0xd0,
0x2a, 0x30, 0x3f, 0x8e, 0xf3, 0xc2, 0x51, 0xdf,
0xd6, 0xe2, 0xd8, 0x5a, 0x95, 0x47, 0x4c, 0x43
};
if (!TEST_mem_eq(out, sizeof(out), expected, sizeof(expected))) {
goto err;
}
}
ret = 1;
err:
EVP_KDF_CTX_free(kctx);
return ret;
}
#ifndef OPENSSL_NO_SCRYPT
static int test_kdf_scrypt(void)
{
int ret = 0;
EVP_KDF_CTX *kctx;
unsigned char out[64];
if ((kctx = EVP_KDF_CTX_new_id(EVP_KDF_SCRYPT)) == NULL) {
TEST_error("EVP_KDF_SCRYPT");
goto err;
}
if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_PASS, "password", (size_t)8) <= 0) {
TEST_error("EVP_KDF_CTRL_SET_PASS");
goto err;
}
if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SALT, "NaCl", (size_t)4) <= 0) {
TEST_error("EVP_KDF_CTRL_SET_SALT");
goto err;
}
if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SCRYPT_N, (uint64_t)1024) <= 0) {
TEST_error("EVP_KDF_CTRL_SET_SCRYPT_N");
goto err;
}
if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SCRYPT_R, (uint32_t)8) <= 0) {
TEST_error("EVP_KDF_CTRL_SET_SCRYPT_R");
goto err;
}
if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SCRYPT_P, (uint32_t)16) <= 0) {
TEST_error("EVP_KDF_CTRL_SET_SCRYPT_P");
goto err;
}
if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MAXMEM_BYTES, (uint64_t)16) <= 0) {
TEST_error("EVP_KDF_CTRL_SET_MAXMEM_BYTES");
goto err;
}
if (EVP_KDF_derive(kctx, out, sizeof(out)) > 0) {
TEST_error("EVP_KDF_derive should have failed");
goto err;
}
if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MAXMEM_BYTES,
(uint64_t)(10 * 1024 * 1024)) <= 0) {
TEST_error("EVP_KDF_CTRL_SET_MAXMEM_BYTES");
goto err;
}
if (EVP_KDF_derive(kctx, out, sizeof(out)) <= 0) {
TEST_error("EVP_KDF_derive");
goto err;
}
{
const unsigned char expected[sizeof(out)] = {
0xfd, 0xba, 0xbe, 0x1c, 0x9d, 0x34, 0x72, 0x00,
0x78, 0x56, 0xe7, 0x19, 0x0d, 0x01, 0xe9, 0xfe,
0x7c, 0x6a, 0xd7, 0xcb, 0xc8, 0x23, 0x78, 0x30,
0xe7, 0x73, 0x76, 0x63, 0x4b, 0x37, 0x31, 0x62,
0x2e, 0xaf, 0x30, 0xd9, 0x2e, 0x22, 0xa3, 0x88,
0x6f, 0xf1, 0x09, 0x27, 0x9d, 0x98, 0x30, 0xda,
0xc7, 0x27, 0xaf, 0xb9, 0x4a, 0x83, 0xee, 0x6d,
0x83, 0x60, 0xcb, 0xdf, 0xa2, 0xcc, 0x06, 0x40
};
if (!TEST_mem_eq(out, sizeof(out), expected, sizeof(expected))) {
goto err;
}
}
ret = 1;
err:
EVP_KDF_CTX_free(kctx);
return ret;
}
#endif
int setup_tests(void)
{
ADD_TEST(test_kdf_tls1_prf);
ADD_TEST(test_kdf_hkdf);
ADD_TEST(test_kdf_pbkdf2);
#ifndef OPENSSL_NO_SCRYPT
ADD_TEST(test_kdf_scrypt);
#endif
return 1;
}

View file

@ -1892,13 +1892,14 @@ static const EVP_TEST_METHOD encode_test_method = {
encode_test_run,
};
/**
*** KDF TESTS
**/
typedef struct kdf_data_st {
/* Context for this operation */
EVP_PKEY_CTX *ctx;
EVP_KDF_CTX *ctx;
/* Expected output */
unsigned char *output;
size_t output_len;
@ -1913,6 +1914,137 @@ static int kdf_test_init(EVP_TEST *t, const char *name)
KDF_DATA *kdata;
int kdf_nid = OBJ_sn2nid(name);
#ifdef OPENSSL_NO_SCRYPT
if (strcmp(name, "scrypt") == 0) {
t->skip = 1;
return 1;
}
#endif
if (kdf_nid == NID_undef)
kdf_nid = OBJ_ln2nid(name);
if (!TEST_ptr(kdata = OPENSSL_zalloc(sizeof(*kdata))))
return 0;
kdata->ctx = EVP_KDF_CTX_new_id(kdf_nid);
if (kdata->ctx == NULL) {
OPENSSL_free(kdata);
return 0;
}
t->data = kdata;
return 1;
}
static void kdf_test_cleanup(EVP_TEST *t)
{
KDF_DATA *kdata = t->data;
OPENSSL_free(kdata->output);
EVP_KDF_CTX_free(kdata->ctx);
}
static int kdf_test_ctrl(EVP_TEST *t, EVP_KDF_CTX *kctx,
const char *value)
{
int rv;
char *p, *tmpval;
if (!TEST_ptr(tmpval = OPENSSL_strdup(value)))
return 0;
p = strchr(tmpval, ':');
if (p != NULL)
*p++ = '\0';
rv = EVP_KDF_ctrl_str(kctx, tmpval, p);
if (rv == -2) {
t->err = "KDF_CTRL_INVALID";
rv = 1;
} else if (p != NULL && rv <= 0) {
/* If p has an OID and lookup fails assume disabled algorithm */
int nid = OBJ_sn2nid(p);
if (nid == NID_undef)
nid = OBJ_ln2nid(p);
if (nid != NID_undef
&& EVP_get_digestbynid(nid) == NULL
&& EVP_get_cipherbynid(nid) == NULL) {
t->skip = 1;
rv = 1;
} else {
t->err = "KDF_CTRL_ERROR";
rv = 1;
}
}
OPENSSL_free(tmpval);
return rv > 0;
}
static int kdf_test_parse(EVP_TEST *t,
const char *keyword, const char *value)
{
KDF_DATA *kdata = t->data;
if (strcmp(keyword, "Output") == 0)
return parse_bin(value, &kdata->output, &kdata->output_len);
if (strncmp(keyword, "Ctrl", 4) == 0)
return kdf_test_ctrl(t, kdata->ctx, value);
return 0;
}
static int kdf_test_run(EVP_TEST *t)
{
KDF_DATA *expected = t->data;
unsigned char *got = NULL;
size_t got_len = expected->output_len;
if (!TEST_ptr(got = OPENSSL_malloc(got_len))) {
t->err = "INTERNAL_ERROR";
goto err;
}
if (EVP_KDF_derive(expected->ctx, got, got_len) <= 0) {
t->err = "KDF_DERIVE_ERROR";
goto err;
}
if (!memory_err_compare(t, "KDF_MISMATCH",
expected->output, expected->output_len,
got, got_len))
goto err;
t->err = NULL;
err:
OPENSSL_free(got);
return 1;
}
static const EVP_TEST_METHOD kdf_test_method = {
"KDF",
kdf_test_init,
kdf_test_cleanup,
kdf_test_parse,
kdf_test_run
};
/**
*** PKEY KDF TESTS
**/
typedef struct pkey_kdf_data_st {
/* Context for this operation */
EVP_PKEY_CTX *ctx;
/* Expected output */
unsigned char *output;
size_t output_len;
} PKEY_KDF_DATA;
/*
* Perform public key operation setup: lookup key, allocated ctx and call
* the appropriate initialisation function
*/
static int pkey_kdf_test_init(EVP_TEST *t, const char *name)
{
PKEY_KDF_DATA *kdata;
int kdf_nid = OBJ_sn2nid(name);
#ifdef OPENSSL_NO_SCRYPT
if (strcmp(name, "scrypt") == 0) {
t->skip = 1;
@ -1939,17 +2071,17 @@ static int kdf_test_init(EVP_TEST *t, const char *name)
return 1;
}
static void kdf_test_cleanup(EVP_TEST *t)
static void pkey_kdf_test_cleanup(EVP_TEST *t)
{
KDF_DATA *kdata = t->data;
PKEY_KDF_DATA *kdata = t->data;
OPENSSL_free(kdata->output);
EVP_PKEY_CTX_free(kdata->ctx);
}
static int kdf_test_parse(EVP_TEST *t,
const char *keyword, const char *value)
static int pkey_kdf_test_parse(EVP_TEST *t,
const char *keyword, const char *value)
{
KDF_DATA *kdata = t->data;
PKEY_KDF_DATA *kdata = t->data;
if (strcmp(keyword, "Output") == 0)
return parse_bin(value, &kdata->output, &kdata->output_len);
@ -1958,9 +2090,9 @@ static int kdf_test_parse(EVP_TEST *t,
return 0;
}
static int kdf_test_run(EVP_TEST *t)
static int pkey_kdf_test_run(EVP_TEST *t)
{
KDF_DATA *expected = t->data;
PKEY_KDF_DATA *expected = t->data;
unsigned char *got = NULL;
size_t got_len = expected->output_len;
@ -1972,11 +2104,10 @@ static int kdf_test_run(EVP_TEST *t)
t->err = "KDF_DERIVE_ERROR";
goto err;
}
if (!memory_err_compare(t, "KDF_MISMATCH",
expected->output, expected->output_len,
got, got_len))
if (!TEST_mem_eq(expected->output, expected->output_len, got, got_len)) {
t->err = "KDF_MISMATCH";
goto err;
}
t->err = NULL;
err:
@ -1984,12 +2115,12 @@ static int kdf_test_run(EVP_TEST *t)
return 1;
}
static const EVP_TEST_METHOD kdf_test_method = {
"KDF",
kdf_test_init,
kdf_test_cleanup,
kdf_test_parse,
kdf_test_run
static const EVP_TEST_METHOD pkey_kdf_test_method = {
"PKEYKDF",
pkey_kdf_test_init,
pkey_kdf_test_cleanup,
pkey_kdf_test_parse,
pkey_kdf_test_run
};
@ -2497,6 +2628,7 @@ static const EVP_TEST_METHOD *evp_test_list[] = {
&digestverify_test_method,
&encode_test_method,
&kdf_test_method,
&pkey_kdf_test_method,
&keypair_test_method,
&keygen_test_method,
&mac_test_method,

View file

@ -1,5 +1,5 @@
/*
* Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* 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
@ -18,30 +18,34 @@
static int test_kdf_tls1_prf(void)
{
int ret = 0;
EVP_PKEY_CTX *pctx;
unsigned char out[16];
size_t outlen = sizeof(out);
pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_TLS1_PRF, NULL);
if ((pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_TLS1_PRF, NULL)) == NULL) {
TEST_error("EVP_PKEY_TLS1_PRF");
goto err;
}
if (EVP_PKEY_derive_init(pctx) <= 0) {
TEST_error("EVP_PKEY_derive_init");
return 0;
goto err;
}
if (EVP_PKEY_CTX_set_tls1_prf_md(pctx, EVP_sha256()) <= 0) {
TEST_error("EVP_PKEY_CTX_set_tls1_prf_md");
return 0;
goto err;
}
if (EVP_PKEY_CTX_set1_tls1_prf_secret(pctx, "secret", 6) <= 0) {
TEST_error("EVP_PKEY_CTX_set1_tls1_prf_secret");
return 0;
goto err;
}
if (EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, "seed", 4) <= 0) {
TEST_error("EVP_PKEY_CTX_add1_tls1_prf_seed");
return 0;
goto err;
}
if (EVP_PKEY_derive(pctx, out, &outlen) <= 0) {
TEST_error("EVP_PKEY_derive");
return 0;
goto err;
}
{
@ -50,43 +54,49 @@ static int test_kdf_tls1_prf(void)
0xaa, 0xe9, 0x74, 0xc3, 0x04, 0x73, 0x5e, 0xcc
};
if (!TEST_mem_eq(out, sizeof(out), expected, sizeof(expected))) {
return 0;
goto err;
}
}
ret = 1;
err:
EVP_PKEY_CTX_free(pctx);
return 1;
return ret;
}
static int test_kdf_hkdf(void)
{
int ret = 0;
EVP_PKEY_CTX *pctx;
unsigned char out[10];
size_t outlen = sizeof(out);
pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL);
if ((pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL)) == NULL) {
TEST_error("EVP_PKEY_HKDF");
goto err;
}
if (EVP_PKEY_derive_init(pctx) <= 0) {
TEST_error("EVP_PKEY_derive_init");
return 0;
goto err;
}
if (EVP_PKEY_CTX_set_hkdf_md(pctx, EVP_sha256()) <= 0) {
TEST_error("EVP_PKEY_CTX_set_hkdf_md");
return 0;
goto err;
}
if (EVP_PKEY_CTX_set1_hkdf_salt(pctx, "salt", 4) <= 0) {
TEST_error("EVP_PKEY_CTX_set1_hkdf_salt");
return 0;
goto err;
}
if (EVP_PKEY_CTX_set1_hkdf_key(pctx, "secret", 6) <= 0) {
TEST_error("EVP_PKEY_CTX_set1_hkdf_key");
return 0;
goto err;
}
if (EVP_PKEY_CTX_add1_hkdf_info(pctx, "label", 5) <= 0) {
TEST_error("EVP_PKEY_CTX_set1_hkdf_info");
return 0;
goto err;
}
if (EVP_PKEY_derive(pctx, out, &outlen) <= 0) {
TEST_error("EVP_PKEY_derive");
return 0;
goto err;
}
{
@ -94,60 +104,66 @@ static int test_kdf_hkdf(void)
0x2a, 0xc4, 0x36, 0x9f, 0x52, 0x59, 0x96, 0xf8, 0xde, 0x13
};
if (!TEST_mem_eq(out, sizeof(out), expected, sizeof(expected))) {
return 0;
goto err;
}
}
ret = 1;
err:
EVP_PKEY_CTX_free(pctx);
return 1;
return ret;
}
#ifndef OPENSSL_NO_SCRYPT
static int test_kdf_scrypt(void)
{
int ret = 0;
EVP_PKEY_CTX *pctx;
unsigned char out[64];
size_t outlen = sizeof(out);
pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_SCRYPT, NULL);
if ((pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_SCRYPT, NULL)) == NULL) {
TEST_error("EVP_PKEY_SCRYPT");
goto err;
}
if (EVP_PKEY_derive_init(pctx) <= 0) {
TEST_error("EVP_PKEY_derive_init");
return 0;
goto err;
}
if (EVP_PKEY_CTX_set1_pbe_pass(pctx, "password", 8) <= 0) {
TEST_error("EVP_PKEY_CTX_set1_pbe_pass");
return 0;
goto err;
}
if (EVP_PKEY_CTX_set1_scrypt_salt(pctx, "NaCl", 4) <= 0) {
TEST_error("EVP_PKEY_CTX_set1_scrypt_salt");
return 0;
goto err;
}
if (EVP_PKEY_CTX_set_scrypt_N(pctx, 1024) <= 0) {
TEST_error("EVP_PKEY_CTX_set_scrypt_N");
return 0;
goto err;
}
if (EVP_PKEY_CTX_set_scrypt_r(pctx, 8) <= 0) {
TEST_error("EVP_PKEY_CTX_set_scrypt_r");
return 0;
goto err;
}
if (EVP_PKEY_CTX_set_scrypt_p(pctx, 16) <= 0) {
TEST_error("EVP_PKEY_CTX_set_scrypt_p");
return 0;
goto err;
}
if (EVP_PKEY_CTX_set_scrypt_maxmem_bytes(pctx, 16) <= 0) {
TEST_error("EVP_PKEY_CTX_set_maxmem_bytes");
return 0;
goto err;
}
if (EVP_PKEY_derive(pctx, out, &outlen) > 0) {
TEST_error("EVP_PKEY_derive should have failed");
return 0;
goto err;
}
if (EVP_PKEY_CTX_set_scrypt_maxmem_bytes(pctx, 10 * 1024 * 1024) <= 0) {
TEST_error("EVP_PKEY_CTX_set_maxmem_bytes");
return 0;
goto err;
}
if (EVP_PKEY_derive(pctx, out, &outlen) <= 0) {
TEST_error("EVP_PKEY_derive");
return 0;
goto err;
}
{
@ -162,11 +178,13 @@ static int test_kdf_scrypt(void)
0x83, 0x60, 0xcb, 0xdf, 0xa2, 0xcc, 0x06, 0x40
};
if (!TEST_mem_eq(out, sizeof(out), expected, sizeof(expected))) {
return 0;
goto err;
}
}
ret = 1;
err:
EVP_PKEY_CTX_free(pctx);
return 1;
return ret;
}
#endif

View file

@ -15,8 +15,8 @@ use OpenSSL::Test qw/:DEFAULT data_file/;
setup("test_evp");
my @files = ( "evpciph.txt", "evpdigest.txt", "evpencod.txt", "evpkdf.txt",
"evpmac.txt", "evppbe.txt", "evppkey.txt", "evppkey_ecc.txt",
"evpcase.txt", "evpaessiv.txt" );
"evppkey_kdf.txt", "evpmac.txt", "evppbe.txt", "evppkey.txt",
"evppkey_ecc.txt", "evpcase.txt", "evpaessiv.txt" );
plan tests => scalar(@files);

View file

@ -1,5 +1,5 @@
#
# Copyright 2001-2017 The OpenSSL Project Authors. All Rights Reserved.
# Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
#
# 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
@ -15,7 +15,7 @@
Title = TLS1 PRF tests (from NIST test vectors)
KDF=TLS1-PRF
Ctrl.md = md:MD5-SHA1
Ctrl.digest = digest:MD5-SHA1
Ctrl.Secret = hexsecret:bded7fa5c1699c010be23dd06ada3a48349f21e5f86263d512c0c5cc379f0e780ec55d9844b2f1db02a96453513568d0
Ctrl.label = seed:master secret
Ctrl.client_random = hexseed:e5acaf549cd25c22d964c0d930fa4b5261d2507fad84c33715b7b9a864020693
@ -23,7 +23,7 @@ Ctrl.server_random = hexseed:135e4d557fdf3aa6406d82975d5c606a9734c9334b42136e969
Output = 2f6962dfbc744c4b2138bb6b3d33054c5ecc14f24851d9896395a44ab3964efc2090c5bf51a0891209f46c1e1e998f62
KDF=TLS1-PRF
Ctrl.md = md:MD5-SHA1
Ctrl.digest = digest:MD5-SHA1
Ctrl.Secret = hexsecret:2f6962dfbc744c4b2138bb6b3d33054c5ecc14f24851d9896395a44ab3964efc2090c5bf51a0891209f46c1e1e998f62
Ctrl.label = seed:key expansion
Ctrl.server_random = hexseed:67267e650eb32444119d222a368c191af3082888dc35afe8368e638c828874be
@ -31,7 +31,7 @@ Ctrl.client_random = hexseed:d58a7b1cd4fedaa232159df652ce188f9d997e061b9bf48e83b
Output = 3088825988e77fce68d19f756e18e43eb7fe672433504feaf99b3c503d9091b164f166db301d70c9fc0870b4a94563907bee1a61fb786cb717576890bcc51cb9ead97e01d0a2fea99c953377b195205ff07b369589178796edc963fd80fdbe518a2fc1c35c18ae8d
KDF=TLS1-PRF
Ctrl.md = md:SHA256
Ctrl.digest = digest:SHA256
Ctrl.Secret = hexsecret:f8938ecc9edebc5030c0c6a441e213cd24e6f770a50dda07876f8d55da062bcadb386b411fd4fe4313a604fce6c17fbc
Ctrl.label = seed:master secret
Ctrl.client_random = hexseed:36c129d01a3200894b9179faac589d9835d58775f9b5ea3587cb8fd0364cae8c
@ -39,7 +39,7 @@ Ctrl.server_random = hexseed:f6c9575ed7ddd73e1f7d16eca115415812a43c2b747daaaae04
Output = 202c88c00f84a17a20027079604787461176455539e705be730890602c289a5001e34eeb3a043e5d52a65e66125188bf
KDF=TLS1-PRF
Ctrl.md = md:SHA256
Ctrl.digest = digest:SHA256
Ctrl.Secret = hexsecret:202c88c00f84a17a20027079604787461176455539e705be730890602c289a5001e34eeb3a043e5d52a65e66125188bf
Ctrl.label = seed:key expansion
Ctrl.server_random = hexseed:ae6c806f8ad4d80784549dff28a4b58fd837681a51d928c3e30ee5ff14f39868
@ -48,7 +48,7 @@ Output = d06139889fffac1e3a71865f504aa5d0d2a2e89506c6f2279b670c3e1b74f531016a253
# As above but use long name for KDF
KDF=tls1-prf
Ctrl.md = md:SHA256
Ctrl.digest = digest:SHA256
Ctrl.Secret = hexsecret:202c88c00f84a17a20027079604787461176455539e705be730890602c289a5001e34eeb3a043e5d52a65e66125188bf
Ctrl.label = seed:key expansion
Ctrl.server_random = hexseed:ae6c806f8ad4d80784549dff28a4b58fd837681a51d928c3e30ee5ff14f39868
@ -64,7 +64,7 @@ Result = KDF_DERIVE_ERROR
# Missing secret.
KDF=TLS1-PRF
Ctrl.md = md:MD5-SHA1
Ctrl.digest = digest:MD5-SHA1
Ctrl.Seed = hexseed:02
Output = 03
Result = KDF_DERIVE_ERROR
@ -72,7 +72,7 @@ Result = KDF_DERIVE_ERROR
Title = HKDF tests (from RFC5869 test vectors)
KDF = HKDF
Ctrl.md = md:SHA256
Ctrl.digest = digest:SHA256
Ctrl.IKM = hexkey:0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
Ctrl.salt = hexsalt:000102030405060708090a0b0c
Ctrl.info = hexinfo:f0f1f2f3f4f5f6f7f8f9
@ -80,20 +80,20 @@ Output = 3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf3400720
KDF = HKDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.md = md:SHA256
Ctrl.digest = digest:SHA256
Ctrl.IKM = hexkey:0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
Ctrl.salt = hexsalt:000102030405060708090a0b0c
Output = 077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5
KDF = HKDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.md = md:SHA256
Ctrl.digest = digest:SHA256
Ctrl.IKM = hexkey:077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5
Ctrl.info = hexinfo:f0f1f2f3f4f5f6f7f8f9
Output = 3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865
KDF = HKDF
Ctrl.md = md:SHA256
Ctrl.digest = digest:SHA256
Ctrl.IKM = hexkey:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f
Ctrl.salt = hexsalt:606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf
Ctrl.info = hexinfo:b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
@ -101,20 +101,20 @@ Output = b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a9
KDF = HKDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.md = md:SHA256
Ctrl.digest = digest:SHA256
Ctrl.IKM = hexkey:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f
Ctrl.salt = hexsalt:606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf
Output = 06a6b88c5853361a06104c9ceb35b45cef760014904671014a193f40c15fc244
KDF = HKDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.md = md:SHA256
Ctrl.digest = digest:SHA256
Ctrl.IKM = hexkey:06a6b88c5853361a06104c9ceb35b45cef760014904671014a193f40c15fc244
Ctrl.info = hexinfo:b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
Output = b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87
KDF = HKDF
Ctrl.md = md:SHA256
Ctrl.digest = digest:SHA256
Ctrl.IKM = hexkey:0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
Ctrl.salt = salt:
Ctrl.info = info:
@ -122,7 +122,7 @@ Output = 8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d20139
KDF = HKDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.md = md:SHA256
Ctrl.digest = digest:SHA256
Ctrl.IKM = hexkey:0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
Ctrl.salt = salt:
Ctrl.info = info:
@ -130,13 +130,13 @@ Output = 19ef24a32c717b167f33a91d6f648bdf96596776afdb6377ac434c1c293ccb04
KDF = HKDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.md = md:SHA256
Ctrl.digest = digest:SHA256
Ctrl.IKM = hexkey:19ef24a32c717b167f33a91d6f648bdf96596776afdb6377ac434c1c293ccb04
Ctrl.info = info:
Output = 8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8
KDF = HKDF
Ctrl.md = md:SHA1
Ctrl.digest = digest:SHA1
Ctrl.IKM = hexkey:0b0b0b0b0b0b0b0b0b0b0b
Ctrl.salt = hexsalt:000102030405060708090a0b0c
Ctrl.info = hexinfo:f0f1f2f3f4f5f6f7f8f9
@ -144,20 +144,20 @@ Output = 085a01ea1b10f36933068b56efa5ad81a4f14b822f5b091568a9cdd4f155fda2c22e422
KDF = HKDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.md = md:SHA1
Ctrl.digest = digest:SHA1
Ctrl.IKM = hexkey:0b0b0b0b0b0b0b0b0b0b0b
Ctrl.salt = hexsalt:000102030405060708090a0b0c
Output = 9b6c18c432a7bf8f0e71c8eb88f4b30baa2ba243
KDF = HKDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.md = md:SHA1
Ctrl.digest = digest:SHA1
Ctrl.IKM = hexkey:9b6c18c432a7bf8f0e71c8eb88f4b30baa2ba243
Ctrl.info = hexinfo:f0f1f2f3f4f5f6f7f8f9
Output = 085a01ea1b10f36933068b56efa5ad81a4f14b822f5b091568a9cdd4f155fda2c22e422478d305f3f896
KDF = HKDF
Ctrl.md = md:SHA1
Ctrl.digest = digest:SHA1
Ctrl.IKM = hexkey:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f
Ctrl.salt = hexsalt:606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf
Ctrl.info = hexinfo:b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
@ -165,20 +165,20 @@ Output = 0bd770a74d1160f7c9f12cd5912a06ebff6adcae899d92191fe4305673ba2ffe8fa3f1a
KDF = HKDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.md = md:SHA1
Ctrl.digest = digest:SHA1
Ctrl.IKM = hexkey:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f
Ctrl.salt = hexsalt:606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf
Output = 8adae09a2a307059478d309b26c4115a224cfaf6
KDF = HKDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.md = md:SHA1
Ctrl.digest = digest:SHA1
Ctrl.IKM = hexkey:8adae09a2a307059478d309b26c4115a224cfaf6
Ctrl.info = hexinfo:b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
Output = 0bd770a74d1160f7c9f12cd5912a06ebff6adcae899d92191fe4305673ba2ffe8fa3f1a4e5ad79f3f334b3b202b2173c486ea37ce3d397ed034c7f9dfeb15c5e927336d0441f4c4300e2cff0d0900b52d3b4
KDF = HKDF
Ctrl.md = md:SHA1
Ctrl.digest = digest:SHA1
Ctrl.IKM = hexkey:0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
Ctrl.salt = salt:
Ctrl.info = info:
@ -186,20 +186,20 @@ Output = 0ac1af7002b3d761d1e55298da9d0506b9ae52057220a306e07b6b87e8df21d0ea00033
KDF = HKDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.md = md:SHA1
Ctrl.digest = digest:SHA1
Ctrl.IKM = hexkey:0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
Ctrl.salt = salt:
Output = da8c8a73c7fa77288ec6f5e7c297786aa0d32d01
KDF = HKDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.md = md:SHA1
Ctrl.digest = digest:SHA1
Ctrl.IKM = hexkey:da8c8a73c7fa77288ec6f5e7c297786aa0d32d01
Ctrl.info = info:
Output = 0ac1af7002b3d761d1e55298da9d0506b9ae52057220a306e07b6b87e8df21d0ea00033de03984d34918
KDF = HKDF
Ctrl.md = md:SHA1
Ctrl.digest = digest:SHA1
Ctrl.IKM = hexkey:0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
Ctrl.salt = salt:
Ctrl.info = info:
@ -207,14 +207,14 @@ Output = 2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081
KDF = HKDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.md = md:SHA1
Ctrl.digest = digest:SHA1
Ctrl.IKM = hexkey:0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
Ctrl.salt = salt:
Output = 2adccada18779e7c2077ad2eb19d3f3e731385dd
KDF = HKDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.md = md:SHA1
Ctrl.digest = digest:SHA1
Ctrl.IKM = hexkey:2adccada18779e7c2077ad2eb19d3f3e731385dd
Ctrl.info = info:
Output = 2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081d70cce7acfc48
@ -227,27 +227,27 @@ Output = 00
Result = KDF_DERIVE_ERROR
KDF = HKDF
Ctrl.md = md:SHA1
Ctrl.digest = digest:SHA1
Ctrl.salt = salt:
Ctrl.info = info:
Output = 00
Result = KDF_DERIVE_ERROR
KDF = HKDF
Ctrl.md = md:SHA1
Ctrl.digest = digest:SHA1
Ctrl.IKM = hexkey:0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
Ctrl.info = info:
Output = 2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081d70cce7acfc48
KDF = HKDF
Ctrl.md = md:SHA1
Ctrl.digest = digest:SHA1
Ctrl.IKM = hexkey:0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
Ctrl.salt = salt:
Output = 2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081d70cce7acfc48
KDF = HKDF
Ctrl.mode = mode:EXTRACT_AND_EXPAND
Ctrl.md = md:SHA1
Ctrl.digest = digest:SHA1
Ctrl.IKM = hexkey:0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
Ctrl.salt = salt:
Output = 2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081d70cce7acfc48
@ -303,3 +303,133 @@ Ctrl.r = r:8
Ctrl.p = p:1
Result = INTERNAL_ERROR
Title = PBKDF2 tests
KDF = PBKDF2
Ctrl.pass = pass:password
Ctrl.salt = salt:salt
Ctrl.iter = iter:1
Ctrl.digest = digest:sha1
Output = 0c60c80f961f0e71f3a9b524af6012062fe037a6
KDF = PBKDF2
Ctrl.pass = pass:password
Ctrl.salt = salt:salt
Ctrl.iter = iter:1
Ctrl.digest = digest:sha256
Output = 120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b
KDF = PBKDF2
Ctrl.pass = pass:password
Ctrl.salt = salt:salt
Ctrl.iter = iter:1
Ctrl.digest = digest:sha512
Output = 867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252c02d470a285a0501bad999bfe943c08f050235d7d68b1da55e63f73b60a57fce
KDF = PBKDF2
Ctrl.pass = pass:password
Ctrl.salt = salt:salt
Ctrl.iter = iter:2
Ctrl.digest = digest:sha1
Output = ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957
KDF = PBKDF2
Ctrl.pass = pass:password
Ctrl.salt = salt:salt
Ctrl.iter = iter:2
Ctrl.digest = digest:sha256
Output = ae4d0c95af6b46d32d0adff928f06dd02a303f8ef3c251dfd6e2d85a95474c43
KDF = PBKDF2
Ctrl.pass = pass:password
Ctrl.salt = salt:salt
Ctrl.iter = iter:2
Ctrl.digest = digest:sha512
Output = e1d9c16aa681708a45f5c7c4e215ceb66e011a2e9f0040713f18aefdb866d53cf76cab2868a39b9f7840edce4fef5a82be67335c77a6068e04112754f27ccf4e
KDF = PBKDF2
Ctrl.pass = pass:password
Ctrl.salt = salt:salt
Ctrl.iter = iter:4096
Ctrl.digest = digest:sha1
Output = 4b007901b765489abead49d926f721d065a429c1
KDF = PBKDF2
Ctrl.pass = pass:password
Ctrl.salt = salt:salt
Ctrl.iter = iter:4096
Ctrl.digest = digest:sha256
Output = c5e478d59288c841aa530db6845c4c8d962893a001ce4e11a4963873aa98134a
KDF = PBKDF2
Ctrl.pass = pass:password
Ctrl.salt = salt:salt
Ctrl.iter = iter:4096
Ctrl.digest = digest:sha512
Output = d197b1b33db0143e018b12f3d1d1479e6cdebdcc97c5c0f87f6902e072f457b5143f30602641b3d55cd335988cb36b84376060ecd532e039b742a239434af2d5
KDF = PBKDF2
Ctrl.pass = pass:passwordPASSWORDpassword
Ctrl.salt = salt:saltSALTsaltSALTsaltSALTsaltSALTsalt
Ctrl.iter = iter:4096
Ctrl.digest = digest:sha1
Output = 3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038
KDF = PBKDF2
Ctrl.pass = pass:passwordPASSWORDpassword
Ctrl.salt = salt:saltSALTsaltSALTsaltSALTsaltSALTsalt
Ctrl.iter = iter:4096
Ctrl.digest = digest:sha256
Output = 348c89dbcbd32b2f32d814b8116e84cf2b17347ebc1800181c4e2a1fb8dd53e1c635518c7dac47e9
KDF = PBKDF2
Ctrl.pass = pass:passwordPASSWORDpassword
Ctrl.salt = salt:saltSALTsaltSALTsaltSALTsaltSALTsalt
Ctrl.iter = iter:4096
Ctrl.digest = digest:sha512
Output = 8c0511f4c6e597c6ac6315d8f0362e225f3c501495ba23b868c005174dc4ee71115b59f9e60cd9532fa33e0f75aefe30225c583a186cd82bd4daea9724a3d3b8
KDF = PBKDF2
Ctrl.hexpass = hexpass:7061737300776f7264
Ctrl.hexsalt = hexsalt:7361006c74
Ctrl.iter = iter:4096
Ctrl.digest = digest:sha1
Output = 56fa6aa75548099dcc37d7f03425e0c3
KDF = PBKDF2
Ctrl.hexpass = hexpass:7061737300776f7264
Ctrl.hexsalt = hexsalt:7361006c74
Ctrl.iter = iter:4096
Ctrl.digest = digest:sha256
Output = 89b69d0516f829893c696226650a8687
KDF = PBKDF2
Ctrl.hexpass = hexpass:7061737300776f7264
Ctrl.hexsalt = hexsalt:7361006c74
Ctrl.iter = iter:4096
Ctrl.digest = digest:sha512
Output = 9d9e9c4cd21fe4be24d5b8244c759665
Title = PBKDF2 tests for empty inputs
KDF = PBKDF2
Ctrl.pass = pass:
Ctrl.salt = salt:salt
Ctrl.iter = iter:1
Ctrl.digest = digest:sha1
Output = a33dddc30478185515311f8752895d36ea4363a2
KDF = PBKDF2
Ctrl.pass = pass:
Ctrl.salt = salt:salt
Ctrl.iter = iter:1
Ctrl.digest = digest:sha256
Output = f135c27993baf98773c5cdb40a5706ce6a345cde
KDF = PBKDF2
Ctrl.pass = pass:
Ctrl.salt = salt:salt
Ctrl.iter = iter:1
Ctrl.digest = digest:sha512
Output = 00ef42cdbfc98d29db20976608e455567fdddf14

View file

@ -0,0 +1,305 @@
#
# Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
#
# 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
# Tests start with one of these keywords
# Cipher Decrypt Derive Digest Encoding KDF PKEYKDF MAC PBE
# PrivPubKeyPair Sign Verify VerifyRecover
# and continue until a blank line. Lines starting with a pound sign,
# like this prolog, are ignored.
Title = TLS1 PRF tests (from NIST test vectors)
PKEYKDF=TLS1-PRF
Ctrl.md = md:MD5-SHA1
Ctrl.Secret = hexsecret:bded7fa5c1699c010be23dd06ada3a48349f21e5f86263d512c0c5cc379f0e780ec55d9844b2f1db02a96453513568d0
Ctrl.label = seed:master secret
Ctrl.client_random = hexseed:e5acaf549cd25c22d964c0d930fa4b5261d2507fad84c33715b7b9a864020693
Ctrl.server_random = hexseed:135e4d557fdf3aa6406d82975d5c606a9734c9334b42136e96990fbd5358cdb2
Output = 2f6962dfbc744c4b2138bb6b3d33054c5ecc14f24851d9896395a44ab3964efc2090c5bf51a0891209f46c1e1e998f62
PKEYKDF=TLS1-PRF
Ctrl.md = md:MD5-SHA1
Ctrl.Secret = hexsecret:2f6962dfbc744c4b2138bb6b3d33054c5ecc14f24851d9896395a44ab3964efc2090c5bf51a0891209f46c1e1e998f62
Ctrl.label = seed:key expansion
Ctrl.server_random = hexseed:67267e650eb32444119d222a368c191af3082888dc35afe8368e638c828874be
Ctrl.client_random = hexseed:d58a7b1cd4fedaa232159df652ce188f9d997e061b9bf48e83b62990440931f6
Output = 3088825988e77fce68d19f756e18e43eb7fe672433504feaf99b3c503d9091b164f166db301d70c9fc0870b4a94563907bee1a61fb786cb717576890bcc51cb9ead97e01d0a2fea99c953377b195205ff07b369589178796edc963fd80fdbe518a2fc1c35c18ae8d
PKEYKDF=TLS1-PRF
Ctrl.md = md:SHA256
Ctrl.Secret = hexsecret:f8938ecc9edebc5030c0c6a441e213cd24e6f770a50dda07876f8d55da062bcadb386b411fd4fe4313a604fce6c17fbc
Ctrl.label = seed:master secret
Ctrl.client_random = hexseed:36c129d01a3200894b9179faac589d9835d58775f9b5ea3587cb8fd0364cae8c
Ctrl.server_random = hexseed:f6c9575ed7ddd73e1f7d16eca115415812a43c2b747daaaae043abfb50053fce
Output = 202c88c00f84a17a20027079604787461176455539e705be730890602c289a5001e34eeb3a043e5d52a65e66125188bf
PKEYKDF=TLS1-PRF
Ctrl.md = md:SHA256
Ctrl.Secret = hexsecret:202c88c00f84a17a20027079604787461176455539e705be730890602c289a5001e34eeb3a043e5d52a65e66125188bf
Ctrl.label = seed:key expansion
Ctrl.server_random = hexseed:ae6c806f8ad4d80784549dff28a4b58fd837681a51d928c3e30ee5ff14f39868
Ctrl.client_random = hexseed:62e1fd91f23f558a605f28478c58cf72637b89784d959df7e946d3f07bd1b616
Output = d06139889fffac1e3a71865f504aa5d0d2a2e89506c6f2279b670c3e1b74f531016a2530c51a3a0f7e1d6590d0f0566b2f387f8d11fd4f731cdd572d2eae927f6f2f81410b25e6960be68985add6c38445ad9f8c64bf8068bf9a6679485d966f1ad6f68b43495b10a683755ea2b858d70ccac7ec8b053c6bd41ca299d4e51928
# As above but use long name for KDF
PKEYKDF=tls1-prf
Ctrl.md = md:SHA256
Ctrl.Secret = hexsecret:202c88c00f84a17a20027079604787461176455539e705be730890602c289a5001e34eeb3a043e5d52a65e66125188bf
Ctrl.label = seed:key expansion
Ctrl.server_random = hexseed:ae6c806f8ad4d80784549dff28a4b58fd837681a51d928c3e30ee5ff14f39868
Ctrl.client_random = hexseed:62e1fd91f23f558a605f28478c58cf72637b89784d959df7e946d3f07bd1b616
Output = d06139889fffac1e3a71865f504aa5d0d2a2e89506c6f2279b670c3e1b74f531016a2530c51a3a0f7e1d6590d0f0566b2f387f8d11fd4f731cdd572d2eae927f6f2f81410b25e6960be68985add6c38445ad9f8c64bf8068bf9a6679485d966f1ad6f68b43495b10a683755ea2b858d70ccac7ec8b053c6bd41ca299d4e51928
# Missing digest.
PKEYKDF=TLS1-PRF
Ctrl.Secret = hexsecret:01
Ctrl.Seed = hexseed:02
Output = 03
Result = KDF_DERIVE_ERROR
# Missing secret.
PKEYKDF=TLS1-PRF
Ctrl.md = md:MD5-SHA1
Ctrl.Seed = hexseed:02
Output = 03
Result = KDF_DERIVE_ERROR
Title = HKDF tests (from RFC5869 test vectors)
PKEYKDF = HKDF
Ctrl.md = md:SHA256
Ctrl.IKM = hexkey:0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
Ctrl.salt = hexsalt:000102030405060708090a0b0c
Ctrl.info = hexinfo:f0f1f2f3f4f5f6f7f8f9
Output = 3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865
PKEYKDF = HKDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.md = md:SHA256
Ctrl.IKM = hexkey:0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
Ctrl.salt = hexsalt:000102030405060708090a0b0c
Output = 077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5
PKEYKDF = HKDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.md = md:SHA256
Ctrl.IKM = hexkey:077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5
Ctrl.info = hexinfo:f0f1f2f3f4f5f6f7f8f9
Output = 3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865
PKEYKDF = HKDF
Ctrl.md = md:SHA256
Ctrl.IKM = hexkey:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f
Ctrl.salt = hexsalt:606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf
Ctrl.info = hexinfo:b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
Output = b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87
PKEYKDF = HKDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.md = md:SHA256
Ctrl.IKM = hexkey:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f
Ctrl.salt = hexsalt:606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf
Output = 06a6b88c5853361a06104c9ceb35b45cef760014904671014a193f40c15fc244
PKEYKDF = HKDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.md = md:SHA256
Ctrl.IKM = hexkey:06a6b88c5853361a06104c9ceb35b45cef760014904671014a193f40c15fc244
Ctrl.info = hexinfo:b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
Output = b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87
PKEYKDF = HKDF
Ctrl.md = md:SHA256
Ctrl.IKM = hexkey:0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
Ctrl.salt = salt:
Ctrl.info = info:
Output = 8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8
PKEYKDF = HKDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.md = md:SHA256
Ctrl.IKM = hexkey:0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
Ctrl.salt = salt:
Ctrl.info = info:
Output = 19ef24a32c717b167f33a91d6f648bdf96596776afdb6377ac434c1c293ccb04
PKEYKDF = HKDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.md = md:SHA256
Ctrl.IKM = hexkey:19ef24a32c717b167f33a91d6f648bdf96596776afdb6377ac434c1c293ccb04
Ctrl.info = info:
Output = 8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8
PKEYKDF = HKDF
Ctrl.md = md:SHA1
Ctrl.IKM = hexkey:0b0b0b0b0b0b0b0b0b0b0b
Ctrl.salt = hexsalt:000102030405060708090a0b0c
Ctrl.info = hexinfo:f0f1f2f3f4f5f6f7f8f9
Output = 085a01ea1b10f36933068b56efa5ad81a4f14b822f5b091568a9cdd4f155fda2c22e422478d305f3f896
PKEYKDF = HKDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.md = md:SHA1
Ctrl.IKM = hexkey:0b0b0b0b0b0b0b0b0b0b0b
Ctrl.salt = hexsalt:000102030405060708090a0b0c
Output = 9b6c18c432a7bf8f0e71c8eb88f4b30baa2ba243
PKEYKDF = HKDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.md = md:SHA1
Ctrl.IKM = hexkey:9b6c18c432a7bf8f0e71c8eb88f4b30baa2ba243
Ctrl.info = hexinfo:f0f1f2f3f4f5f6f7f8f9
Output = 085a01ea1b10f36933068b56efa5ad81a4f14b822f5b091568a9cdd4f155fda2c22e422478d305f3f896
PKEYKDF = HKDF
Ctrl.md = md:SHA1
Ctrl.IKM = hexkey:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f
Ctrl.salt = hexsalt:606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf
Ctrl.info = hexinfo:b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
Output = 0bd770a74d1160f7c9f12cd5912a06ebff6adcae899d92191fe4305673ba2ffe8fa3f1a4e5ad79f3f334b3b202b2173c486ea37ce3d397ed034c7f9dfeb15c5e927336d0441f4c4300e2cff0d0900b52d3b4
PKEYKDF = HKDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.md = md:SHA1
Ctrl.IKM = hexkey:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f
Ctrl.salt = hexsalt:606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf
Output = 8adae09a2a307059478d309b26c4115a224cfaf6
PKEYKDF = HKDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.md = md:SHA1
Ctrl.IKM = hexkey:8adae09a2a307059478d309b26c4115a224cfaf6
Ctrl.info = hexinfo:b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
Output = 0bd770a74d1160f7c9f12cd5912a06ebff6adcae899d92191fe4305673ba2ffe8fa3f1a4e5ad79f3f334b3b202b2173c486ea37ce3d397ed034c7f9dfeb15c5e927336d0441f4c4300e2cff0d0900b52d3b4
PKEYKDF = HKDF
Ctrl.md = md:SHA1
Ctrl.IKM = hexkey:0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
Ctrl.salt = salt:
Ctrl.info = info:
Output = 0ac1af7002b3d761d1e55298da9d0506b9ae52057220a306e07b6b87e8df21d0ea00033de03984d34918
PKEYKDF = HKDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.md = md:SHA1
Ctrl.IKM = hexkey:0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
Ctrl.salt = salt:
Output = da8c8a73c7fa77288ec6f5e7c297786aa0d32d01
PKEYKDF = HKDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.md = md:SHA1
Ctrl.IKM = hexkey:da8c8a73c7fa77288ec6f5e7c297786aa0d32d01
Ctrl.info = info:
Output = 0ac1af7002b3d761d1e55298da9d0506b9ae52057220a306e07b6b87e8df21d0ea00033de03984d34918
PKEYKDF = HKDF
Ctrl.md = md:SHA1
Ctrl.IKM = hexkey:0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
Ctrl.salt = salt:
Ctrl.info = info:
Output = 2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081d70cce7acfc48
PKEYKDF = HKDF
Ctrl.mode = mode:EXTRACT_ONLY
Ctrl.md = md:SHA1
Ctrl.IKM = hexkey:0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
Ctrl.salt = salt:
Output = 2adccada18779e7c2077ad2eb19d3f3e731385dd
PKEYKDF = HKDF
Ctrl.mode = mode:EXPAND_ONLY
Ctrl.md = md:SHA1
Ctrl.IKM = hexkey:2adccada18779e7c2077ad2eb19d3f3e731385dd
Ctrl.info = info:
Output = 2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081d70cce7acfc48
PKEYKDF = HKDF
Ctrl.IKM = hexkey:0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
Ctrl.salt = salt:
Ctrl.info = info:
Output = 00
Result = KDF_DERIVE_ERROR
PKEYKDF = HKDF
Ctrl.md = md:SHA1
Ctrl.salt = salt:
Ctrl.info = info:
Output = 00
Result = KDF_DERIVE_ERROR
PKEYKDF = HKDF
Ctrl.md = md:SHA1
Ctrl.IKM = hexkey:0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
Ctrl.info = info:
Output = 2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081d70cce7acfc48
PKEYKDF = HKDF
Ctrl.md = md:SHA1
Ctrl.IKM = hexkey:0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
Ctrl.salt = salt:
Output = 2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081d70cce7acfc48
PKEYKDF = HKDF
Ctrl.mode = mode:EXTRACT_AND_EXPAND
Ctrl.md = md:SHA1
Ctrl.IKM = hexkey:0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
Ctrl.salt = salt:
Output = 2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081d70cce7acfc48
Title = id-scrypt tests (from draft-josefsson-id-scrypt-kdf-03 and others)
PKEYKDF = scrypt
Ctrl.pass = pass:
Ctrl.salt = salt:
Ctrl.N = N:16
Ctrl.r = r:1
Ctrl.p = p:1
Output = 77d6576238657b203b19ca42c18a0497f16b4844e3074ae8dfdffa3fede21442fcd0069ded0948f8326a753a0fc81f17e8d3e0fb2e0d3628cf35e20c38d18906
PKEYKDF = scrypt
Ctrl.pass = pass:password
Ctrl.salt = salt:NaCl
Ctrl.N = N:1024
Ctrl.r = r:8
Ctrl.p = p:16
Output = fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e77376634b3731622eaf30d92e22a3886ff109279d9830dac727afb94a83ee6d8360cbdfa2cc0640
PKEYKDF = scrypt
Ctrl.hexpass = hexpass:70617373776f7264
Ctrl.salt = salt:NaCl
Ctrl.N = N:1024
Ctrl.r = r:8
Ctrl.p = p:16
Output = fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e77376634b3731622eaf30d92e22a3886ff109279d9830dac727afb94a83ee6d8360cbdfa2cc0640
PKEYKDF = scrypt
Ctrl.pass = pass:password
Ctrl.hexsalt = hexsalt:4e61436c
Ctrl.N = N:1024
Ctrl.r = r:8
Ctrl.p = p:16
Output = fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e77376634b3731622eaf30d92e22a3886ff109279d9830dac727afb94a83ee6d8360cbdfa2cc0640
PKEYKDF = scrypt
Ctrl.pass = pass:pleaseletmein
Ctrl.salt = salt:SodiumChloride
Ctrl.N = N:16384
Ctrl.r = r:8
Ctrl.p = p:1
Output = 7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b543f6545da1f2d5432955613f0fcf62d49705242a9af9e61e85dc0d651e40dfcf017b45575887
# Out of memory
PKEYKDF = scrypt
Ctrl.pass = pass:pleaseletmein
Ctrl.salt = salt:SodiumChloride
Ctrl.N = N:1048576
Ctrl.r = r:8
Ctrl.p = p:1
Result = INTERNAL_ERROR

View file

@ -0,0 +1,13 @@
#! /usr/bin/env perl
# Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
#
# 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
use OpenSSL::Test::Simple;
simple_test("test_evp_kdf", "evp_kdf_test");

View file

@ -4631,3 +4631,11 @@ CMS_add1_signing_cert_v2 4586 3_0_0 EXIST::FUNCTION:CMS
ESS_SIGNING_CERT_new_init 4587 3_0_0 EXIST::FUNCTION:
ESS_SIGNING_CERT_V2_new_init 4588 3_0_0 EXIST::FUNCTION:
ERR_load_ESS_strings 4589 3_0_0 EXIST::FUNCTION:
EVP_KDF_CTX_new_id 4590 3_0_0 EXIST::FUNCTION:
EVP_KDF_CTX_free 4591 3_0_0 EXIST::FUNCTION:
EVP_KDF_reset 4592 3_0_0 EXIST::FUNCTION:
EVP_KDF_ctrl 4593 3_0_0 EXIST::FUNCTION:
EVP_KDF_vctrl 4594 3_0_0 EXIST::FUNCTION:
EVP_KDF_ctrl_str 4595 3_0_0 EXIST::FUNCTION:
EVP_KDF_size 4596 3_0_0 EXIST::FUNCTION:
EVP_KDF_derive 4597 3_0_0 EXIST::FUNCTION:

View file

@ -22,6 +22,7 @@ CRYPTO_EX_dup datatype
CRYPTO_EX_free datatype
CRYPTO_EX_new datatype
DTLS_timer_cb datatype
EVP_KDF_CTX datatype
EVP_MAC datatype
EVP_MAC_CTX datatype
EVP_PKEY_gen_cb datatype