check in v3.8.2 source
This commit is contained in:
557
crypto/dh/dh_ameth.c
Normal file
557
crypto/dh/dh_ameth.c
Normal file
@@ -0,0 +1,557 @@
|
||||
/* $OpenBSD: dh_ameth.c,v 1.39 2023/08/12 07:59:48 tb Exp $ */
|
||||
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
|
||||
* project 2006.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2006 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* licensing@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/dh.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/x509.h>
|
||||
|
||||
#include "asn1_local.h"
|
||||
#include "bn_local.h"
|
||||
#include "dh_local.h"
|
||||
#include "evp_local.h"
|
||||
|
||||
static void
|
||||
dh_free(EVP_PKEY *pkey)
|
||||
{
|
||||
DH_free(pkey->pkey.dh);
|
||||
}
|
||||
|
||||
static int
|
||||
dh_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
|
||||
{
|
||||
X509_ALGOR *algor;
|
||||
int ptype;
|
||||
const void *pval;
|
||||
const ASN1_STRING *astr;
|
||||
const unsigned char *key, *params, *p;
|
||||
int key_len, params_len;
|
||||
ASN1_INTEGER *aint = NULL;
|
||||
DH *dh = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (!X509_PUBKEY_get0_param(NULL, &key, &key_len, &algor, pubkey))
|
||||
goto err;
|
||||
X509_ALGOR_get0(NULL, &ptype, &pval, algor);
|
||||
|
||||
if (ptype != V_ASN1_SEQUENCE) {
|
||||
DHerror(DH_R_PARAMETER_ENCODING_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
astr = pval;
|
||||
params = astr->data;
|
||||
params_len = astr->length;
|
||||
|
||||
p = params;
|
||||
if ((dh = d2i_DHparams(NULL, &p, params_len)) == NULL) {
|
||||
DHerror(DH_R_DECODE_ERROR);
|
||||
goto err;
|
||||
}
|
||||
p = key;
|
||||
if ((aint = d2i_ASN1_INTEGER(NULL, &p, key_len)) == NULL) {
|
||||
DHerror(DH_R_DECODE_ERROR);
|
||||
goto err;
|
||||
}
|
||||
BN_free(dh->pub_key);
|
||||
if ((dh->pub_key = ASN1_INTEGER_to_BN(aint, NULL)) == NULL) {
|
||||
DHerror(DH_R_BN_DECODE_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!EVP_PKEY_assign_DH(pkey, dh))
|
||||
goto err;
|
||||
dh = NULL;
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
ASN1_INTEGER_free(aint);
|
||||
DH_free(dh);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
dh_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
|
||||
{
|
||||
const DH *dh = pkey->pkey.dh;
|
||||
ASN1_STRING *astr = NULL;
|
||||
int ptype = V_ASN1_SEQUENCE;
|
||||
ASN1_INTEGER *aint = NULL;
|
||||
ASN1_OBJECT *aobj;
|
||||
unsigned char *params = NULL, *key = NULL;
|
||||
int params_len = 0, key_len = 0;
|
||||
int ret = 0;
|
||||
|
||||
if ((params_len = i2d_DHparams(dh, ¶ms)) <= 0) {
|
||||
DHerror(ERR_R_MALLOC_FAILURE);
|
||||
params_len = 0;
|
||||
goto err;
|
||||
}
|
||||
if ((astr = ASN1_STRING_new()) == NULL) {
|
||||
DHerror(ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
ASN1_STRING_set0(astr, params, params_len);
|
||||
params = NULL;
|
||||
params_len = 0;
|
||||
|
||||
if ((aint = BN_to_ASN1_INTEGER(dh->pub_key, NULL)) == NULL)
|
||||
goto err;
|
||||
if ((key_len = i2d_ASN1_INTEGER(aint, &key)) <= 0) {
|
||||
DHerror(ERR_R_MALLOC_FAILURE);
|
||||
key_len = 0;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((aobj = OBJ_nid2obj(EVP_PKEY_DH)) == NULL)
|
||||
goto err;
|
||||
if (!X509_PUBKEY_set0_param(pk, aobj, ptype, astr, key, key_len))
|
||||
goto err;
|
||||
astr = NULL;
|
||||
key = NULL;
|
||||
key_len = 0;
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
ASN1_STRING_free(astr);
|
||||
ASN1_INTEGER_free(aint);
|
||||
freezero(params, params_len);
|
||||
freezero(key, key_len);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* PKCS#8 DH is defined in PKCS#11 of all places. It is similar to DH in
|
||||
* that the AlgorithmIdentifier contains the parameters, the private key
|
||||
* is explcitly included and the pubkey must be recalculated.
|
||||
*/
|
||||
|
||||
static int
|
||||
dh_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8)
|
||||
{
|
||||
const X509_ALGOR *algor;
|
||||
int ptype;
|
||||
const void *pval;
|
||||
const ASN1_STRING *astr;
|
||||
const unsigned char *key, *params, *p;
|
||||
int key_len, params_len;
|
||||
ASN1_INTEGER *aint = NULL;
|
||||
DH *dh = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (!PKCS8_pkey_get0(NULL, &key, &key_len, &algor, p8))
|
||||
goto err;
|
||||
X509_ALGOR_get0(NULL, &ptype, &pval, algor);
|
||||
|
||||
if (ptype != V_ASN1_SEQUENCE) {
|
||||
DHerror(DH_R_PARAMETER_ENCODING_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
astr = pval;
|
||||
params = astr->data;
|
||||
params_len = astr->length;
|
||||
|
||||
p = params;
|
||||
if ((dh = d2i_DHparams(NULL, &p, params_len)) == NULL) {
|
||||
DHerror(DH_R_DECODE_ERROR);
|
||||
goto err;
|
||||
}
|
||||
p = key;
|
||||
if ((aint = d2i_ASN1_INTEGER(NULL, &p, key_len)) == NULL) {
|
||||
DHerror(DH_R_DECODE_ERROR);
|
||||
goto err;
|
||||
}
|
||||
BN_free(dh->priv_key);
|
||||
if ((dh->priv_key = ASN1_INTEGER_to_BN(aint, NULL)) == NULL) {
|
||||
DHerror(DH_R_BN_DECODE_ERROR);
|
||||
goto err;
|
||||
}
|
||||
if (!DH_generate_key(dh))
|
||||
goto err;
|
||||
|
||||
if (!EVP_PKEY_assign_DH(pkey, dh))
|
||||
goto err;
|
||||
dh = NULL;
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
ASN1_INTEGER_free(aint);
|
||||
DH_free(dh);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
dh_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
|
||||
{
|
||||
const DH *dh = pkey->pkey.dh;
|
||||
ASN1_STRING *astr = NULL;
|
||||
int ptype = V_ASN1_SEQUENCE;
|
||||
ASN1_INTEGER *aint = NULL;
|
||||
ASN1_OBJECT *aobj;
|
||||
unsigned char *params = NULL, *key = NULL;
|
||||
int params_len = 0, key_len = 0;
|
||||
int ret = 0;
|
||||
|
||||
if ((params_len = i2d_DHparams(dh, ¶ms)) <= 0) {
|
||||
DHerror(ERR_R_MALLOC_FAILURE);
|
||||
params_len = 0;
|
||||
goto err;
|
||||
}
|
||||
if ((astr = ASN1_STRING_type_new(V_ASN1_SEQUENCE)) == NULL) {
|
||||
DHerror(ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
ASN1_STRING_set0(astr, params, params_len);
|
||||
params = NULL;
|
||||
params_len = 0;
|
||||
|
||||
if ((aint = BN_to_ASN1_INTEGER(dh->priv_key, NULL)) == NULL) {
|
||||
DHerror(DH_R_BN_ERROR);
|
||||
goto err;
|
||||
}
|
||||
if ((key_len = i2d_ASN1_INTEGER(aint, &key)) <= 0) {
|
||||
DHerror(ERR_R_MALLOC_FAILURE);
|
||||
key_len = 0;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((aobj = OBJ_nid2obj(NID_dhKeyAgreement)) == NULL)
|
||||
goto err;
|
||||
if (!PKCS8_pkey_set0(p8, aobj, 0, ptype, astr, key, key_len))
|
||||
goto err;
|
||||
astr = NULL;
|
||||
key = NULL;
|
||||
key_len = 0;
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
ASN1_STRING_free(astr);
|
||||
ASN1_INTEGER_free(aint);
|
||||
freezero(params, params_len);
|
||||
freezero(key, key_len);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
dh_param_decode(EVP_PKEY *pkey, const unsigned char **params, int params_len)
|
||||
{
|
||||
DH *dh = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if ((dh = d2i_DHparams(NULL, params, params_len)) == NULL) {
|
||||
DHerror(ERR_R_DH_LIB);
|
||||
goto err;
|
||||
}
|
||||
if (!EVP_PKEY_assign_DH(pkey, dh))
|
||||
goto err;
|
||||
dh = NULL;
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
DH_free(dh);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
dh_param_encode(const EVP_PKEY *pkey, unsigned char **params)
|
||||
{
|
||||
return i2d_DHparams(pkey->pkey.dh, params);
|
||||
}
|
||||
|
||||
static int
|
||||
do_dh_print(BIO *bp, const DH *x, int indent, ASN1_PCTX *ctx, int ptype)
|
||||
{
|
||||
int reason = ERR_R_BUF_LIB, ret = 0;
|
||||
const char *ktype = NULL;
|
||||
BIGNUM *priv_key, *pub_key;
|
||||
|
||||
if (ptype == 2)
|
||||
priv_key = x->priv_key;
|
||||
else
|
||||
priv_key = NULL;
|
||||
|
||||
if (ptype > 0)
|
||||
pub_key = x->pub_key;
|
||||
else
|
||||
pub_key = NULL;
|
||||
|
||||
if (ptype == 2)
|
||||
ktype = "PKCS#3 DH Private-Key";
|
||||
else if (ptype == 1)
|
||||
ktype = "PKCS#3 DH Public-Key";
|
||||
else
|
||||
ktype = "PKCS#3 DH Parameters";
|
||||
|
||||
if (x->p == NULL) {
|
||||
reason = ERR_R_PASSED_NULL_PARAMETER;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!BIO_indent(bp, indent, 128))
|
||||
goto err;
|
||||
if (BIO_printf(bp, "%s: (%d bit)\n", ktype, BN_num_bits(x->p)) <= 0)
|
||||
goto err;
|
||||
indent += 4;
|
||||
|
||||
if (!bn_printf(bp, priv_key, indent, "private-key:"))
|
||||
goto err;
|
||||
if (!bn_printf(bp, pub_key, indent, "public-key:"))
|
||||
goto err;
|
||||
|
||||
if (!bn_printf(bp, x->p, indent, "prime:"))
|
||||
goto err;
|
||||
if (!bn_printf(bp, x->g, indent, "generator:"))
|
||||
goto err;
|
||||
if (x->length != 0) {
|
||||
if (!BIO_indent(bp, indent, 128))
|
||||
goto err;
|
||||
if (BIO_printf(bp, "recommended-private-length: %d bits\n",
|
||||
(int)x->length) <= 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
if (0) {
|
||||
err:
|
||||
DHerror(reason);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static int
|
||||
dh_size(const EVP_PKEY *pkey)
|
||||
{
|
||||
return DH_size(pkey->pkey.dh);
|
||||
}
|
||||
|
||||
static int
|
||||
dh_bits(const EVP_PKEY *pkey)
|
||||
{
|
||||
return BN_num_bits(pkey->pkey.dh->p);
|
||||
}
|
||||
|
||||
static int
|
||||
dh_security_bits(const EVP_PKEY *pkey)
|
||||
{
|
||||
return DH_security_bits(pkey->pkey.dh);
|
||||
}
|
||||
|
||||
static int
|
||||
dh_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
|
||||
{
|
||||
if (BN_cmp(a->pkey.dh->p, b->pkey.dh->p) ||
|
||||
BN_cmp(a->pkey.dh->g, b->pkey.dh->g))
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
dh_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
|
||||
{
|
||||
BIGNUM *a;
|
||||
|
||||
if ((a = BN_dup(from->pkey.dh->p)) == NULL)
|
||||
return 0;
|
||||
BN_free(to->pkey.dh->p);
|
||||
to->pkey.dh->p = a;
|
||||
|
||||
if ((a = BN_dup(from->pkey.dh->g)) == NULL)
|
||||
return 0;
|
||||
BN_free(to->pkey.dh->g);
|
||||
to->pkey.dh->g = a;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
dh_missing_parameters(const EVP_PKEY *pkey)
|
||||
{
|
||||
const DH *dh = pkey->pkey.dh;
|
||||
|
||||
return dh->p == NULL || dh->g == NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
dh_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
|
||||
{
|
||||
if (dh_cmp_parameters(a, b) == 0)
|
||||
return 0;
|
||||
if (BN_cmp(b->pkey.dh->pub_key, a->pkey.dh->pub_key) != 0)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
dh_param_print(BIO *bp, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx)
|
||||
{
|
||||
return do_dh_print(bp, pkey->pkey.dh, indent, ctx, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
dh_public_print(BIO *bp, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx)
|
||||
{
|
||||
return do_dh_print(bp, pkey->pkey.dh, indent, ctx, 1);
|
||||
}
|
||||
|
||||
static int
|
||||
dh_private_print(BIO *bp, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx)
|
||||
{
|
||||
return do_dh_print(bp, pkey->pkey.dh, indent, ctx, 2);
|
||||
}
|
||||
|
||||
int
|
||||
DHparams_print(BIO *bp, const DH *x)
|
||||
{
|
||||
return do_dh_print(bp, x, 4, NULL, 0);
|
||||
}
|
||||
LCRYPTO_ALIAS(DHparams_print);
|
||||
|
||||
int
|
||||
DHparams_print_fp(FILE *fp, const DH *x)
|
||||
{
|
||||
BIO *b;
|
||||
int ret;
|
||||
|
||||
if ((b = BIO_new(BIO_s_file())) == NULL) {
|
||||
DHerror(ERR_R_BUF_LIB);
|
||||
return 0;
|
||||
}
|
||||
|
||||
BIO_set_fp(b, fp, BIO_NOCLOSE);
|
||||
ret = DHparams_print(b, x);
|
||||
BIO_free(b);
|
||||
|
||||
return ret;
|
||||
}
|
||||
LCRYPTO_ALIAS(DHparams_print_fp);
|
||||
|
||||
static int
|
||||
dh_pkey_public_check(const EVP_PKEY *pkey)
|
||||
{
|
||||
DH *dh = pkey->pkey.dh;
|
||||
|
||||
if (dh->pub_key == NULL) {
|
||||
DHerror(DH_R_MISSING_PUBKEY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return DH_check_pub_key_ex(dh, dh->pub_key);
|
||||
}
|
||||
|
||||
static int
|
||||
dh_pkey_param_check(const EVP_PKEY *pkey)
|
||||
{
|
||||
DH *dh = pkey->pkey.dh;
|
||||
|
||||
/*
|
||||
* It would have made more sense to support EVP_PKEY_check() for DH
|
||||
* keys and call DH_check_ex() there and keeping this as a wrapper
|
||||
* for DH_param_check_ex(). We follow OpenSSL's choice.
|
||||
*/
|
||||
return DH_check_ex(dh);
|
||||
}
|
||||
|
||||
const EVP_PKEY_ASN1_METHOD dh_asn1_meth = {
|
||||
.pkey_id = EVP_PKEY_DH,
|
||||
.pkey_base_id = EVP_PKEY_DH,
|
||||
|
||||
.pem_str = "DH",
|
||||
.info = "OpenSSL PKCS#3 DH method",
|
||||
|
||||
.pub_decode = dh_pub_decode,
|
||||
.pub_encode = dh_pub_encode,
|
||||
.pub_cmp = dh_pub_cmp,
|
||||
.pub_print = dh_public_print,
|
||||
|
||||
.priv_decode = dh_priv_decode,
|
||||
.priv_encode = dh_priv_encode,
|
||||
.priv_print = dh_private_print,
|
||||
|
||||
.pkey_size = dh_size,
|
||||
.pkey_bits = dh_bits,
|
||||
.pkey_security_bits = dh_security_bits,
|
||||
|
||||
.param_decode = dh_param_decode,
|
||||
.param_encode = dh_param_encode,
|
||||
.param_missing = dh_missing_parameters,
|
||||
.param_copy = dh_copy_parameters,
|
||||
.param_cmp = dh_cmp_parameters,
|
||||
.param_print = dh_param_print,
|
||||
|
||||
.pkey_free = dh_free,
|
||||
|
||||
.pkey_check = NULL,
|
||||
.pkey_public_check = dh_pkey_public_check,
|
||||
.pkey_param_check = dh_pkey_param_check,
|
||||
};
|
176
crypto/dh/dh_asn1.c
Normal file
176
crypto/dh/dh_asn1.c
Normal file
@@ -0,0 +1,176 @@
|
||||
/* $OpenBSD: dh_asn1.c,v 1.12 2023/07/08 15:29:03 beck Exp $ */
|
||||
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
|
||||
* project 2000.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2000-2005 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* licensing@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/dh.h>
|
||||
#include <openssl/objects.h>
|
||||
|
||||
#include "dh_local.h"
|
||||
|
||||
/* Override the default free and new methods */
|
||||
static int
|
||||
dh_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
|
||||
{
|
||||
if (operation == ASN1_OP_NEW_PRE) {
|
||||
*pval = (ASN1_VALUE *)DH_new();
|
||||
if (*pval)
|
||||
return 2;
|
||||
return 0;
|
||||
} else if (operation == ASN1_OP_FREE_PRE) {
|
||||
DH_free((DH *)*pval);
|
||||
*pval = NULL;
|
||||
return 2;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const ASN1_AUX DHparams_aux = {
|
||||
.app_data = NULL,
|
||||
.flags = 0,
|
||||
.ref_offset = 0,
|
||||
.ref_lock = 0,
|
||||
.asn1_cb = dh_cb,
|
||||
.enc_offset = 0,
|
||||
};
|
||||
static const ASN1_TEMPLATE DHparams_seq_tt[] = {
|
||||
{
|
||||
.flags = 0,
|
||||
.tag = 0,
|
||||
.offset = offsetof(DH, p),
|
||||
.field_name = "p",
|
||||
.item = &BIGNUM_it,
|
||||
},
|
||||
{
|
||||
.flags = 0,
|
||||
.tag = 0,
|
||||
.offset = offsetof(DH, g),
|
||||
.field_name = "g",
|
||||
.item = &BIGNUM_it,
|
||||
},
|
||||
{
|
||||
.flags = ASN1_TFLG_OPTIONAL,
|
||||
.tag = 0,
|
||||
.offset = offsetof(DH, length),
|
||||
.field_name = "length",
|
||||
.item = &ZLONG_it,
|
||||
},
|
||||
};
|
||||
|
||||
const ASN1_ITEM DHparams_it = {
|
||||
.itype = ASN1_ITYPE_SEQUENCE,
|
||||
.utype = V_ASN1_SEQUENCE,
|
||||
.templates = DHparams_seq_tt,
|
||||
.tcount = sizeof(DHparams_seq_tt) / sizeof(ASN1_TEMPLATE),
|
||||
.funcs = &DHparams_aux,
|
||||
.size = sizeof(DH),
|
||||
.sname = "DH",
|
||||
};
|
||||
|
||||
|
||||
DH *
|
||||
d2i_DHparams(DH **a, const unsigned char **in, long len)
|
||||
{
|
||||
return (DH *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
|
||||
&DHparams_it);
|
||||
}
|
||||
LCRYPTO_ALIAS(d2i_DHparams);
|
||||
|
||||
int
|
||||
i2d_DHparams(const DH *a, unsigned char **out)
|
||||
{
|
||||
return ASN1_item_i2d((ASN1_VALUE *)a, out, &DHparams_it);
|
||||
}
|
||||
LCRYPTO_ALIAS(i2d_DHparams);
|
||||
|
||||
DH *
|
||||
d2i_DHparams_bio(BIO *bp, DH **a)
|
||||
{
|
||||
return ASN1_item_d2i_bio(&DHparams_it, bp, a);
|
||||
}
|
||||
LCRYPTO_ALIAS(d2i_DHparams_bio);
|
||||
|
||||
int
|
||||
i2d_DHparams_bio(BIO *bp, DH *a)
|
||||
{
|
||||
return ASN1_item_i2d_bio(&DHparams_it, bp, a);
|
||||
}
|
||||
LCRYPTO_ALIAS(i2d_DHparams_bio);
|
||||
|
||||
DH *
|
||||
d2i_DHparams_fp(FILE *fp, DH **a)
|
||||
{
|
||||
return ASN1_item_d2i_fp(&DHparams_it, fp, a);
|
||||
}
|
||||
LCRYPTO_ALIAS(d2i_DHparams_fp);
|
||||
|
||||
int
|
||||
i2d_DHparams_fp(FILE *fp, DH *a)
|
||||
{
|
||||
return ASN1_item_i2d_fp(&DHparams_it, fp, a);
|
||||
}
|
||||
LCRYPTO_ALIAS(i2d_DHparams_fp);
|
||||
|
||||
DH *
|
||||
DHparams_dup(DH *dh)
|
||||
{
|
||||
return ASN1_item_dup(&DHparams_it, dh);
|
||||
}
|
||||
LCRYPTO_ALIAS(DHparams_dup);
|
303
crypto/dh/dh_check.c
Normal file
303
crypto/dh/dh_check.c
Normal file
@@ -0,0 +1,303 @@
|
||||
/* $OpenBSD: dh_check.c,v 1.28 2023/07/24 16:25:02 tb Exp $ */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/dh.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "bn_local.h"
|
||||
#include "dh_local.h"
|
||||
|
||||
#define DH_NUMBER_ITERATIONS_FOR_PRIME 64
|
||||
|
||||
/*
|
||||
* Check that p is odd and 1 < g < p - 1. The _ex version removes the need of
|
||||
* inspecting flags and pushes errors on the stack instead.
|
||||
*/
|
||||
|
||||
int
|
||||
DH_check_params_ex(const DH *dh)
|
||||
{
|
||||
int flags = 0;
|
||||
|
||||
if (!DH_check_params(dh, &flags))
|
||||
return 0;
|
||||
|
||||
if ((flags & DH_CHECK_P_NOT_PRIME) != 0)
|
||||
DHerror(DH_R_CHECK_P_NOT_PRIME);
|
||||
if ((flags & DH_NOT_SUITABLE_GENERATOR) != 0)
|
||||
DHerror(DH_R_NOT_SUITABLE_GENERATOR);
|
||||
|
||||
return flags == 0;
|
||||
}
|
||||
|
||||
int
|
||||
DH_check_params(const DH *dh, int *flags)
|
||||
{
|
||||
BIGNUM *max_g = NULL;
|
||||
int ok = 0;
|
||||
|
||||
*flags = 0;
|
||||
|
||||
if (!BN_is_odd(dh->p))
|
||||
*flags |= DH_CHECK_P_NOT_PRIME;
|
||||
|
||||
/*
|
||||
* Check that 1 < dh->g < p - 1
|
||||
*/
|
||||
|
||||
if (BN_cmp(dh->g, BN_value_one()) <= 0)
|
||||
*flags |= DH_NOT_SUITABLE_GENERATOR;
|
||||
/* max_g = p - 1 */
|
||||
if ((max_g = BN_dup(dh->p)) == NULL)
|
||||
goto err;
|
||||
if (!BN_sub_word(max_g, 1))
|
||||
goto err;
|
||||
/* check that g < max_g */
|
||||
if (BN_cmp(dh->g, max_g) >= 0)
|
||||
*flags |= DH_NOT_SUITABLE_GENERATOR;
|
||||
|
||||
ok = 1;
|
||||
|
||||
err:
|
||||
BN_free(max_g);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that p is a safe prime and that g is a suitable generator.
|
||||
* The _ex version puts errors on the stack instead of returning flags.
|
||||
*/
|
||||
|
||||
int
|
||||
DH_check_ex(const DH *dh)
|
||||
{
|
||||
int flags = 0;
|
||||
|
||||
if (!DH_check(dh, &flags))
|
||||
return 0;
|
||||
|
||||
if ((flags & DH_NOT_SUITABLE_GENERATOR) != 0)
|
||||
DHerror(DH_R_NOT_SUITABLE_GENERATOR);
|
||||
if ((flags & DH_CHECK_Q_NOT_PRIME) != 0)
|
||||
DHerror(DH_R_CHECK_Q_NOT_PRIME);
|
||||
if ((flags & DH_CHECK_INVALID_Q_VALUE) != 0)
|
||||
DHerror(DH_R_CHECK_INVALID_Q_VALUE);
|
||||
if ((flags & DH_CHECK_INVALID_J_VALUE) != 0)
|
||||
DHerror(DH_R_CHECK_INVALID_J_VALUE);
|
||||
if ((flags & DH_UNABLE_TO_CHECK_GENERATOR) != 0)
|
||||
DHerror(DH_R_UNABLE_TO_CHECK_GENERATOR);
|
||||
if ((flags & DH_CHECK_P_NOT_PRIME) != 0)
|
||||
DHerror(DH_R_CHECK_P_NOT_PRIME);
|
||||
if ((flags & DH_CHECK_P_NOT_SAFE_PRIME) != 0)
|
||||
DHerror(DH_R_CHECK_P_NOT_SAFE_PRIME);
|
||||
|
||||
return flags == 0;
|
||||
}
|
||||
|
||||
int
|
||||
DH_check(const DH *dh, int *flags)
|
||||
{
|
||||
BN_CTX *ctx = NULL;
|
||||
int is_prime;
|
||||
int ok = 0;
|
||||
|
||||
*flags = 0;
|
||||
|
||||
if (!DH_check_params(dh, flags))
|
||||
goto err;
|
||||
|
||||
ctx = BN_CTX_new();
|
||||
if (ctx == NULL)
|
||||
goto err;
|
||||
BN_CTX_start(ctx);
|
||||
|
||||
if (dh->q != NULL) {
|
||||
BIGNUM *quotient, *residue;
|
||||
|
||||
if ((quotient = BN_CTX_get(ctx)) == NULL)
|
||||
goto err;
|
||||
if ((residue = BN_CTX_get(ctx)) == NULL)
|
||||
goto err;
|
||||
if ((*flags & DH_NOT_SUITABLE_GENERATOR) == 0) {
|
||||
/* Check g^q == 1 mod p */
|
||||
if (!BN_mod_exp_ct(residue, dh->g, dh->q, dh->p, ctx))
|
||||
goto err;
|
||||
if (!BN_is_one(residue))
|
||||
*flags |= DH_NOT_SUITABLE_GENERATOR;
|
||||
}
|
||||
is_prime = BN_is_prime_ex(dh->q, DH_NUMBER_ITERATIONS_FOR_PRIME,
|
||||
ctx, NULL);
|
||||
if (is_prime < 0)
|
||||
goto err;
|
||||
if (is_prime == 0)
|
||||
*flags |= DH_CHECK_Q_NOT_PRIME;
|
||||
/* Check p == 1 mod q, i.e., q divides p - 1 */
|
||||
if (!BN_div_ct(quotient, residue, dh->p, dh->q, ctx))
|
||||
goto err;
|
||||
if (!BN_is_one(residue))
|
||||
*flags |= DH_CHECK_INVALID_Q_VALUE;
|
||||
if (dh->j != NULL && BN_cmp(dh->j, quotient) != 0)
|
||||
*flags |= DH_CHECK_INVALID_J_VALUE;
|
||||
}
|
||||
|
||||
is_prime = BN_is_prime_ex(dh->p, DH_NUMBER_ITERATIONS_FOR_PRIME,
|
||||
ctx, NULL);
|
||||
if (is_prime < 0)
|
||||
goto err;
|
||||
if (is_prime == 0)
|
||||
*flags |= DH_CHECK_P_NOT_PRIME;
|
||||
else if (dh->q == NULL) {
|
||||
BIGNUM *q;
|
||||
|
||||
if ((q = BN_CTX_get(ctx)) == NULL)
|
||||
goto err;
|
||||
if (!BN_rshift1(q, dh->p))
|
||||
goto err;
|
||||
is_prime = BN_is_prime_ex(q, DH_NUMBER_ITERATIONS_FOR_PRIME,
|
||||
ctx, NULL);
|
||||
if (is_prime < 0)
|
||||
goto err;
|
||||
if (is_prime == 0)
|
||||
*flags |= DH_CHECK_P_NOT_SAFE_PRIME;
|
||||
}
|
||||
|
||||
ok = 1;
|
||||
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(ctx);
|
||||
return ok;
|
||||
}
|
||||
LCRYPTO_ALIAS(DH_check);
|
||||
|
||||
int
|
||||
DH_check_pub_key_ex(const DH *dh, const BIGNUM *pub_key)
|
||||
{
|
||||
int flags = 0;
|
||||
|
||||
if (!DH_check_pub_key(dh, pub_key, &flags))
|
||||
return 0;
|
||||
|
||||
if ((flags & DH_CHECK_PUBKEY_TOO_SMALL) != 0)
|
||||
DHerror(DH_R_CHECK_PUBKEY_TOO_SMALL);
|
||||
if ((flags & DH_CHECK_PUBKEY_TOO_LARGE) != 0)
|
||||
DHerror(DH_R_CHECK_PUBKEY_TOO_LARGE);
|
||||
if ((flags & DH_CHECK_PUBKEY_INVALID) != 0)
|
||||
DHerror(DH_R_CHECK_PUBKEY_INVALID);
|
||||
|
||||
return flags == 0;
|
||||
}
|
||||
|
||||
int
|
||||
DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *flags)
|
||||
{
|
||||
BN_CTX *ctx = NULL;
|
||||
BIGNUM *max_pub_key;
|
||||
int ok = 0;
|
||||
|
||||
*flags = 0;
|
||||
|
||||
if ((ctx = BN_CTX_new()) == NULL)
|
||||
goto err;
|
||||
BN_CTX_start(ctx);
|
||||
if ((max_pub_key = BN_CTX_get(ctx)) == NULL)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* Check that 1 < pub_key < dh->p - 1
|
||||
*/
|
||||
|
||||
if (BN_cmp(pub_key, BN_value_one()) <= 0)
|
||||
*flags |= DH_CHECK_PUBKEY_TOO_SMALL;
|
||||
|
||||
/* max_pub_key = dh->p - 1 */
|
||||
if (!BN_sub(max_pub_key, dh->p, BN_value_one()))
|
||||
goto err;
|
||||
|
||||
if (BN_cmp(pub_key, max_pub_key) >= 0)
|
||||
*flags |= DH_CHECK_PUBKEY_TOO_LARGE;
|
||||
|
||||
/*
|
||||
* If dh->q is set, check that pub_key^q == 1 mod p
|
||||
*/
|
||||
|
||||
if (dh->q != NULL) {
|
||||
BIGNUM *residue;
|
||||
|
||||
if ((residue = BN_CTX_get(ctx)) == NULL)
|
||||
goto err;
|
||||
|
||||
if (!BN_mod_exp_ct(residue, pub_key, dh->q, dh->p, ctx))
|
||||
goto err;
|
||||
if (!BN_is_one(residue))
|
||||
*flags |= DH_CHECK_PUBKEY_INVALID;
|
||||
}
|
||||
|
||||
ok = 1;
|
||||
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(ctx);
|
||||
|
||||
return ok;
|
||||
}
|
||||
LCRYPTO_ALIAS(DH_check_pub_key);
|
114
crypto/dh/dh_err.c
Normal file
114
crypto/dh/dh_err.c
Normal file
@@ -0,0 +1,114 @@
|
||||
/* $OpenBSD: dh_err.c,v 1.19 2023/07/08 15:29:03 beck Exp $ */
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1999-2011 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <openssl/opensslconf.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/dh.h>
|
||||
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
|
||||
#define ERR_FUNC(func) ERR_PACK(ERR_LIB_DH,func,0)
|
||||
#define ERR_REASON(reason) ERR_PACK(ERR_LIB_DH,0,reason)
|
||||
|
||||
static ERR_STRING_DATA DH_str_functs[]= {
|
||||
{ERR_FUNC(0xfff), "CRYPTO_internal"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
static ERR_STRING_DATA DH_str_reasons[]=
|
||||
{
|
||||
{ERR_REASON(DH_R_BAD_GENERATOR) ,"bad generator"},
|
||||
{ERR_REASON(DH_R_BN_DECODE_ERROR) ,"bn decode error"},
|
||||
{ERR_REASON(DH_R_BN_ERROR) ,"bn error"},
|
||||
{ERR_REASON(DH_R_DECODE_ERROR) ,"decode error"},
|
||||
{ERR_REASON(DH_R_INVALID_PUBKEY) ,"invalid public key"},
|
||||
{ERR_REASON(DH_R_KEYS_NOT_SET) ,"keys not set"},
|
||||
{ERR_REASON(DH_R_KEY_SIZE_TOO_SMALL) ,"key size too small"},
|
||||
{ERR_REASON(DH_R_MODULUS_TOO_LARGE) ,"modulus too large"},
|
||||
{ERR_REASON(DH_R_NON_FIPS_METHOD) ,"non fips method"},
|
||||
{ERR_REASON(DH_R_NO_PARAMETERS_SET) ,"no parameters set"},
|
||||
{ERR_REASON(DH_R_NO_PRIVATE_VALUE) ,"no private value"},
|
||||
{ERR_REASON(DH_R_PARAMETER_ENCODING_ERROR),"parameter encoding error"},
|
||||
{ERR_REASON(DH_R_CHECK_INVALID_J_VALUE) ,"check invalid j value"},
|
||||
{ERR_REASON(DH_R_CHECK_INVALID_Q_VALUE) ,"check invalid q value"},
|
||||
{ERR_REASON(DH_R_CHECK_PUBKEY_INVALID) ,"check pubkey invalid"},
|
||||
{ERR_REASON(DH_R_CHECK_PUBKEY_TOO_LARGE) ,"check pubkey too large"},
|
||||
{ERR_REASON(DH_R_CHECK_PUBKEY_TOO_SMALL) ,"check pubkey too small"},
|
||||
{ERR_REASON(DH_R_CHECK_P_NOT_PRIME) ,"check p not prime"},
|
||||
{ERR_REASON(DH_R_CHECK_P_NOT_SAFE_PRIME) ,"check p not safe prime"},
|
||||
{ERR_REASON(DH_R_CHECK_Q_NOT_PRIME) ,"check q not prime"},
|
||||
{ERR_REASON(DH_R_MISSING_PUBKEY) ,"missing pubkey"},
|
||||
{ERR_REASON(DH_R_NOT_SUITABLE_GENERATOR) ,"not suitable generator"},
|
||||
{ERR_REASON(DH_R_UNABLE_TO_CHECK_GENERATOR),"unable to check generator"},
|
||||
{0,NULL}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
void ERR_load_DH_strings(void)
|
||||
{
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
|
||||
if (ERR_func_error_string(DH_str_functs[0].error) == NULL)
|
||||
{
|
||||
ERR_load_strings(0,DH_str_functs);
|
||||
ERR_load_strings(0,DH_str_reasons);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
LCRYPTO_ALIAS(ERR_load_DH_strings);
|
197
crypto/dh/dh_gen.c
Normal file
197
crypto/dh/dh_gen.c
Normal file
@@ -0,0 +1,197 @@
|
||||
/* $OpenBSD: dh_gen.c,v 1.21 2023/07/08 15:29:03 beck Exp $ */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/dh.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "bn_local.h"
|
||||
#include "dh_local.h"
|
||||
|
||||
static int dh_builtin_genparams(DH *ret, int prime_len, int generator,
|
||||
BN_GENCB *cb);
|
||||
|
||||
int
|
||||
DH_generate_parameters_ex(DH *ret, int prime_len, int generator, BN_GENCB *cb)
|
||||
{
|
||||
if (ret->meth->generate_params)
|
||||
return ret->meth->generate_params(ret, prime_len, generator, cb);
|
||||
return dh_builtin_genparams(ret, prime_len, generator, cb);
|
||||
}
|
||||
LCRYPTO_ALIAS(DH_generate_parameters_ex);
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* Thanks to Phil Karn <karn@qualcomm.com> 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.
|
||||
*/
|
||||
static int
|
||||
dh_builtin_genparams(DH *ret, int prime_len, int generator, BN_GENCB *cb)
|
||||
{
|
||||
BIGNUM *t1, *t2;
|
||||
int g, ok = -1;
|
||||
BN_CTX *ctx = NULL;
|
||||
|
||||
ctx = BN_CTX_new();
|
||||
if (ctx == NULL)
|
||||
goto err;
|
||||
BN_CTX_start(ctx);
|
||||
if ((t1 = BN_CTX_get(ctx)) == NULL)
|
||||
goto err;
|
||||
if ((t2 = BN_CTX_get(ctx)) == NULL)
|
||||
goto err;
|
||||
|
||||
/* Make sure 'ret' has the necessary elements */
|
||||
if (!ret->p && ((ret->p = BN_new()) == NULL))
|
||||
goto err;
|
||||
if (!ret->g && ((ret->g = BN_new()) == NULL))
|
||||
goto err;
|
||||
|
||||
if (generator <= 1) {
|
||||
DHerror(DH_R_BAD_GENERATOR);
|
||||
goto err;
|
||||
}
|
||||
if (generator == DH_GENERATOR_2) {
|
||||
if (!BN_set_word(t1, 24))
|
||||
goto err;
|
||||
if (!BN_set_word(t2, 11))
|
||||
goto err;
|
||||
g = 2;
|
||||
} else if (generator == DH_GENERATOR_5) {
|
||||
if (!BN_set_word(t1, 10))
|
||||
goto err;
|
||||
if (!BN_set_word(t2, 3))
|
||||
goto err;
|
||||
/* BN_set_word(t3,7); just have to miss
|
||||
* out on these ones :-( */
|
||||
g = 5;
|
||||
} else {
|
||||
/*
|
||||
* in the general case, don't worry if 'generator' is a
|
||||
* generator or 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))
|
||||
goto err;
|
||||
if (!BN_set_word(t2, 1))
|
||||
goto err;
|
||||
g = generator;
|
||||
}
|
||||
|
||||
if (!BN_generate_prime_ex(ret->p, prime_len, 1, t1, t2, cb))
|
||||
goto err;
|
||||
if (!BN_GENCB_call(cb, 3, 0))
|
||||
goto err;
|
||||
if (!BN_set_word(ret->g, g))
|
||||
goto err;
|
||||
ok = 1;
|
||||
err:
|
||||
if (ok == -1) {
|
||||
DHerror(ERR_R_BN_LIB);
|
||||
ok = 0;
|
||||
}
|
||||
|
||||
if (ctx != NULL) {
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(ctx);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
DH *
|
||||
DH_generate_parameters(int prime_len, int generator,
|
||||
void (*callback)(int, int, void *), void *cb_arg)
|
||||
{
|
||||
BN_GENCB cb;
|
||||
DH *ret = NULL;
|
||||
|
||||
if ((ret = DH_new()) == NULL)
|
||||
return NULL;
|
||||
|
||||
BN_GENCB_set_old(&cb, callback, cb_arg);
|
||||
|
||||
if (DH_generate_parameters_ex(ret, prime_len, generator, &cb))
|
||||
return ret;
|
||||
DH_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
LCRYPTO_ALIAS(DH_generate_parameters);
|
247
crypto/dh/dh_key.c
Normal file
247
crypto/dh/dh_key.c
Normal file
@@ -0,0 +1,247 @@
|
||||
/* $OpenBSD: dh_key.c,v 1.40 2023/08/03 18:53:55 tb Exp $ */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/dh.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "bn_local.h"
|
||||
#include "dh_local.h"
|
||||
|
||||
static int generate_key(DH *dh);
|
||||
static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh);
|
||||
static int dh_bn_mod_exp(const DH *dh, BIGNUM *r, const BIGNUM *a,
|
||||
const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
|
||||
static int dh_init(DH *dh);
|
||||
static int dh_finish(DH *dh);
|
||||
|
||||
int
|
||||
DH_generate_key(DH *dh)
|
||||
{
|
||||
return dh->meth->generate_key(dh);
|
||||
}
|
||||
LCRYPTO_ALIAS(DH_generate_key);
|
||||
|
||||
int
|
||||
DH_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
|
||||
{
|
||||
return dh->meth->compute_key(key, pub_key, dh);
|
||||
}
|
||||
LCRYPTO_ALIAS(DH_compute_key);
|
||||
|
||||
static DH_METHOD dh_ossl = {
|
||||
.name = "OpenSSL DH Method",
|
||||
.generate_key = generate_key,
|
||||
.compute_key = compute_key,
|
||||
.bn_mod_exp = dh_bn_mod_exp,
|
||||
.init = dh_init,
|
||||
.finish = dh_finish,
|
||||
};
|
||||
|
||||
const DH_METHOD *
|
||||
DH_OpenSSL(void)
|
||||
{
|
||||
return &dh_ossl;
|
||||
}
|
||||
LCRYPTO_ALIAS(DH_OpenSSL);
|
||||
|
||||
static int
|
||||
generate_key(DH *dh)
|
||||
{
|
||||
int ok = 0;
|
||||
unsigned l;
|
||||
BN_CTX *ctx;
|
||||
BN_MONT_CTX *mont = NULL;
|
||||
BIGNUM *pub_key = NULL, *priv_key = NULL;
|
||||
|
||||
if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) {
|
||||
DHerror(DH_R_MODULUS_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ctx = BN_CTX_new();
|
||||
if (ctx == NULL)
|
||||
goto err;
|
||||
|
||||
if ((priv_key = dh->priv_key) == NULL) {
|
||||
if ((priv_key = BN_new()) == NULL)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((pub_key = dh->pub_key) == NULL) {
|
||||
if ((pub_key = BN_new()) == NULL)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (dh->flags & DH_FLAG_CACHE_MONT_P) {
|
||||
mont = BN_MONT_CTX_set_locked(&dh->method_mont_p,
|
||||
CRYPTO_LOCK_DH, dh->p, ctx);
|
||||
if (!mont)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (dh->priv_key == NULL) {
|
||||
if (dh->q) {
|
||||
if (!bn_rand_interval(priv_key, 2, dh->q))
|
||||
goto err;
|
||||
} else {
|
||||
/* secret exponent length */
|
||||
l = dh->length ? dh->length : BN_num_bits(dh->p) - 1;
|
||||
if (!BN_rand(priv_key, l, 0, 0))
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dh->meth->bn_mod_exp(dh, pub_key, dh->g, priv_key, dh->p, ctx,
|
||||
mont))
|
||||
goto err;
|
||||
|
||||
dh->pub_key = pub_key;
|
||||
dh->priv_key = priv_key;
|
||||
ok = 1;
|
||||
err:
|
||||
if (ok != 1)
|
||||
DHerror(ERR_R_BN_LIB);
|
||||
|
||||
if (dh->pub_key == NULL)
|
||||
BN_free(pub_key);
|
||||
if (dh->priv_key == NULL)
|
||||
BN_free(priv_key);
|
||||
BN_CTX_free(ctx);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int
|
||||
compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
|
||||
{
|
||||
BN_CTX *ctx = NULL;
|
||||
BN_MONT_CTX *mont = NULL;
|
||||
BIGNUM *tmp;
|
||||
int ret = -1;
|
||||
int check_result;
|
||||
|
||||
if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) {
|
||||
DHerror(DH_R_MODULUS_TOO_LARGE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ctx = BN_CTX_new();
|
||||
if (ctx == NULL)
|
||||
goto err;
|
||||
BN_CTX_start(ctx);
|
||||
if ((tmp = BN_CTX_get(ctx)) == NULL)
|
||||
goto err;
|
||||
|
||||
if (dh->priv_key == NULL) {
|
||||
DHerror(DH_R_NO_PRIVATE_VALUE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (dh->flags & DH_FLAG_CACHE_MONT_P) {
|
||||
mont = BN_MONT_CTX_set_locked(&dh->method_mont_p,
|
||||
CRYPTO_LOCK_DH, dh->p, ctx);
|
||||
|
||||
BN_set_flags(dh->priv_key, BN_FLG_CONSTTIME);
|
||||
|
||||
if (!mont)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!DH_check_pub_key(dh, pub_key, &check_result) || check_result) {
|
||||
DHerror(DH_R_INVALID_PUBKEY);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!dh->meth->bn_mod_exp(dh, tmp, pub_key, dh->priv_key, dh->p, ctx,
|
||||
mont)) {
|
||||
DHerror(ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = BN_bn2bin(tmp, key);
|
||||
err:
|
||||
if (ctx != NULL) {
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(ctx);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
dh_bn_mod_exp(const DH *dh, BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
|
||||
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
|
||||
{
|
||||
return BN_mod_exp_mont_ct(r, a, p, m, ctx, m_ctx);
|
||||
}
|
||||
|
||||
static int
|
||||
dh_init(DH *dh)
|
||||
{
|
||||
dh->flags |= DH_FLAG_CACHE_MONT_P;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
dh_finish(DH *dh)
|
||||
{
|
||||
BN_MONT_CTX_free(dh->method_mont_p);
|
||||
return 1;
|
||||
}
|
400
crypto/dh/dh_lib.c
Normal file
400
crypto/dh/dh_lib.c
Normal file
@@ -0,0 +1,400 @@
|
||||
/* $OpenBSD: dh_lib.c,v 1.41 2023/08/13 12:09:14 tb Exp $ */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <openssl/opensslconf.h>
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/dh.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#ifndef OPENSSL_NO_ENGINE
|
||||
#include <openssl/engine.h>
|
||||
#endif
|
||||
|
||||
#include "dh_local.h"
|
||||
|
||||
static const DH_METHOD *default_DH_method = NULL;
|
||||
|
||||
void
|
||||
DH_set_default_method(const DH_METHOD *meth)
|
||||
{
|
||||
default_DH_method = meth;
|
||||
}
|
||||
LCRYPTO_ALIAS(DH_set_default_method);
|
||||
|
||||
const DH_METHOD *
|
||||
DH_get_default_method(void)
|
||||
{
|
||||
if (!default_DH_method)
|
||||
default_DH_method = DH_OpenSSL();
|
||||
return default_DH_method;
|
||||
}
|
||||
LCRYPTO_ALIAS(DH_get_default_method);
|
||||
|
||||
int
|
||||
DH_set_method(DH *dh, const DH_METHOD *meth)
|
||||
{
|
||||
/*
|
||||
* 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);
|
||||
#ifndef OPENSSL_NO_ENGINE
|
||||
ENGINE_finish(dh->engine);
|
||||
dh->engine = NULL;
|
||||
#endif
|
||||
dh->meth = meth;
|
||||
if (meth->init)
|
||||
meth->init(dh);
|
||||
return 1;
|
||||
}
|
||||
LCRYPTO_ALIAS(DH_set_method);
|
||||
|
||||
DH *
|
||||
DH_new(void)
|
||||
{
|
||||
return DH_new_method(NULL);
|
||||
}
|
||||
LCRYPTO_ALIAS(DH_new);
|
||||
|
||||
DH *
|
||||
DH_new_method(ENGINE *engine)
|
||||
{
|
||||
DH *dh;
|
||||
|
||||
if ((dh = calloc(1, sizeof(*dh))) == NULL) {
|
||||
DHerror(ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
dh->meth = DH_get_default_method();
|
||||
dh->flags = dh->meth->flags & ~DH_FLAG_NON_FIPS_ALLOW;
|
||||
dh->references = 1;
|
||||
|
||||
#ifndef OPENSSL_NO_ENGINE
|
||||
if (engine != NULL) {
|
||||
if (!ENGINE_init(engine)) {
|
||||
DHerror(ERR_R_ENGINE_LIB);
|
||||
goto err;
|
||||
}
|
||||
dh->engine = engine;
|
||||
} else
|
||||
dh->engine = ENGINE_get_default_DH();
|
||||
if (dh->engine != NULL) {
|
||||
if ((dh->meth = ENGINE_get_DH(dh->engine)) == NULL) {
|
||||
DHerror(ERR_R_ENGINE_LIB);
|
||||
goto err;
|
||||
}
|
||||
dh->flags = dh->meth->flags & ~DH_FLAG_NON_FIPS_ALLOW;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_DH, dh, &dh->ex_data))
|
||||
goto err;
|
||||
if (dh->meth->init != NULL && !dh->meth->init(dh))
|
||||
goto err;
|
||||
|
||||
return dh;
|
||||
|
||||
err:
|
||||
DH_free(dh);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
LCRYPTO_ALIAS(DH_new_method);
|
||||
|
||||
void
|
||||
DH_free(DH *r)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (r == NULL)
|
||||
return;
|
||||
i = CRYPTO_add(&r->references, -1, CRYPTO_LOCK_DH);
|
||||
if (i > 0)
|
||||
return;
|
||||
|
||||
if (r->meth != NULL && r->meth->finish != NULL)
|
||||
r->meth->finish(r);
|
||||
#ifndef OPENSSL_NO_ENGINE
|
||||
ENGINE_finish(r->engine);
|
||||
#endif
|
||||
|
||||
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DH, r, &r->ex_data);
|
||||
|
||||
BN_free(r->p);
|
||||
BN_free(r->g);
|
||||
BN_free(r->q);
|
||||
BN_free(r->j);
|
||||
free(r->seed);
|
||||
BN_free(r->counter);
|
||||
BN_free(r->pub_key);
|
||||
BN_free(r->priv_key);
|
||||
free(r);
|
||||
}
|
||||
LCRYPTO_ALIAS(DH_free);
|
||||
|
||||
int
|
||||
DH_up_ref(DH *r)
|
||||
{
|
||||
int i = CRYPTO_add(&r->references, 1, CRYPTO_LOCK_DH);
|
||||
|
||||
return i > 1 ? 1 : 0;
|
||||
}
|
||||
LCRYPTO_ALIAS(DH_up_ref);
|
||||
|
||||
int
|
||||
DH_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
|
||||
CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
|
||||
{
|
||||
return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_DH, argl, argp, new_func,
|
||||
dup_func, free_func);
|
||||
}
|
||||
LCRYPTO_ALIAS(DH_get_ex_new_index);
|
||||
|
||||
int
|
||||
DH_set_ex_data(DH *d, int idx, void *arg)
|
||||
{
|
||||
return CRYPTO_set_ex_data(&d->ex_data, idx, arg);
|
||||
}
|
||||
LCRYPTO_ALIAS(DH_set_ex_data);
|
||||
|
||||
void *
|
||||
DH_get_ex_data(DH *d, int idx)
|
||||
{
|
||||
return CRYPTO_get_ex_data(&d->ex_data, idx);
|
||||
}
|
||||
LCRYPTO_ALIAS(DH_get_ex_data);
|
||||
|
||||
int
|
||||
DH_size(const DH *dh)
|
||||
{
|
||||
return BN_num_bytes(dh->p);
|
||||
}
|
||||
LCRYPTO_ALIAS(DH_size);
|
||||
|
||||
int
|
||||
DH_bits(const DH *dh)
|
||||
{
|
||||
return BN_num_bits(dh->p);
|
||||
}
|
||||
LCRYPTO_ALIAS(DH_bits);
|
||||
|
||||
int
|
||||
DH_security_bits(const DH *dh)
|
||||
{
|
||||
int N = -1;
|
||||
|
||||
if (dh->q != NULL)
|
||||
N = BN_num_bits(dh->q);
|
||||
else if (dh->length > 0)
|
||||
N = dh->length;
|
||||
|
||||
return BN_security_bits(BN_num_bits(dh->p), N);
|
||||
}
|
||||
LCRYPTO_ALIAS(DH_security_bits);
|
||||
|
||||
ENGINE *
|
||||
DH_get0_engine(DH *dh)
|
||||
{
|
||||
return dh->engine;
|
||||
}
|
||||
LCRYPTO_ALIAS(DH_get0_engine);
|
||||
|
||||
void
|
||||
DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
|
||||
{
|
||||
if (p != NULL)
|
||||
*p = dh->p;
|
||||
if (q != NULL)
|
||||
*q = dh->q;
|
||||
if (g != NULL)
|
||||
*g = dh->g;
|
||||
}
|
||||
LCRYPTO_ALIAS(DH_get0_pqg);
|
||||
|
||||
int
|
||||
DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g)
|
||||
{
|
||||
if ((dh->p == NULL && p == NULL) || (dh->g == NULL && g == NULL))
|
||||
return 0;
|
||||
|
||||
if (p != NULL) {
|
||||
BN_free(dh->p);
|
||||
dh->p = p;
|
||||
}
|
||||
if (q != NULL) {
|
||||
BN_free(dh->q);
|
||||
dh->q = q;
|
||||
dh->length = BN_num_bits(dh->q);
|
||||
}
|
||||
if (g != NULL) {
|
||||
BN_free(dh->g);
|
||||
dh->g = g;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
LCRYPTO_ALIAS(DH_set0_pqg);
|
||||
|
||||
void
|
||||
DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key)
|
||||
{
|
||||
if (pub_key != NULL)
|
||||
*pub_key = dh->pub_key;
|
||||
if (priv_key != NULL)
|
||||
*priv_key = dh->priv_key;
|
||||
}
|
||||
LCRYPTO_ALIAS(DH_get0_key);
|
||||
|
||||
int
|
||||
DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key)
|
||||
{
|
||||
if (pub_key != NULL) {
|
||||
BN_free(dh->pub_key);
|
||||
dh->pub_key = pub_key;
|
||||
}
|
||||
if (priv_key != NULL) {
|
||||
BN_free(dh->priv_key);
|
||||
dh->priv_key = priv_key;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
LCRYPTO_ALIAS(DH_set0_key);
|
||||
|
||||
const BIGNUM *
|
||||
DH_get0_p(const DH *dh)
|
||||
{
|
||||
return dh->p;
|
||||
}
|
||||
LCRYPTO_ALIAS(DH_get0_p);
|
||||
|
||||
const BIGNUM *
|
||||
DH_get0_q(const DH *dh)
|
||||
{
|
||||
return dh->q;
|
||||
}
|
||||
LCRYPTO_ALIAS(DH_get0_q);
|
||||
|
||||
const BIGNUM *
|
||||
DH_get0_g(const DH *dh)
|
||||
{
|
||||
return dh->g;
|
||||
}
|
||||
LCRYPTO_ALIAS(DH_get0_g);
|
||||
|
||||
const BIGNUM *
|
||||
DH_get0_priv_key(const DH *dh)
|
||||
{
|
||||
return dh->priv_key;
|
||||
}
|
||||
LCRYPTO_ALIAS(DH_get0_priv_key);
|
||||
|
||||
const BIGNUM *
|
||||
DH_get0_pub_key(const DH *dh)
|
||||
{
|
||||
return dh->pub_key;
|
||||
}
|
||||
LCRYPTO_ALIAS(DH_get0_pub_key);
|
||||
|
||||
void
|
||||
DH_clear_flags(DH *dh, int flags)
|
||||
{
|
||||
dh->flags &= ~flags;
|
||||
}
|
||||
LCRYPTO_ALIAS(DH_clear_flags);
|
||||
|
||||
int
|
||||
DH_test_flags(const DH *dh, int flags)
|
||||
{
|
||||
return dh->flags & flags;
|
||||
}
|
||||
LCRYPTO_ALIAS(DH_test_flags);
|
||||
|
||||
void
|
||||
DH_set_flags(DH *dh, int flags)
|
||||
{
|
||||
dh->flags |= flags;
|
||||
}
|
||||
LCRYPTO_ALIAS(DH_set_flags);
|
||||
|
||||
long
|
||||
DH_get_length(const DH *dh)
|
||||
{
|
||||
return dh->length;
|
||||
}
|
||||
LCRYPTO_ALIAS(DH_get_length);
|
||||
|
||||
int
|
||||
DH_set_length(DH *dh, long length)
|
||||
{
|
||||
if (length < 0 || length > INT_MAX)
|
||||
return 0;
|
||||
|
||||
dh->length = length;
|
||||
return 1;
|
||||
}
|
||||
LCRYPTO_ALIAS(DH_set_length);
|
117
crypto/dh/dh_local.h
Normal file
117
crypto/dh/dh_local.h
Normal file
@@ -0,0 +1,117 @@
|
||||
/* $OpenBSD: dh_local.h,v 1.3 2022/01/14 08:25:44 tb Exp $ */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#ifndef HEADER_DH_LOCAL_H
|
||||
#define HEADER_DH_LOCAL_H
|
||||
|
||||
__BEGIN_HIDDEN_DECLS
|
||||
|
||||
struct dh_method {
|
||||
const char *name;
|
||||
/* Methods here */
|
||||
int (*generate_key)(DH *dh);
|
||||
int (*compute_key)(unsigned char *key,const BIGNUM *pub_key,DH *dh);
|
||||
int (*bn_mod_exp)(const DH *dh, BIGNUM *r, const BIGNUM *a,
|
||||
const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
|
||||
int (*init)(DH *dh);
|
||||
int (*finish)(DH *dh);
|
||||
int flags;
|
||||
char *app_data;
|
||||
/* If this is non-NULL, it will be used to generate parameters */
|
||||
int (*generate_params)(DH *dh, int prime_len, int generator,
|
||||
BN_GENCB *cb);
|
||||
};
|
||||
|
||||
struct dh_st {
|
||||
/* This first argument is used to pick up errors when
|
||||
* a DH is passed instead of a EVP_PKEY */
|
||||
int pad;
|
||||
int version;
|
||||
BIGNUM *p;
|
||||
BIGNUM *g;
|
||||
long length; /* optional */
|
||||
BIGNUM *pub_key; /* g^x */
|
||||
BIGNUM *priv_key; /* x */
|
||||
|
||||
int flags;
|
||||
BN_MONT_CTX *method_mont_p;
|
||||
/* Place holders if we want to do X9.42 DH */
|
||||
BIGNUM *q;
|
||||
BIGNUM *j;
|
||||
unsigned char *seed;
|
||||
int seedlen;
|
||||
BIGNUM *counter;
|
||||
|
||||
int references;
|
||||
CRYPTO_EX_DATA ex_data;
|
||||
const DH_METHOD *meth;
|
||||
ENGINE *engine;
|
||||
};
|
||||
|
||||
/*
|
||||
* Public API in OpenSSL that we only want to use internally.
|
||||
*/
|
||||
|
||||
int DH_check_params_ex(const DH *dh);
|
||||
int DH_check_params(const DH *dh, int *flags);
|
||||
int DH_check_ex(const DH *dh);
|
||||
int DH_check_pub_key_ex(const DH *dh, const BIGNUM *pub_key);
|
||||
|
||||
__END_HIDDEN_DECLS
|
||||
|
||||
#endif /* !HEADER_DH_LOCAL_H */
|
266
crypto/dh/dh_pmeth.c
Normal file
266
crypto/dh/dh_pmeth.c
Normal file
@@ -0,0 +1,266 @@
|
||||
/* $OpenBSD: dh_pmeth.c,v 1.13 2022/11/26 16:08:51 tb Exp $ */
|
||||
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
|
||||
* project 2006.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2006 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* licensing@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/dh.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/x509.h>
|
||||
|
||||
#include "bn_local.h"
|
||||
#include "dh_local.h"
|
||||
#include "evp_local.h"
|
||||
|
||||
/* DH pkey context structure */
|
||||
|
||||
typedef struct {
|
||||
/* Parameter gen parameters */
|
||||
int prime_len;
|
||||
int generator;
|
||||
int use_dsa;
|
||||
/* Keygen callback info */
|
||||
int gentmp[2];
|
||||
/* message digest */
|
||||
} DH_PKEY_CTX;
|
||||
|
||||
static int
|
||||
pkey_dh_init(EVP_PKEY_CTX *ctx)
|
||||
{
|
||||
DH_PKEY_CTX *dctx;
|
||||
|
||||
dctx = malloc(sizeof(DH_PKEY_CTX));
|
||||
if (!dctx)
|
||||
return 0;
|
||||
dctx->prime_len = 1024;
|
||||
dctx->generator = 2;
|
||||
dctx->use_dsa = 0;
|
||||
|
||||
ctx->data = dctx;
|
||||
ctx->keygen_info = dctx->gentmp;
|
||||
ctx->keygen_info_count = 2;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
pkey_dh_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
|
||||
{
|
||||
DH_PKEY_CTX *dctx, *sctx;
|
||||
|
||||
if (!pkey_dh_init(dst))
|
||||
return 0;
|
||||
sctx = src->data;
|
||||
dctx = dst->data;
|
||||
dctx->prime_len = sctx->prime_len;
|
||||
dctx->generator = sctx->generator;
|
||||
dctx->use_dsa = sctx->use_dsa;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
pkey_dh_cleanup(EVP_PKEY_CTX *ctx)
|
||||
{
|
||||
DH_PKEY_CTX *dctx = ctx->data;
|
||||
|
||||
free(dctx);
|
||||
}
|
||||
|
||||
static int
|
||||
pkey_dh_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
|
||||
{
|
||||
DH_PKEY_CTX *dctx = ctx->data;
|
||||
|
||||
switch (type) {
|
||||
case EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN:
|
||||
if (p1 < 256)
|
||||
return -2;
|
||||
dctx->prime_len = p1;
|
||||
return 1;
|
||||
|
||||
case EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR:
|
||||
dctx->generator = p1;
|
||||
return 1;
|
||||
|
||||
case EVP_PKEY_CTRL_PEER_KEY:
|
||||
/* Default behaviour is OK */
|
||||
return 1;
|
||||
|
||||
default:
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
pkey_dh_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, const char *value)
|
||||
{
|
||||
long lval;
|
||||
char *ep;
|
||||
int len;
|
||||
|
||||
if (!strcmp(type, "dh_paramgen_prime_len")) {
|
||||
errno = 0;
|
||||
lval = strtol(value, &ep, 10);
|
||||
if (value[0] == '\0' || *ep != '\0')
|
||||
goto not_a_number;
|
||||
if ((errno == ERANGE &&
|
||||
(lval == LONG_MAX || lval == LONG_MIN)) ||
|
||||
(lval > INT_MAX || lval < INT_MIN))
|
||||
goto out_of_range;
|
||||
len = lval;
|
||||
return EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, len);
|
||||
} else if (!strcmp(type, "dh_paramgen_generator")) {
|
||||
errno = 0;
|
||||
lval = strtol(value, &ep, 10);
|
||||
if (value[0] == '\0' || *ep != '\0')
|
||||
goto not_a_number;
|
||||
if ((errno == ERANGE &&
|
||||
(lval == LONG_MAX || lval == LONG_MIN)) ||
|
||||
(lval > INT_MAX || lval < INT_MIN))
|
||||
goto out_of_range;
|
||||
len = lval;
|
||||
return EVP_PKEY_CTX_set_dh_paramgen_generator(ctx, len);
|
||||
}
|
||||
|
||||
not_a_number:
|
||||
out_of_range:
|
||||
return -2;
|
||||
}
|
||||
|
||||
static int
|
||||
pkey_dh_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
|
||||
{
|
||||
DH *dh = NULL;
|
||||
DH_PKEY_CTX *dctx = ctx->data;
|
||||
BN_GENCB *pcb, cb;
|
||||
int ret;
|
||||
|
||||
if (ctx->pkey_gencb) {
|
||||
pcb = &cb;
|
||||
evp_pkey_set_cb_translate(pcb, ctx);
|
||||
} else
|
||||
pcb = NULL;
|
||||
dh = DH_new();
|
||||
if (!dh)
|
||||
return 0;
|
||||
ret = DH_generate_parameters_ex(dh, dctx->prime_len, dctx->generator,
|
||||
pcb);
|
||||
if (ret)
|
||||
EVP_PKEY_assign_DH(pkey, dh);
|
||||
else
|
||||
DH_free(dh);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
pkey_dh_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
|
||||
{
|
||||
DH *dh = NULL;
|
||||
|
||||
if (ctx->pkey == NULL) {
|
||||
DHerror(DH_R_NO_PARAMETERS_SET);
|
||||
return 0;
|
||||
}
|
||||
dh = DH_new();
|
||||
if (!dh)
|
||||
return 0;
|
||||
EVP_PKEY_assign_DH(pkey, dh);
|
||||
/* Note: if error return, pkey is freed by parent routine */
|
||||
if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey))
|
||||
return 0;
|
||||
return DH_generate_key(pkey->pkey.dh);
|
||||
}
|
||||
|
||||
static int
|
||||
pkey_dh_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!ctx->pkey || !ctx->peerkey) {
|
||||
DHerror(DH_R_KEYS_NOT_SET);
|
||||
return 0;
|
||||
}
|
||||
ret = DH_compute_key(key, ctx->peerkey->pkey.dh->pub_key,
|
||||
ctx->pkey->pkey.dh);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
*keylen = ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const EVP_PKEY_METHOD dh_pkey_meth = {
|
||||
.pkey_id = EVP_PKEY_DH,
|
||||
.flags = EVP_PKEY_FLAG_AUTOARGLEN,
|
||||
|
||||
.init = pkey_dh_init,
|
||||
.copy = pkey_dh_copy,
|
||||
.cleanup = pkey_dh_cleanup,
|
||||
|
||||
.paramgen = pkey_dh_paramgen,
|
||||
|
||||
.keygen = pkey_dh_keygen,
|
||||
|
||||
.derive = pkey_dh_derive,
|
||||
|
||||
.ctrl = pkey_dh_ctrl,
|
||||
.ctrl_str = pkey_dh_ctrl_str
|
||||
};
|
Reference in New Issue
Block a user