mirror of
https://github.com/openssl/openssl.git
synced 2025-02-23 14:42:15 +08:00
Change HKDF to alloc the info buffer.
Fixes #19909 I have enforced a maximum bound still but it is much higher. Note also that TLS13 still uses the 2048 buffer size. Reviewed-by: Hugo Landau <hlandau@openssl.org> Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from https://github.com/openssl/openssl/pull/19923)
This commit is contained in:
parent
624efd2ba6
commit
e8115bd165
@ -32,6 +32,7 @@
|
||||
#include "internal/e_os.h"
|
||||
|
||||
#define HKDF_MAXBUF 2048
|
||||
#define HKDF_MAXINFO (32*1024)
|
||||
|
||||
static OSSL_FUNC_kdf_newctx_fn kdf_hkdf_new;
|
||||
static OSSL_FUNC_kdf_dupctx_fn kdf_hkdf_dup;
|
||||
@ -83,7 +84,7 @@ typedef struct {
|
||||
size_t label_len;
|
||||
unsigned char *data;
|
||||
size_t data_len;
|
||||
unsigned char info[HKDF_MAXBUF];
|
||||
unsigned char *info;
|
||||
size_t info_len;
|
||||
} KDF_HKDF;
|
||||
|
||||
@ -120,7 +121,7 @@ static void kdf_hkdf_reset(void *vctx)
|
||||
OPENSSL_free(ctx->label);
|
||||
OPENSSL_clear_free(ctx->data, ctx->data_len);
|
||||
OPENSSL_clear_free(ctx->key, ctx->key_len);
|
||||
OPENSSL_cleanse(ctx->info, ctx->info_len);
|
||||
OPENSSL_clear_free(ctx->info, ctx->info_len);
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
ctx->provctx = provctx;
|
||||
}
|
||||
@ -142,10 +143,10 @@ static void *kdf_hkdf_dup(void *vctx)
|
||||
&dest->label, &dest->label_len)
|
||||
|| !ossl_prov_memdup(src->data, src->data_len,
|
||||
&dest->data, &dest->data_len)
|
||||
|| !ossl_prov_memdup(src->info, src->info_len,
|
||||
&dest->info, &dest->info_len)
|
||||
|| !ossl_prov_digest_copy(&dest->digest, &src->digest))
|
||||
goto err;
|
||||
memcpy(dest->info, src->info, sizeof(dest->info));
|
||||
dest->info_len = src->info_len;
|
||||
dest->mode = src->mode;
|
||||
}
|
||||
return dest;
|
||||
@ -273,6 +274,41 @@ static int hkdf_common_set_ctx_params(KDF_HKDF *ctx, const OSSL_PARAM params[])
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Use WPACKET to concat one or more OSSL_KDF_PARAM_INFO fields into a fixed
|
||||
* out buffer of size *outlen.
|
||||
* If out is NULL then outlen is used to return the required buffer size.
|
||||
*/
|
||||
static int setinfo_fromparams(const OSSL_PARAM *p, unsigned char *out, size_t *outlen)
|
||||
{
|
||||
int ret = 0;
|
||||
WPACKET pkt;
|
||||
|
||||
if (out == NULL) {
|
||||
if (!WPACKET_init_null(&pkt, 0))
|
||||
return 0;
|
||||
} else {
|
||||
if (!WPACKET_init_static_len(&pkt, out, *outlen, 0))
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (; p != NULL; p = OSSL_PARAM_locate_const(p + 1, OSSL_KDF_PARAM_INFO)) {
|
||||
if (p->data_type != OSSL_PARAM_OCTET_STRING)
|
||||
goto err;
|
||||
if (p->data != NULL
|
||||
&& p->data_size != 0
|
||||
&& !WPACKET_memcpy(&pkt, p->data, p->data_size))
|
||||
goto err;
|
||||
}
|
||||
if (!WPACKET_get_total_written(&pkt, outlen)
|
||||
|| !WPACKET_finish(&pkt))
|
||||
goto err;
|
||||
ret = 1;
|
||||
err:
|
||||
WPACKET_cleanup(&pkt);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int kdf_hkdf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
|
||||
{
|
||||
const OSSL_PARAM *p;
|
||||
@ -286,20 +322,26 @@ static int kdf_hkdf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
|
||||
|
||||
/* The info fields concatenate, so process them all */
|
||||
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_INFO)) != NULL) {
|
||||
ctx->info_len = 0;
|
||||
for (; p != NULL; p = OSSL_PARAM_locate_const(p + 1,
|
||||
OSSL_KDF_PARAM_INFO)) {
|
||||
const void *q = ctx->info + ctx->info_len;
|
||||
size_t sz = 0;
|
||||
size_t sz = 0;
|
||||
|
||||
if (p->data_size != 0
|
||||
&& p->data != NULL
|
||||
&& !OSSL_PARAM_get_octet_string(p, (void **)&q,
|
||||
HKDF_MAXBUF - ctx->info_len,
|
||||
&sz))
|
||||
return 0;
|
||||
ctx->info_len += sz;
|
||||
}
|
||||
/* calculate the total size */
|
||||
if (!setinfo_fromparams(p, NULL, &sz))
|
||||
return 0;
|
||||
if (sz > HKDF_MAXINFO)
|
||||
return 0;
|
||||
|
||||
OPENSSL_clear_free(ctx->info, ctx->info_len);
|
||||
ctx->info = NULL;
|
||||
if (sz == 0)
|
||||
return 1;
|
||||
/* Alloc the buffer */
|
||||
ctx->info = OPENSSL_malloc(sz);
|
||||
if (ctx->info == NULL)
|
||||
return 0;
|
||||
ctx->info_len = sz;
|
||||
/* Concat one or more OSSL_KDF_PARAM_INFO fields */
|
||||
if (!setinfo_fromparams(p, ctx->info, &sz))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
@ -202,3 +202,14 @@ Ctrl.IKM = hexkey:0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
|
||||
Ctrl.salt = salt:
|
||||
Output = da8c8a73
|
||||
Result = KDF_DERIVE_ERROR
|
||||
|
||||
# Test concat of multiple info (Uses existing test data, and just splits the info into separate fields)
|
||||
KDF = HKDF
|
||||
Ctrl.mode = mode:EXPAND_ONLY
|
||||
Ctrl.digest = digest:SHA1
|
||||
Ctrl.IKM = hexkey:8adae09a2a307059478d309b26c4115a224cfaf6
|
||||
Ctrl.info = hexinfo:b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0
|
||||
Ctrl.info = hexinfo:c1c2c3
|
||||
Ctrl.info = hexinfo:c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9
|
||||
Ctrl.info = hexinfo:dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
|
||||
Output = 0bd770a74d1160f7c9f12cd5912a06ebff6adcae899d92191fe4305673ba2ffe8fa3f1a4e5ad79f3f334b3b202b2173c486ea37ce3d397ed034c7f9dfeb15c5e927336d0441f4c4300e2cff0d0900b52d3b4
|
||||
|
Loading…
Reference in New Issue
Block a user