2016-05-18 03:38:09 +08:00
|
|
|
/*
|
2020-04-15 23:14:00 +08:00
|
|
|
* Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
|
1998-12-21 18:52:47 +08:00
|
|
|
*
|
2018-12-06 20:36:05 +08:00
|
|
|
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
2016-05-18 03:38:09 +08:00
|
|
|
* 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
|
1998-12-21 18:52:47 +08:00
|
|
|
*/
|
|
|
|
|
2020-02-03 17:05:31 +08:00
|
|
|
/*
|
|
|
|
* DH low level APIs are deprecated for public use, but still ok for
|
|
|
|
* internal use.
|
|
|
|
*/
|
|
|
|
#include "internal/deprecated.h"
|
|
|
|
|
1998-12-21 18:52:47 +08:00
|
|
|
#include <stdio.h>
|
1999-04-24 06:13:45 +08:00
|
|
|
#include <openssl/bn.h>
|
2016-03-19 02:30:20 +08:00
|
|
|
#include <openssl/engine.h>
|
2020-02-02 17:11:29 +08:00
|
|
|
#include <openssl/obj_mac.h>
|
2020-04-15 23:14:00 +08:00
|
|
|
#include <openssl/core_names.h>
|
2020-02-02 17:11:29 +08:00
|
|
|
#include "internal/cryptlib.h"
|
|
|
|
#include "internal/refcount.h"
|
2020-04-15 23:14:00 +08:00
|
|
|
#include "crypto/evp.h"
|
2020-01-24 12:09:33 +08:00
|
|
|
#include "crypto/dh.h"
|
2020-02-02 17:11:29 +08:00
|
|
|
#include "dh_local.h"
|
1998-12-21 18:52:47 +08:00
|
|
|
|
2020-02-16 11:03:46 +08:00
|
|
|
static DH *dh_new_intern(ENGINE *engine, OPENSSL_CTX *libctx);
|
|
|
|
|
2020-01-23 18:33:28 +08:00
|
|
|
#ifndef FIPS_MODE
|
2001-09-26 04:23:40 +08:00
|
|
|
int DH_set_method(DH *dh, const DH_METHOD *meth)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* NB: The caller is specifically setting a method, so it's not up to us
|
|
|
|
* to deal with which ENGINE it comes from.
|
|
|
|
*/
|
|
|
|
const DH_METHOD *mtmp;
|
|
|
|
mtmp = dh->meth;
|
|
|
|
if (mtmp->finish)
|
|
|
|
mtmp->finish(dh);
|
2003-01-31 01:39:26 +08:00
|
|
|
#ifndef OPENSSL_NO_ENGINE
|
2016-02-26 01:09:06 +08:00
|
|
|
ENGINE_finish(dh->engine);
|
|
|
|
dh->engine = NULL;
|
2003-01-31 01:39:26 +08:00
|
|
|
#endif
|
2015-01-22 11:40:55 +08:00
|
|
|
dh->meth = meth;
|
|
|
|
if (meth->init)
|
|
|
|
meth->init(dh);
|
|
|
|
return 1;
|
|
|
|
}
|
1999-08-24 07:11:32 +08:00
|
|
|
|
2020-02-29 15:57:34 +08:00
|
|
|
const DH_METHOD *dh_get_method(const DH *dh)
|
|
|
|
{
|
|
|
|
return dh->meth;
|
|
|
|
}
|
|
|
|
|
1999-04-20 05:31:43 +08:00
|
|
|
DH *DH_new(void)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2020-02-16 11:03:46 +08:00
|
|
|
return dh_new_intern(NULL, NULL);
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
1999-08-24 07:11:32 +08:00
|
|
|
|
2000-10-27 05:07:28 +08:00
|
|
|
DH *DH_new_method(ENGINE *engine)
|
2020-02-16 11:03:46 +08:00
|
|
|
{
|
|
|
|
return dh_new_intern(engine, NULL);
|
|
|
|
}
|
|
|
|
#endif /* !FIPS_MODE */
|
|
|
|
|
2020-04-15 23:14:00 +08:00
|
|
|
DH *dh_new_with_libctx(OPENSSL_CTX *libctx)
|
2020-02-16 11:03:46 +08:00
|
|
|
{
|
|
|
|
return dh_new_intern(NULL, libctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
static DH *dh_new_intern(ENGINE *engine, OPENSSL_CTX *libctx)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2015-09-03 21:15:26 +08:00
|
|
|
DH *ret = OPENSSL_zalloc(sizeof(*ret));
|
1999-08-24 07:11:32 +08:00
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
if (ret == NULL) {
|
2020-02-16 11:03:46 +08:00
|
|
|
DHerr(0, ERR_R_MALLOC_FAILURE);
|
2016-03-04 23:43:46 +08:00
|
|
|
return NULL;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2001-06-24 07:07:34 +08:00
|
|
|
|
2016-03-09 03:11:48 +08:00
|
|
|
ret->references = 1;
|
|
|
|
ret->lock = CRYPTO_THREAD_lock_new();
|
|
|
|
if (ret->lock == NULL) {
|
2020-02-16 11:03:46 +08:00
|
|
|
DHerr(0, ERR_R_MALLOC_FAILURE);
|
2016-03-09 03:11:48 +08:00
|
|
|
OPENSSL_free(ret);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-02-16 11:03:46 +08:00
|
|
|
ret->libctx = libctx;
|
2015-01-22 11:40:55 +08:00
|
|
|
ret->meth = DH_get_default_method();
|
2020-01-23 18:33:28 +08:00
|
|
|
#if !defined(FIPS_MODE) && !defined(OPENSSL_NO_ENGINE)
|
2016-03-09 03:11:48 +08:00
|
|
|
ret->flags = ret->meth->flags; /* early default init */
|
2015-01-22 11:40:55 +08:00
|
|
|
if (engine) {
|
|
|
|
if (!ENGINE_init(engine)) {
|
2020-02-16 11:03:46 +08:00
|
|
|
DHerr(0, ERR_R_ENGINE_LIB);
|
2016-03-09 03:11:48 +08:00
|
|
|
goto err;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
|
|
|
ret->engine = engine;
|
|
|
|
} else
|
|
|
|
ret->engine = ENGINE_get_default_DH();
|
|
|
|
if (ret->engine) {
|
|
|
|
ret->meth = ENGINE_get_DH(ret->engine);
|
2016-02-26 01:09:06 +08:00
|
|
|
if (ret->meth == NULL) {
|
2020-02-16 11:03:46 +08:00
|
|
|
DHerr(0, ERR_R_ENGINE_LIB);
|
2016-03-09 03:11:48 +08:00
|
|
|
goto err;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
|
|
|
}
|
2003-01-31 01:39:26 +08:00
|
|
|
#endif
|
2001-09-26 04:23:40 +08:00
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
ret->flags = ret->meth->flags;
|
2016-03-04 23:43:46 +08:00
|
|
|
|
2020-01-14 09:32:42 +08:00
|
|
|
#ifndef FIPS_MODE
|
2016-03-09 03:11:48 +08:00
|
|
|
if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_DH, ret, &ret->ex_data))
|
|
|
|
goto err;
|
2020-01-23 18:33:28 +08:00
|
|
|
#endif /* FIPS_MODE */
|
2016-03-04 23:43:46 +08:00
|
|
|
|
|
|
|
if ((ret->meth->init != NULL) && !ret->meth->init(ret)) {
|
2020-02-16 11:03:46 +08:00
|
|
|
DHerr(0, ERR_R_INIT_FAIL);
|
2018-09-05 17:08:12 +08:00
|
|
|
goto err;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2016-03-04 23:43:46 +08:00
|
|
|
|
|
|
|
return ret;
|
2018-09-05 17:08:12 +08:00
|
|
|
|
|
|
|
err:
|
|
|
|
DH_free(ret);
|
|
|
|
return NULL;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
1998-12-21 18:52:47 +08:00
|
|
|
|
1999-04-20 05:31:43 +08:00
|
|
|
void DH_free(DH *r)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
int i;
|
2015-03-24 22:17:37 +08:00
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
if (r == NULL)
|
|
|
|
return;
|
2016-03-04 23:43:46 +08:00
|
|
|
|
2016-08-27 22:01:08 +08:00
|
|
|
CRYPTO_DOWN_REF(&r->references, &i, r->lock);
|
2016-01-31 01:04:25 +08:00
|
|
|
REF_PRINT_COUNT("DH", r);
|
2015-01-22 11:40:55 +08:00
|
|
|
if (i > 0)
|
|
|
|
return;
|
2016-01-31 01:04:25 +08:00
|
|
|
REF_ASSERT_ISNT(i < 0);
|
1999-08-24 07:11:32 +08:00
|
|
|
|
2018-09-05 16:58:55 +08:00
|
|
|
if (r->meth != NULL && r->meth->finish != NULL)
|
2015-01-22 11:40:55 +08:00
|
|
|
r->meth->finish(r);
|
2020-01-23 18:33:28 +08:00
|
|
|
#if !defined(FIPS_MODE)
|
|
|
|
# if !defined(OPENSSL_NO_ENGINE)
|
2016-02-26 01:09:06 +08:00
|
|
|
ENGINE_finish(r->engine);
|
2020-01-23 18:33:28 +08:00
|
|
|
# endif
|
2015-01-22 11:40:55 +08:00
|
|
|
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DH, r, &r->ex_data);
|
2020-01-14 09:32:42 +08:00
|
|
|
#endif
|
2000-11-30 03:59:45 +08:00
|
|
|
|
2016-03-04 23:43:46 +08:00
|
|
|
CRYPTO_THREAD_lock_free(r->lock);
|
|
|
|
|
2020-01-24 12:09:33 +08:00
|
|
|
ffc_params_cleanup(&r->params);
|
2015-05-01 09:37:06 +08:00
|
|
|
BN_clear_free(r->pub_key);
|
|
|
|
BN_clear_free(r->priv_key);
|
2015-01-22 11:40:55 +08:00
|
|
|
OPENSSL_free(r);
|
|
|
|
}
|
1998-12-21 18:52:47 +08:00
|
|
|
|
2001-09-06 00:54:32 +08:00
|
|
|
int DH_up_ref(DH *r)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2016-03-04 23:43:46 +08:00
|
|
|
int i;
|
|
|
|
|
2016-08-27 22:01:08 +08:00
|
|
|
if (CRYPTO_UP_REF(&r->references, &i, r->lock) <= 0)
|
2016-03-04 23:43:46 +08:00
|
|
|
return 0;
|
2016-01-31 01:04:25 +08:00
|
|
|
|
|
|
|
REF_PRINT_COUNT("DH", r);
|
|
|
|
REF_ASSERT_ISNT(i < 2);
|
2015-01-22 11:40:55 +08:00
|
|
|
return ((i > 1) ? 1 : 0);
|
|
|
|
}
|
2001-08-26 01:24:21 +08:00
|
|
|
|
2020-01-14 09:32:42 +08:00
|
|
|
#ifndef FIPS_MODE
|
2000-01-24 07:41:49 +08:00
|
|
|
int DH_set_ex_data(DH *d, int idx, void *arg)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2017-10-17 22:04:09 +08:00
|
|
|
return CRYPTO_set_ex_data(&d->ex_data, idx, arg);
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
1999-08-24 07:11:32 +08:00
|
|
|
|
2020-03-23 15:30:37 +08:00
|
|
|
void *DH_get_ex_data(const DH *d, int idx)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2017-10-17 22:04:09 +08:00
|
|
|
return CRYPTO_get_ex_data(&d->ex_data, idx);
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2020-01-14 09:32:42 +08:00
|
|
|
#endif
|
1999-08-24 07:11:32 +08:00
|
|
|
|
2015-04-18 18:23:12 +08:00
|
|
|
int DH_bits(const DH *dh)
|
|
|
|
{
|
2020-01-24 12:09:33 +08:00
|
|
|
return BN_num_bits(dh->params.p);
|
2015-04-18 18:23:12 +08:00
|
|
|
}
|
|
|
|
|
2000-11-07 22:30:37 +08:00
|
|
|
int DH_size(const DH *dh)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2020-01-24 12:09:33 +08:00
|
|
|
return BN_num_bytes(dh->params.p);
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2014-01-18 22:51:40 +08:00
|
|
|
|
|
|
|
int DH_security_bits(const DH *dh)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
int N;
|
2020-01-24 12:09:33 +08:00
|
|
|
if (dh->params.q != NULL)
|
|
|
|
N = BN_num_bits(dh->params.q);
|
2015-01-22 11:40:55 +08:00
|
|
|
else if (dh->length)
|
|
|
|
N = dh->length;
|
|
|
|
else
|
|
|
|
N = -1;
|
2020-01-24 12:09:33 +08:00
|
|
|
return BN_security_bits(BN_num_bits(dh->params.p), N);
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2016-04-07 00:49:48 +08:00
|
|
|
|
2016-06-14 21:48:16 +08:00
|
|
|
void DH_get0_pqg(const DH *dh,
|
|
|
|
const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
|
2016-04-07 00:49:48 +08:00
|
|
|
{
|
2020-01-24 12:09:33 +08:00
|
|
|
ffc_params_get0_pqg(&dh->params, p, q, g);
|
2016-04-07 00:49:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g)
|
|
|
|
{
|
2020-04-20 09:07:38 +08:00
|
|
|
/*
|
|
|
|
* If the fields p and g in d are NULL, the corresponding input
|
RSA, DSA, DH: Allow some given input to be NULL on already initialised keys
The diverse {RSA,DSA,DH}_set0_* functions are made to allow some
parameters to be NULL IF the corresponding numbers in the given key
structure have already been previously initialised. Specifically,
this allows the addition of private components to be added to a key
that already has the public half, approximately like this:
RSA_get0_key(rsa, NULL, &e, NULL);
RSA_get0_factors(rsa, &p, &q);
/* calculate new d */
RSA_set0_key(rsa, NULL, NULL, d);
Reviewed-by: Matt Caswell <matt@openssl.org>
2016-04-26 02:28:54 +08:00
|
|
|
* parameters MUST be non-NULL. q may remain NULL.
|
|
|
|
*/
|
2020-01-24 12:09:33 +08:00
|
|
|
if ((dh->params.p == NULL && p == NULL)
|
|
|
|
|| (dh->params.g == NULL && g == NULL))
|
2016-04-07 00:49:48 +08:00
|
|
|
return 0;
|
RSA, DSA, DH: Allow some given input to be NULL on already initialised keys
The diverse {RSA,DSA,DH}_set0_* functions are made to allow some
parameters to be NULL IF the corresponding numbers in the given key
structure have already been previously initialised. Specifically,
this allows the addition of private components to be added to a key
that already has the public half, approximately like this:
RSA_get0_key(rsa, NULL, &e, NULL);
RSA_get0_factors(rsa, &p, &q);
/* calculate new d */
RSA_set0_key(rsa, NULL, NULL, d);
Reviewed-by: Matt Caswell <matt@openssl.org>
2016-04-26 02:28:54 +08:00
|
|
|
|
2020-01-24 12:09:33 +08:00
|
|
|
ffc_params_set0_pqg(&dh->params, p, q, g);
|
2020-04-20 09:07:38 +08:00
|
|
|
dh_cache_named_group(dh);
|
|
|
|
if (q != NULL)
|
|
|
|
dh->length = BN_num_bits(q);
|
2020-03-07 05:47:58 +08:00
|
|
|
/*
|
|
|
|
* Check if this is a named group. If it finds a named group then the
|
|
|
|
* 'q' and 'length' value are either already set or are set by the
|
|
|
|
* call.
|
|
|
|
*/
|
|
|
|
if (DH_get_nid(dh) == NID_undef) {
|
|
|
|
/* If its not a named group then set the 'length' if q is not NULL */
|
|
|
|
if (q != NULL)
|
|
|
|
dh->length = BN_num_bits(q);
|
|
|
|
}
|
2019-07-07 16:56:46 +08:00
|
|
|
dh->dirty_cnt++;
|
2016-04-07 00:49:48 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
long DH_get_length(const DH *dh)
|
|
|
|
{
|
|
|
|
return dh->length;
|
|
|
|
}
|
|
|
|
|
|
|
|
int DH_set_length(DH *dh, long length)
|
|
|
|
{
|
|
|
|
dh->length = length;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2016-06-14 21:48:16 +08:00
|
|
|
void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key)
|
2016-04-07 00:49:48 +08:00
|
|
|
{
|
|
|
|
if (pub_key != NULL)
|
|
|
|
*pub_key = dh->pub_key;
|
|
|
|
if (priv_key != NULL)
|
|
|
|
*priv_key = dh->priv_key;
|
|
|
|
}
|
|
|
|
|
|
|
|
int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key)
|
|
|
|
{
|
RSA, DSA, DH: Allow some given input to be NULL on already initialised keys
The diverse {RSA,DSA,DH}_set0_* functions are made to allow some
parameters to be NULL IF the corresponding numbers in the given key
structure have already been previously initialised. Specifically,
this allows the addition of private components to be added to a key
that already has the public half, approximately like this:
RSA_get0_key(rsa, NULL, &e, NULL);
RSA_get0_factors(rsa, &p, &q);
/* calculate new d */
RSA_set0_key(rsa, NULL, NULL, d);
Reviewed-by: Matt Caswell <matt@openssl.org>
2016-04-26 02:28:54 +08:00
|
|
|
if (pub_key != NULL) {
|
2019-09-07 06:53:24 +08:00
|
|
|
BN_clear_free(dh->pub_key);
|
RSA, DSA, DH: Allow some given input to be NULL on already initialised keys
The diverse {RSA,DSA,DH}_set0_* functions are made to allow some
parameters to be NULL IF the corresponding numbers in the given key
structure have already been previously initialised. Specifically,
this allows the addition of private components to be added to a key
that already has the public half, approximately like this:
RSA_get0_key(rsa, NULL, &e, NULL);
RSA_get0_factors(rsa, &p, &q);
/* calculate new d */
RSA_set0_key(rsa, NULL, NULL, d);
Reviewed-by: Matt Caswell <matt@openssl.org>
2016-04-26 02:28:54 +08:00
|
|
|
dh->pub_key = pub_key;
|
|
|
|
}
|
|
|
|
if (priv_key != NULL) {
|
2019-09-07 06:53:24 +08:00
|
|
|
BN_clear_free(dh->priv_key);
|
RSA, DSA, DH: Allow some given input to be NULL on already initialised keys
The diverse {RSA,DSA,DH}_set0_* functions are made to allow some
parameters to be NULL IF the corresponding numbers in the given key
structure have already been previously initialised. Specifically,
this allows the addition of private components to be added to a key
that already has the public half, approximately like this:
RSA_get0_key(rsa, NULL, &e, NULL);
RSA_get0_factors(rsa, &p, &q);
/* calculate new d */
RSA_set0_key(rsa, NULL, NULL, d);
Reviewed-by: Matt Caswell <matt@openssl.org>
2016-04-26 02:28:54 +08:00
|
|
|
dh->priv_key = priv_key;
|
2020-04-20 09:07:38 +08:00
|
|
|
dh->length = BN_num_bits(priv_key);
|
RSA, DSA, DH: Allow some given input to be NULL on already initialised keys
The diverse {RSA,DSA,DH}_set0_* functions are made to allow some
parameters to be NULL IF the corresponding numbers in the given key
structure have already been previously initialised. Specifically,
this allows the addition of private components to be added to a key
that already has the public half, approximately like this:
RSA_get0_key(rsa, NULL, &e, NULL);
RSA_get0_factors(rsa, &p, &q);
/* calculate new d */
RSA_set0_key(rsa, NULL, NULL, d);
Reviewed-by: Matt Caswell <matt@openssl.org>
2016-04-26 02:28:54 +08:00
|
|
|
}
|
2016-04-07 00:49:48 +08:00
|
|
|
|
2019-07-07 16:56:46 +08:00
|
|
|
dh->dirty_cnt++;
|
2016-04-07 00:49:48 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2018-05-16 22:18:13 +08:00
|
|
|
const BIGNUM *DH_get0_p(const DH *dh)
|
|
|
|
{
|
2020-01-24 12:09:33 +08:00
|
|
|
return dh->params.p;
|
2018-05-16 22:18:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
const BIGNUM *DH_get0_q(const DH *dh)
|
|
|
|
{
|
2020-01-24 12:09:33 +08:00
|
|
|
return dh->params.q;
|
2018-05-16 22:18:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
const BIGNUM *DH_get0_g(const DH *dh)
|
|
|
|
{
|
2020-01-24 12:09:33 +08:00
|
|
|
return dh->params.g;
|
2018-05-16 22:18:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
const BIGNUM *DH_get0_priv_key(const DH *dh)
|
|
|
|
{
|
|
|
|
return dh->priv_key;
|
|
|
|
}
|
|
|
|
|
|
|
|
const BIGNUM *DH_get0_pub_key(const DH *dh)
|
|
|
|
{
|
|
|
|
return dh->pub_key;
|
|
|
|
}
|
|
|
|
|
2016-04-07 00:49:48 +08:00
|
|
|
void DH_clear_flags(DH *dh, int flags)
|
|
|
|
{
|
|
|
|
dh->flags &= ~flags;
|
|
|
|
}
|
|
|
|
|
|
|
|
int DH_test_flags(const DH *dh, int flags)
|
|
|
|
{
|
|
|
|
return dh->flags & flags;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DH_set_flags(DH *dh, int flags)
|
|
|
|
{
|
|
|
|
dh->flags |= flags;
|
|
|
|
}
|
|
|
|
|
2020-01-23 18:33:28 +08:00
|
|
|
#ifndef FIPS_MODE
|
2016-04-07 00:49:48 +08:00
|
|
|
ENGINE *DH_get0_engine(DH *dh)
|
|
|
|
{
|
|
|
|
return dh->engine;
|
|
|
|
}
|
2020-01-23 18:33:28 +08:00
|
|
|
#endif /*FIPS_MODE */
|
2020-01-24 12:09:33 +08:00
|
|
|
|
|
|
|
FFC_PARAMS *dh_get0_params(DH *dh)
|
|
|
|
{
|
|
|
|
return &dh->params;
|
|
|
|
}
|
2020-01-31 06:18:46 +08:00
|
|
|
int dh_get0_nid(const DH *dh)
|
|
|
|
{
|
|
|
|
return dh->params.nid;
|
|
|
|
}
|
2020-04-15 23:14:00 +08:00
|
|
|
|
|
|
|
int dh_ffc_params_fromdata(DH *dh, const OSSL_PARAM params[])
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
FFC_PARAMS *ffc;
|
|
|
|
|
|
|
|
if (dh == NULL)
|
|
|
|
return 0;
|
|
|
|
ffc = dh_get0_params(dh);
|
|
|
|
if (ffc == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
ret = ffc_params_fromdata(ffc, params);
|
|
|
|
if (ret) {
|
2020-04-20 09:07:38 +08:00
|
|
|
dh_cache_named_group(dh);
|
2020-04-15 23:14:00 +08:00
|
|
|
dh->dirty_cnt++;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int dh_paramgen_check(EVP_PKEY_CTX *ctx)
|
|
|
|
{
|
|
|
|
if (ctx == NULL || !EVP_PKEY_CTX_IS_GEN_OP(ctx)) {
|
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
|
|
|
|
/* Uses the same return values as EVP_PKEY_CTX_ctrl */
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
/* If key type not DH return error */
|
|
|
|
if (ctx->pmeth != NULL
|
|
|
|
&& ctx->pmeth->pkey_id != EVP_PKEY_DH
|
|
|
|
&& ctx->pmeth->pkey_id != EVP_PKEY_DHX)
|
|
|
|
return -1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int EVP_PKEY_CTX_set_dh_paramgen_gindex(EVP_PKEY_CTX *ctx, int gindex)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
OSSL_PARAM params[2], *p = params;
|
|
|
|
|
|
|
|
if ((ret = dh_paramgen_check(ctx)) <= 0)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
*p++ = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_FFC_GINDEX, &gindex);
|
|
|
|
*p++ = OSSL_PARAM_construct_end();
|
|
|
|
|
|
|
|
return EVP_PKEY_CTX_set_params(ctx, params);
|
|
|
|
}
|
|
|
|
|
|
|
|
int EVP_PKEY_CTX_set_dh_paramgen_seed(EVP_PKEY_CTX *ctx,
|
|
|
|
const unsigned char *seed,
|
|
|
|
size_t seedlen)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
OSSL_PARAM params[2], *p = params;
|
|
|
|
|
|
|
|
if ((ret = dh_paramgen_check(ctx)) <= 0)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
*p++ = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_FFC_SEED,
|
|
|
|
(void *)seed, seedlen);
|
|
|
|
*p++ = OSSL_PARAM_construct_end();
|
|
|
|
|
|
|
|
return EVP_PKEY_CTX_set_params(ctx, params);
|
|
|
|
}
|
|
|
|
|
|
|
|
int EVP_PKEY_CTX_set_dh_paramgen_type(EVP_PKEY_CTX *ctx, int typ)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
OSSL_PARAM params[2], *p = params;
|
|
|
|
const char *name;
|
|
|
|
|
|
|
|
if ((ret = dh_paramgen_check(ctx)) <= 0)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
#if !defined(FIPS_MODE)
|
|
|
|
/* TODO(3.0): Remove this eventually when no more legacy */
|
|
|
|
if (ctx->op.keymgmt.genctx == NULL)
|
|
|
|
return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_PARAMGEN,
|
|
|
|
EVP_PKEY_CTRL_DH_PARAMGEN_TYPE, typ, NULL);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
name = dh_gen_type_id2name(typ);
|
|
|
|
if (name == NULL)
|
|
|
|
return 0;
|
|
|
|
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_FFC_TYPE,
|
|
|
|
(char *) name, 0);
|
|
|
|
*p++ = OSSL_PARAM_construct_end();
|
|
|
|
|
|
|
|
return EVP_PKEY_CTX_set_params(ctx, params);
|
|
|
|
}
|
|
|
|
|
|
|
|
int EVP_PKEY_CTX_set_dh_paramgen_prime_len(EVP_PKEY_CTX *ctx, int pbits)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
OSSL_PARAM params[2], *p = params;
|
|
|
|
size_t bits = pbits;
|
|
|
|
|
|
|
|
if ((ret = dh_paramgen_check(ctx)) <= 0)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
#if !defined(FIPS_MODE)
|
|
|
|
/* TODO(3.0): Remove this eventually when no more legacy */
|
|
|
|
if (ctx->op.keymgmt.genctx == NULL)
|
|
|
|
return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_PARAMGEN,
|
|
|
|
EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN, pbits,
|
|
|
|
NULL);
|
|
|
|
#endif
|
|
|
|
*p++ = OSSL_PARAM_construct_size_t(OSSL_PKEY_PARAM_FFC_PBITS, &bits);
|
|
|
|
*p++ = OSSL_PARAM_construct_end();
|
|
|
|
return EVP_PKEY_CTX_set_params(ctx, params);
|
|
|
|
}
|
|
|
|
|
|
|
|
int EVP_PKEY_CTX_set_dh_paramgen_subprime_len(EVP_PKEY_CTX *ctx, int qbits)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
OSSL_PARAM params[2], *p = params;
|
|
|
|
size_t bits2 = qbits;
|
|
|
|
|
|
|
|
if ((ret = dh_paramgen_check(ctx)) <= 0)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
#if !defined(FIPS_MODE)
|
|
|
|
/* TODO(3.0): Remove this eventually when no more legacy */
|
|
|
|
if (ctx->op.keymgmt.genctx == NULL)
|
|
|
|
return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_PARAMGEN,
|
|
|
|
EVP_PKEY_CTRL_DH_PARAMGEN_SUBPRIME_LEN, qbits,
|
|
|
|
NULL);
|
|
|
|
#endif
|
|
|
|
*p++ = OSSL_PARAM_construct_size_t(OSSL_PKEY_PARAM_FFC_QBITS, &bits2);
|
|
|
|
*p++ = OSSL_PARAM_construct_end();
|
|
|
|
|
|
|
|
return EVP_PKEY_CTX_set_params(ctx, params);
|
|
|
|
}
|
|
|
|
|
|
|
|
int EVP_PKEY_CTX_set_dh_paramgen_generator(EVP_PKEY_CTX *ctx, int gen)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
OSSL_PARAM params[2], *p = params;
|
|
|
|
|
|
|
|
if ((ret = dh_paramgen_check(ctx)) <= 0)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
#if !defined(FIPS_MODE)
|
|
|
|
/* TODO(3.0): Remove this eventually when no more legacy */
|
|
|
|
if (ctx->op.keymgmt.genctx == NULL)
|
|
|
|
return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_PARAMGEN,
|
|
|
|
EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR, gen, NULL);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
*p++ = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_FFC_GENERATOR, &gen);
|
|
|
|
*p++ = OSSL_PARAM_construct_end();
|
|
|
|
|
|
|
|
return EVP_PKEY_CTX_set_params(ctx, params);
|
|
|
|
}
|
|
|
|
|
|
|
|
int EVP_PKEY_CTX_set_dh_rfc5114(EVP_PKEY_CTX *ctx, int gen)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
OSSL_PARAM params[2], *p = params;
|
|
|
|
const char *name;
|
|
|
|
|
|
|
|
if ((ret = dh_paramgen_check(ctx)) <= 0)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
#if !defined(FIPS_MODE)
|
|
|
|
/* TODO(3.0): Remove this eventually when no more legacy */
|
|
|
|
if (ctx->op.keymgmt.genctx == NULL)
|
|
|
|
return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_PARAMGEN,
|
|
|
|
EVP_PKEY_CTRL_DH_RFC5114, gen, NULL);
|
|
|
|
#endif
|
|
|
|
name = ffc_named_group_from_uid(gen);
|
|
|
|
if (name == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_FFC_GROUP,
|
|
|
|
(void *)name, 0);
|
|
|
|
*p++ = OSSL_PARAM_construct_end();
|
|
|
|
return EVP_PKEY_CTX_set_params(ctx, params);
|
|
|
|
}
|
|
|
|
|
|
|
|
int EVP_PKEY_CTX_set_dhx_rfc5114(EVP_PKEY_CTX *ctx, int gen)
|
|
|
|
{
|
|
|
|
return EVP_PKEY_CTX_set_dh_rfc5114(ctx, gen);
|
|
|
|
}
|
|
|
|
|
|
|
|
int EVP_PKEY_CTX_set_dh_nid(EVP_PKEY_CTX *ctx, int nid)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
OSSL_PARAM params[2], *p = params;
|
|
|
|
const char *name;
|
|
|
|
|
|
|
|
if ((ret = dh_paramgen_check(ctx)) <= 0)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
#if !defined(FIPS_MODE)
|
|
|
|
/* TODO(3.0): Remove this eventually when no more legacy */
|
|
|
|
if (ctx->op.keymgmt.genctx == NULL)
|
|
|
|
return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH,
|
|
|
|
EVP_PKEY_OP_PARAMGEN | EVP_PKEY_OP_KEYGEN,
|
|
|
|
EVP_PKEY_CTRL_DH_NID, nid, NULL);
|
|
|
|
#endif
|
|
|
|
name = ffc_named_group_from_uid(nid);
|
|
|
|
if (name == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_FFC_GROUP,
|
|
|
|
(void *)name, 0);
|
|
|
|
*p++ = OSSL_PARAM_construct_end();
|
|
|
|
return EVP_PKEY_CTX_set_params(ctx, params);
|
|
|
|
}
|