Latest update.
This commit is contained in:
+64
-2
@@ -16,6 +16,8 @@
|
||||
#include "internal/asn1_int.h"
|
||||
#include "internal/evp_int.h"
|
||||
#include <openssl/cms.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include "internal/param_build.h"
|
||||
|
||||
/*
|
||||
* i2d/d2i like DH parameter functions which use the appropriate routine for
|
||||
@@ -181,7 +183,7 @@ static int dh_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8)
|
||||
DHerr(DH_F_DH_PRIV_DECODE, DH_R_BN_ERROR);
|
||||
goto dherr;
|
||||
}
|
||||
/* Calculate public key */
|
||||
/* Calculate public key, increments dirty_cnt */
|
||||
if (!DH_generate_key(dh))
|
||||
goto dherr;
|
||||
|
||||
@@ -255,6 +257,7 @@ static int dh_param_decode(EVP_PKEY *pkey,
|
||||
DHerr(DH_F_DH_PARAM_DECODE, ERR_R_DH_LIB);
|
||||
return 0;
|
||||
}
|
||||
dh->dirty_cnt++;
|
||||
EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, dh);
|
||||
return 1;
|
||||
}
|
||||
@@ -415,6 +418,7 @@ static int int_dh_param_copy(DH *to, const DH *from, int is_x942)
|
||||
}
|
||||
} else
|
||||
to->length = from->length;
|
||||
to->dirty_cnt++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -540,6 +544,59 @@ static int dh_pkey_param_check(const EVP_PKEY *pkey)
|
||||
return DH_check_ex(dh);
|
||||
}
|
||||
|
||||
static size_t dh_pkey_dirty_cnt(const EVP_PKEY *pkey)
|
||||
{
|
||||
return pkey->pkey.dh->dirty_cnt;
|
||||
}
|
||||
|
||||
static void *dh_pkey_export_to(const EVP_PKEY *pk, EVP_KEYMGMT *keymgmt)
|
||||
{
|
||||
DH *dh = pk->pkey.dh;
|
||||
OSSL_PARAM_BLD tmpl;
|
||||
const BIGNUM *p = DH_get0_p(dh), *g = DH_get0_g(dh), *q = DH_get0_q(dh);
|
||||
const BIGNUM *pub_key = DH_get0_pub_key(dh);
|
||||
const BIGNUM *priv_key = DH_get0_priv_key(dh);
|
||||
OSSL_PARAM *params;
|
||||
void *provkey = NULL;
|
||||
|
||||
if (p == NULL || g == NULL)
|
||||
return NULL;
|
||||
|
||||
ossl_param_bld_init(&tmpl);
|
||||
if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_P, p)
|
||||
|| !ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_G, g))
|
||||
return NULL;
|
||||
|
||||
if (q != NULL) {
|
||||
if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_Q, q))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* This may be used to pass domain parameters only without any key data -
|
||||
* so "pub_key" is optional. We can never have a "priv_key" without a
|
||||
* corresponding "pub_key" though.
|
||||
*/
|
||||
if (pub_key != NULL) {
|
||||
if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_DH_PUB_KEY, pub_key))
|
||||
return NULL;
|
||||
|
||||
if (priv_key != NULL) {
|
||||
if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_DH_PRIV_KEY,
|
||||
priv_key))
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
params = ossl_param_bld_to_param(&tmpl);
|
||||
|
||||
/* We export, the provider imports */
|
||||
provkey = evp_keymgmt_importkey(keymgmt, params);
|
||||
|
||||
ossl_param_bld_free(params);
|
||||
return provkey;
|
||||
}
|
||||
|
||||
const EVP_PKEY_ASN1_METHOD dh_asn1_meth = {
|
||||
EVP_PKEY_DH,
|
||||
EVP_PKEY_DH,
|
||||
@@ -576,7 +633,12 @@ const EVP_PKEY_ASN1_METHOD dh_asn1_meth = {
|
||||
|
||||
0,
|
||||
dh_pkey_public_check,
|
||||
dh_pkey_param_check
|
||||
dh_pkey_param_check,
|
||||
|
||||
0, 0, 0, 0,
|
||||
|
||||
dh_pkey_dirty_cnt,
|
||||
dh_pkey_export_to,
|
||||
};
|
||||
|
||||
const EVP_PKEY_ASN1_METHOD dhx_asn1_meth = {
|
||||
|
||||
@@ -27,6 +27,8 @@ static int dh_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
DH_free((DH *)*pval);
|
||||
*pval = NULL;
|
||||
return 2;
|
||||
} else if (operation == ASN1_OP_D2I_POST) {
|
||||
((DH *)*pval)->dirty_cnt++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
+24
-27
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1995-2017 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
|
||||
@@ -24,12 +24,17 @@ int DH_check_params_ex(const DH *dh)
|
||||
{
|
||||
int errflags = 0;
|
||||
|
||||
(void)DH_check_params(dh, &errflags);
|
||||
if (!DH_check_params(dh, &errflags))
|
||||
return 0;
|
||||
|
||||
if ((errflags & DH_CHECK_P_NOT_PRIME) != 0)
|
||||
DHerr(DH_F_DH_CHECK_PARAMS_EX, DH_R_CHECK_P_NOT_PRIME);
|
||||
if ((errflags & DH_NOT_SUITABLE_GENERATOR) != 0)
|
||||
DHerr(DH_F_DH_CHECK_PARAMS_EX, DH_R_NOT_SUITABLE_GENERATOR);
|
||||
if ((errflags & DH_MODULUS_TOO_SMALL) != 0)
|
||||
DHerr(DH_F_DH_CHECK_PARAMS_EX, DH_R_MODULUS_TOO_SMALL);
|
||||
if ((errflags & DH_MODULUS_TOO_LARGE) != 0)
|
||||
DHerr(DH_F_DH_CHECK_PARAMS_EX, DH_R_MODULUS_TOO_LARGE);
|
||||
|
||||
return errflags == 0;
|
||||
}
|
||||
@@ -57,6 +62,10 @@ int DH_check_params(const DH *dh, int *ret)
|
||||
goto err;
|
||||
if (BN_cmp(dh->g, tmp) >= 0)
|
||||
*ret |= DH_NOT_SUITABLE_GENERATOR;
|
||||
if (BN_num_bits(dh->p) < DH_MIN_MODULUS_BITS)
|
||||
*ret |= DH_MODULUS_TOO_SMALL;
|
||||
if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS)
|
||||
*ret |= DH_MODULUS_TOO_LARGE;
|
||||
|
||||
ok = 1;
|
||||
err:
|
||||
@@ -67,18 +76,14 @@ int DH_check_params(const DH *dh, int *ret)
|
||||
|
||||
/*-
|
||||
* Check that p is a safe prime and
|
||||
* if g is 2, 3 or 5, check that it is a suitable generator
|
||||
* where
|
||||
* for 2, p mod 24 == 11
|
||||
* for 3, p mod 12 == 5
|
||||
* for 5, p mod 10 == 3 or 7
|
||||
* should hold.
|
||||
* g is a suitable generator.
|
||||
*/
|
||||
int DH_check_ex(const DH *dh)
|
||||
{
|
||||
int errflags = 0;
|
||||
|
||||
(void)DH_check(dh, &errflags);
|
||||
if (!DH_check(dh, &errflags))
|
||||
return 0;
|
||||
|
||||
if ((errflags & DH_NOT_SUITABLE_GENERATOR) != 0)
|
||||
DHerr(DH_F_DH_CHECK_EX, DH_R_NOT_SUITABLE_GENERATOR);
|
||||
@@ -94,6 +99,10 @@ int DH_check_ex(const DH *dh)
|
||||
DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_P_NOT_PRIME);
|
||||
if ((errflags & DH_CHECK_P_NOT_SAFE_PRIME) != 0)
|
||||
DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_P_NOT_SAFE_PRIME);
|
||||
if ((errflags & DH_MODULUS_TOO_SMALL) != 0)
|
||||
DHerr(DH_F_DH_CHECK_EX, DH_R_MODULUS_TOO_SMALL);
|
||||
if ((errflags & DH_MODULUS_TOO_LARGE) != 0)
|
||||
DHerr(DH_F_DH_CHECK_EX, DH_R_MODULUS_TOO_LARGE);
|
||||
|
||||
return errflags == 0;
|
||||
}
|
||||
@@ -102,10 +111,11 @@ int DH_check(const DH *dh, int *ret)
|
||||
{
|
||||
int ok = 0, r;
|
||||
BN_CTX *ctx = NULL;
|
||||
BN_ULONG l;
|
||||
BIGNUM *t1 = NULL, *t2 = NULL;
|
||||
|
||||
*ret = 0;
|
||||
if (!DH_check_params(dh, ret))
|
||||
return 0;
|
||||
|
||||
ctx = BN_CTX_new();
|
||||
if (ctx == NULL)
|
||||
goto err;
|
||||
@@ -139,21 +149,7 @@ int DH_check(const DH *dh, int *ret)
|
||||
*ret |= DH_CHECK_INVALID_Q_VALUE;
|
||||
if (dh->j && BN_cmp(dh->j, t1))
|
||||
*ret |= DH_CHECK_INVALID_J_VALUE;
|
||||
|
||||
} else if (BN_is_word(dh->g, DH_GENERATOR_2)) {
|
||||
l = BN_mod_word(dh->p, 24);
|
||||
if (l == (BN_ULONG)-1)
|
||||
goto err;
|
||||
if (l != 11)
|
||||
*ret |= DH_NOT_SUITABLE_GENERATOR;
|
||||
} else if (BN_is_word(dh->g, DH_GENERATOR_5)) {
|
||||
l = BN_mod_word(dh->p, 10);
|
||||
if (l == (BN_ULONG)-1)
|
||||
goto err;
|
||||
if ((l != 3) && (l != 7))
|
||||
*ret |= DH_NOT_SUITABLE_GENERATOR;
|
||||
} else
|
||||
*ret |= DH_UNABLE_TO_CHECK_GENERATOR;
|
||||
}
|
||||
|
||||
r = BN_is_prime_ex(dh->p, DH_NUMBER_ITERATIONS_FOR_PRIME, ctx, NULL);
|
||||
if (r < 0)
|
||||
@@ -180,7 +176,8 @@ int DH_check_pub_key_ex(const DH *dh, const BIGNUM *pub_key)
|
||||
{
|
||||
int errflags = 0;
|
||||
|
||||
(void)DH_check(dh, &errflags);
|
||||
if (!DH_check_pub_key(dh, pub_key, &errflags))
|
||||
return 0;
|
||||
|
||||
if ((errflags & DH_CHECK_PUBKEY_TOO_SMALL) != 0)
|
||||
DHerr(DH_F_DH_CHECK_PUB_KEY_EX, DH_R_CHECK_PUBKEY_TOO_SMALL);
|
||||
|
||||
+2
-38
@@ -13,41 +13,6 @@
|
||||
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
|
||||
static const ERR_STRING_DATA DH_str_functs[] = {
|
||||
{ERR_PACK(ERR_LIB_DH, DH_F_COMPUTE_KEY, 0), "compute_key"},
|
||||
{ERR_PACK(ERR_LIB_DH, DH_F_DHPARAMS_PRINT_FP, 0), "DHparams_print_fp"},
|
||||
{ERR_PACK(ERR_LIB_DH, DH_F_DH_BUF2KEY, 0), "dh_buf2key"},
|
||||
{ERR_PACK(ERR_LIB_DH, DH_F_DH_BUILTIN_GENPARAMS, 0),
|
||||
"dh_builtin_genparams"},
|
||||
{ERR_PACK(ERR_LIB_DH, DH_F_DH_CHECK_EX, 0), "DH_check_ex"},
|
||||
{ERR_PACK(ERR_LIB_DH, DH_F_DH_CHECK_PARAMS_EX, 0), "DH_check_params_ex"},
|
||||
{ERR_PACK(ERR_LIB_DH, DH_F_DH_CHECK_PUB_KEY_EX, 0), "DH_check_pub_key_ex"},
|
||||
{ERR_PACK(ERR_LIB_DH, DH_F_DH_CMS_DECRYPT, 0), "dh_cms_decrypt"},
|
||||
{ERR_PACK(ERR_LIB_DH, DH_F_DH_CMS_SET_PEERKEY, 0), "dh_cms_set_peerkey"},
|
||||
{ERR_PACK(ERR_LIB_DH, DH_F_DH_CMS_SET_SHARED_INFO, 0),
|
||||
"dh_cms_set_shared_info"},
|
||||
{ERR_PACK(ERR_LIB_DH, DH_F_DH_KEY2BUF, 0), "dh_key2buf"},
|
||||
{ERR_PACK(ERR_LIB_DH, DH_F_DH_METH_DUP, 0), "DH_meth_dup"},
|
||||
{ERR_PACK(ERR_LIB_DH, DH_F_DH_METH_NEW, 0), "DH_meth_new"},
|
||||
{ERR_PACK(ERR_LIB_DH, DH_F_DH_METH_SET1_NAME, 0), "DH_meth_set1_name"},
|
||||
{ERR_PACK(ERR_LIB_DH, DH_F_DH_NEW_BY_NID, 0), "DH_new_by_nid"},
|
||||
{ERR_PACK(ERR_LIB_DH, DH_F_DH_NEW_METHOD, 0), "DH_new_method"},
|
||||
{ERR_PACK(ERR_LIB_DH, DH_F_DH_PARAM_DECODE, 0), "dh_param_decode"},
|
||||
{ERR_PACK(ERR_LIB_DH, DH_F_DH_PKEY_PUBLIC_CHECK, 0),
|
||||
"dh_pkey_public_check"},
|
||||
{ERR_PACK(ERR_LIB_DH, DH_F_DH_PRIV_DECODE, 0), "dh_priv_decode"},
|
||||
{ERR_PACK(ERR_LIB_DH, DH_F_DH_PRIV_ENCODE, 0), "dh_priv_encode"},
|
||||
{ERR_PACK(ERR_LIB_DH, DH_F_DH_PUB_DECODE, 0), "dh_pub_decode"},
|
||||
{ERR_PACK(ERR_LIB_DH, DH_F_DH_PUB_ENCODE, 0), "dh_pub_encode"},
|
||||
{ERR_PACK(ERR_LIB_DH, DH_F_DO_DH_PRINT, 0), "do_dh_print"},
|
||||
{ERR_PACK(ERR_LIB_DH, DH_F_GENERATE_KEY, 0), "generate_key"},
|
||||
{ERR_PACK(ERR_LIB_DH, DH_F_PKEY_DH_CTRL_STR, 0), "pkey_dh_ctrl_str"},
|
||||
{ERR_PACK(ERR_LIB_DH, DH_F_PKEY_DH_DERIVE, 0), "pkey_dh_derive"},
|
||||
{ERR_PACK(ERR_LIB_DH, DH_F_PKEY_DH_INIT, 0), "pkey_dh_init"},
|
||||
{ERR_PACK(ERR_LIB_DH, DH_F_PKEY_DH_KEYGEN, 0), "pkey_dh_keygen"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
static const ERR_STRING_DATA DH_str_reasons[] = {
|
||||
{ERR_PACK(ERR_LIB_DH, 0, DH_R_BAD_GENERATOR), "bad generator"},
|
||||
{ERR_PACK(ERR_LIB_DH, 0, DH_R_BN_DECODE_ERROR), "bn decode error"},
|
||||
@@ -76,6 +41,7 @@ static const ERR_STRING_DATA DH_str_reasons[] = {
|
||||
{ERR_PACK(ERR_LIB_DH, 0, DH_R_KEYS_NOT_SET), "keys not set"},
|
||||
{ERR_PACK(ERR_LIB_DH, 0, DH_R_MISSING_PUBKEY), "missing pubkey"},
|
||||
{ERR_PACK(ERR_LIB_DH, 0, DH_R_MODULUS_TOO_LARGE), "modulus too large"},
|
||||
{ERR_PACK(ERR_LIB_DH, 0, DH_R_MODULUS_TOO_SMALL), "modulus too small"},
|
||||
{ERR_PACK(ERR_LIB_DH, 0, DH_R_NOT_SUITABLE_GENERATOR),
|
||||
"not suitable generator"},
|
||||
{ERR_PACK(ERR_LIB_DH, 0, DH_R_NO_PARAMETERS_SET), "no parameters set"},
|
||||
@@ -94,10 +60,8 @@ static const ERR_STRING_DATA DH_str_reasons[] = {
|
||||
int ERR_load_DH_strings(void)
|
||||
{
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
if (ERR_func_error_string(DH_str_functs[0].error) == NULL) {
|
||||
ERR_load_strings_const(DH_str_functs);
|
||||
if (ERR_reason_error_string(DH_str_reasons[0].error) == NULL)
|
||||
ERR_load_strings_const(DH_str_reasons);
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
+36
-29
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1995-2017 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
|
||||
@@ -30,30 +30,29 @@ int DH_generate_parameters_ex(DH *ret, int prime_len, int generator,
|
||||
|
||||
/*-
|
||||
* We generate DH parameters as follows
|
||||
* find a prime q which is prime_len/2 bits long.
|
||||
* p=(2*q)+1 or (p-1)/2 = q
|
||||
* For this case, g is a generator if
|
||||
* g^((p-1)/q) mod p != 1 for values of q which are the factors of p-1.
|
||||
* Since the factors of p-1 are q and 2, we just need to check
|
||||
* g^2 mod p != 1 and g^q mod p != 1.
|
||||
* find a prime p which is prime_len bits long,
|
||||
* where q=(p-1)/2 is also prime.
|
||||
* In the following we assume that g is not 0, 1 or p-1, since it
|
||||
* would generate only trivial subgroups.
|
||||
* For this case, g is a generator of the order-q subgroup if
|
||||
* g^q mod p == 1.
|
||||
* Or in terms of the Legendre symbol: (g/p) == 1.
|
||||
*
|
||||
* Having said all that,
|
||||
* there is another special case method for the generators 2, 3 and 5.
|
||||
* for 2, p mod 24 == 11
|
||||
* for 3, p mod 12 == 5 <<<<< does not work for safe primes.
|
||||
* for 5, p mod 10 == 3 or 7
|
||||
* Using the quadratic reciprocity law it is possible to solve
|
||||
* (g/p) == 1 for the special values 2, 3, 5:
|
||||
* (2/p) == 1 if p mod 8 == 1 or 7.
|
||||
* (3/p) == 1 if p mod 12 == 1 or 11.
|
||||
* (5/p) == 1 if p mod 5 == 1 or 4.
|
||||
* See for instance: https://en.wikipedia.org/wiki/Legendre_symbol
|
||||
*
|
||||
* Thanks to Phil Karn for the pointers about the
|
||||
* special generators and for answering some of my questions.
|
||||
*
|
||||
* I've implemented the second simple method :-).
|
||||
* Since DH should be using a safe prime (both p and q are prime),
|
||||
* this generator function can take a very very long time to run.
|
||||
*/
|
||||
/*
|
||||
* Actually there is no reason to insist that 'generator' be a generator.
|
||||
* It's just as OK (and in some sense better) to use a generator of the
|
||||
* order-q subgroup.
|
||||
* Since all safe primes > 7 must satisfy p mod 12 == 11
|
||||
* and all safe primes > 11 must satisfy p mod 5 != 1
|
||||
* we can further improve the condition for g = 2, 3 and 5:
|
||||
* for 2, p mod 24 == 23
|
||||
* for 3, p mod 12 == 11
|
||||
* for 5, p mod 60 == 59
|
||||
*/
|
||||
static int dh_builtin_genparams(DH *ret, int prime_len, int generator,
|
||||
BN_GENCB *cb)
|
||||
@@ -62,6 +61,16 @@ static int dh_builtin_genparams(DH *ret, int prime_len, int generator,
|
||||
int g, ok = -1;
|
||||
BN_CTX *ctx = NULL;
|
||||
|
||||
if (prime_len > OPENSSL_DH_MAX_MODULUS_BITS) {
|
||||
DHerr(DH_F_DH_BUILTIN_GENPARAMS, DH_R_MODULUS_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (prime_len < DH_MIN_MODULUS_BITS) {
|
||||
DHerr(DH_F_DH_BUILTIN_GENPARAMS, DH_R_MODULUS_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ctx = BN_CTX_new();
|
||||
if (ctx == NULL)
|
||||
goto err;
|
||||
@@ -84,17 +93,14 @@ static int dh_builtin_genparams(DH *ret, int prime_len, int generator,
|
||||
if (generator == DH_GENERATOR_2) {
|
||||
if (!BN_set_word(t1, 24))
|
||||
goto err;
|
||||
if (!BN_set_word(t2, 11))
|
||||
if (!BN_set_word(t2, 23))
|
||||
goto err;
|
||||
g = 2;
|
||||
} else if (generator == DH_GENERATOR_5) {
|
||||
if (!BN_set_word(t1, 10))
|
||||
if (!BN_set_word(t1, 60))
|
||||
goto err;
|
||||
if (!BN_set_word(t2, 3))
|
||||
if (!BN_set_word(t2, 59))
|
||||
goto err;
|
||||
/*
|
||||
* BN_set_word(t3,7); just have to miss out on these ones :-(
|
||||
*/
|
||||
g = 5;
|
||||
} else {
|
||||
/*
|
||||
@@ -102,9 +108,9 @@ static int dh_builtin_genparams(DH *ret, int prime_len, int generator,
|
||||
* not: since we are using safe primes, it will generate either an
|
||||
* order-q or an order-2q group, which both is OK
|
||||
*/
|
||||
if (!BN_set_word(t1, 2))
|
||||
if (!BN_set_word(t1, 12))
|
||||
goto err;
|
||||
if (!BN_set_word(t2, 1))
|
||||
if (!BN_set_word(t2, 11))
|
||||
goto err;
|
||||
g = generator;
|
||||
}
|
||||
@@ -115,6 +121,7 @@ static int dh_builtin_genparams(DH *ret, int prime_len, int generator,
|
||||
goto err;
|
||||
if (!BN_set_word(ret->g, g))
|
||||
goto err;
|
||||
ret->dirty_cnt++;
|
||||
ok = 1;
|
||||
err:
|
||||
if (ok == -1) {
|
||||
|
||||
+21
-11
@@ -11,10 +11,12 @@
|
||||
|
||||
#ifndef OPENSSL_NO_CMS
|
||||
# include <string.h>
|
||||
# include <openssl/core_names.h>
|
||||
# include <openssl/dh.h>
|
||||
# include <openssl/evp.h>
|
||||
# include <openssl/asn1.h>
|
||||
# include <openssl/kdf.h>
|
||||
# include <internal/provider.h>
|
||||
|
||||
int DH_KDF_X9_42(unsigned char *out, size_t outlen,
|
||||
const unsigned char *Z, size_t Zlen,
|
||||
@@ -23,8 +25,12 @@ int DH_KDF_X9_42(unsigned char *out, size_t outlen,
|
||||
{
|
||||
int ret = 0, nid;
|
||||
EVP_KDF_CTX *kctx = NULL;
|
||||
const EVP_KDF *kdf = NULL;
|
||||
EVP_KDF *kdf = NULL;
|
||||
const char *oid_sn;
|
||||
OSSL_PARAM params[5], *p = params;
|
||||
const char *mdname = EVP_MD_name(md);
|
||||
const OSSL_PROVIDER *prov = EVP_MD_provider(md);
|
||||
OPENSSL_CTX *provctx = ossl_provider_library_context(prov);
|
||||
|
||||
nid = OBJ_obj2nid(key_oid);
|
||||
if (nid == NID_undef)
|
||||
@@ -33,20 +39,24 @@ int DH_KDF_X9_42(unsigned char *out, size_t outlen,
|
||||
if (oid_sn == NULL)
|
||||
return 0;
|
||||
|
||||
kdf = EVP_get_kdfbyname(SN_x942kdf);
|
||||
if (kdf == NULL)
|
||||
kdf = EVP_KDF_fetch(provctx, OSSL_KDF_NAME_X942KDF, NULL);
|
||||
if ((kctx = EVP_KDF_CTX_new(kdf)) == NULL)
|
||||
goto err;
|
||||
kctx = EVP_KDF_CTX_new(kdf);
|
||||
ret =
|
||||
kctx != NULL
|
||||
&& EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MD, md) > 0
|
||||
&& EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KEY, Z, Zlen) > 0
|
||||
&& (ukm == NULL
|
||||
|| EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_UKM, ukm, ukmlen) > 0)
|
||||
&& EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_CEK_ALG, oid_sn) > 0
|
||||
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
|
||||
(char *)mdname, strlen(mdname) + 1);
|
||||
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
|
||||
(unsigned char *)Z, Zlen);
|
||||
if (ukm != NULL)
|
||||
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_UKM,
|
||||
(unsigned char *)ukm, ukmlen);
|
||||
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_CEK_ALG,
|
||||
(char *)oid_sn, strlen(oid_sn) + 1);
|
||||
*p = OSSL_PARAM_construct_end();
|
||||
ret = EVP_KDF_CTX_set_params(kctx, params) > 0
|
||||
&& EVP_KDF_derive(kctx, out, outlen) > 0;
|
||||
err:
|
||||
EVP_KDF_CTX_free(kctx);
|
||||
EVP_KDF_free(kdf);
|
||||
return ret;
|
||||
}
|
||||
#endif /* OPENSSL_NO_CMS */
|
||||
+23
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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
|
||||
@@ -87,6 +87,11 @@ static int generate_key(DH *dh)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (BN_num_bits(dh->p) < DH_MIN_MODULUS_BITS) {
|
||||
DHerr(DH_F_GENERATE_KEY, DH_R_MODULUS_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ctx = BN_CTX_new();
|
||||
if (ctx == NULL)
|
||||
goto err;
|
||||
@@ -125,6 +130,15 @@ static int generate_key(DH *dh)
|
||||
l = dh->length ? dh->length : BN_num_bits(dh->p) - 1;
|
||||
if (!BN_priv_rand(priv_key, l, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY))
|
||||
goto err;
|
||||
/*
|
||||
* We handle just one known case where g is a quadratic non-residue:
|
||||
* for g = 2: p % 8 == 3
|
||||
*/
|
||||
if (BN_is_word(dh->g, DH_GENERATOR_2) && !BN_is_bit_set(dh->p, 2)) {
|
||||
/* clear bit 0, since it won't be a secret anyway */
|
||||
if (!BN_clear_bit(priv_key, 0))
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,15 +150,16 @@ static int generate_key(DH *dh)
|
||||
BN_with_flags(prk, priv_key, BN_FLG_CONSTTIME);
|
||||
|
||||
if (!dh->meth->bn_mod_exp(dh, pub_key, dh->g, prk, dh->p, ctx, mont)) {
|
||||
BN_free(prk);
|
||||
BN_clear_free(prk);
|
||||
goto err;
|
||||
}
|
||||
/* We MUST free prk before any further use of priv_key */
|
||||
BN_free(prk);
|
||||
BN_clear_free(prk);
|
||||
}
|
||||
|
||||
dh->pub_key = pub_key;
|
||||
dh->priv_key = priv_key;
|
||||
dh->dirty_cnt++;
|
||||
ok = 1;
|
||||
err:
|
||||
if (ok != 1)
|
||||
@@ -171,6 +186,11 @@ static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (BN_num_bits(dh->p) < DH_MIN_MODULUS_BITS) {
|
||||
DHerr(DH_F_COMPUTE_KEY, DH_R_MODULUS_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ctx = BN_CTX_new();
|
||||
if (ctx == NULL)
|
||||
goto err;
|
||||
|
||||
+4
-2
@@ -209,6 +209,7 @@ int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g)
|
||||
dh->length = BN_num_bits(q);
|
||||
}
|
||||
|
||||
dh->dirty_cnt++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -234,14 +235,15 @@ void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key)
|
||||
int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key)
|
||||
{
|
||||
if (pub_key != NULL) {
|
||||
BN_free(dh->pub_key);
|
||||
BN_clear_free(dh->pub_key);
|
||||
dh->pub_key = pub_key;
|
||||
}
|
||||
if (priv_key != NULL) {
|
||||
BN_free(dh->priv_key);
|
||||
BN_clear_free(dh->priv_key);
|
||||
dh->priv_key = priv_key;
|
||||
}
|
||||
|
||||
dh->dirty_cnt++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#include <openssl/dh.h>
|
||||
#include "internal/refcount.h"
|
||||
|
||||
#define DH_MIN_MODULUS_BITS 512
|
||||
|
||||
struct dh_st {
|
||||
/*
|
||||
* This first argument is used to pick up errors when a DH is passed
|
||||
@@ -35,6 +37,9 @@ struct dh_st {
|
||||
const DH_METHOD *meth;
|
||||
ENGINE *engine;
|
||||
CRYPTO_RWLOCK *lock;
|
||||
|
||||
/* Provider data */
|
||||
size_t dirty_cnt; /* If any key material changes, increment this */
|
||||
};
|
||||
|
||||
struct dh_method {
|
||||
|
||||
@@ -22,6 +22,7 @@ static DH *dh_param_init(const BIGNUM *p, int32_t nbits)
|
||||
dh->p = (BIGNUM *)p;
|
||||
dh->g = (BIGNUM *)&_bignum_const_2;
|
||||
dh->length = nbits;
|
||||
dh->dirty_cnt++;
|
||||
return dh;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user