]> git.ipfire.org Git - thirdparty/openssl.git/blobdiff - crypto/dh/dh_ameth.c
Replace OSSL_PARAM_BLD_free_params() with OSSL_PARAM_free().
[thirdparty/openssl.git] / crypto / dh / dh_ameth.c
index 46a2fdd881b7f864cdca6ec9cb963106a2cb050d..907a867ecac2174c89c28ed1fd9cbceab855a22b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -19,7 +19,6 @@
 #include <openssl/bn.h>
 #include <openssl/core_names.h>
 #include <openssl/param_build.h>
-#include <openssl/cms.h>
 #include "internal/ffc.h"
 #include "internal/cryptlib.h"
 #include "crypto/asn1.h"
@@ -36,23 +35,19 @@ static DH *d2i_dhp(const EVP_PKEY *pkey, const unsigned char **pp,
                    long length)
 {
     DH *dh = NULL;
-    int is_dhx = (pkey->ameth == &dhx_asn1_meth);
+    int is_dhx = (pkey->ameth == &ossl_dhx_asn1_meth);
 
     if (is_dhx)
         dh = d2i_DHxparams(NULL, pp, length);
     else
         dh = d2i_DHparams(NULL, pp, length);
 
-    if (dh != NULL) {
-        DH_clear_flags(dh, DH_FLAG_TYPE_MASK);
-        DH_set_flags(dh, is_dhx ? DH_FLAG_TYPE_DHX : DH_FLAG_TYPE_DH);
-    }
     return dh;
 }
 
 static int i2d_dhp(const EVP_PKEY *pkey, const DH *a, unsigned char **pp)
 {
-    if (pkey->ameth == &dhx_asn1_meth)
+    if (pkey->ameth == &ossl_dhx_asn1_meth)
         return i2d_DHxparams(a, pp);
     return i2d_DHparams(a, pp);
 }
@@ -79,7 +74,7 @@ static int dh_pub_decode(EVP_PKEY *pkey, const X509_PUBKEY *pubkey)
     X509_ALGOR_get0(NULL, &ptype, &pval, palg);
 
     if (ptype != V_ASN1_SEQUENCE) {
-        DHerr(DH_F_DH_PUB_DECODE, DH_R_PARAMETER_ENCODING_ERROR);
+        ERR_raise(ERR_LIB_DH, DH_R_PARAMETER_ENCODING_ERROR);
         goto err;
     }
 
@@ -88,18 +83,18 @@ static int dh_pub_decode(EVP_PKEY *pkey, const X509_PUBKEY *pubkey)
     pmlen = pstr->length;
 
     if ((dh = d2i_dhp(pkey, &pm, pmlen)) == NULL) {
-        DHerr(DH_F_DH_PUB_DECODE, DH_R_DECODE_ERROR);
+        ERR_raise(ERR_LIB_DH, DH_R_DECODE_ERROR);
         goto err;
     }
 
     if ((public_key = d2i_ASN1_INTEGER(NULL, &p, pklen)) == NULL) {
-        DHerr(DH_F_DH_PUB_DECODE, DH_R_DECODE_ERROR);
+        ERR_raise(ERR_LIB_DH, DH_R_DECODE_ERROR);
         goto err;
     }
 
     /* We have parameters now set public key */
     if ((dh->pub_key = ASN1_INTEGER_to_BN(public_key, NULL)) == NULL) {
-        DHerr(DH_F_DH_PUB_DECODE, DH_R_BN_DECODE_ERROR);
+        ERR_raise(ERR_LIB_DH, DH_R_BN_DECODE_ERROR);
         goto err;
     }
 
@@ -126,12 +121,12 @@ static int dh_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
 
     str = ASN1_STRING_new();
     if (str == NULL) {
-        DHerr(DH_F_DH_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
         goto err;
     }
     str->length = i2d_dhp(pkey, dh, &str->data);
     if (str->length <= 0) {
-        DHerr(DH_F_DH_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
         goto err;
     }
     ptype = V_ASN1_SEQUENCE;
@@ -145,7 +140,7 @@ static int dh_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
     ASN1_INTEGER_free(pub_key);
 
     if (penclen <= 0) {
-        DHerr(DH_F_DH_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
         goto err;
     }
 
@@ -168,53 +163,15 @@ static int dh_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
 
 static int dh_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8)
 {
-    const unsigned char *p, *pm;
-    int pklen, pmlen;
-    int ptype;
-    const void *pval;
-    const ASN1_STRING *pstr;
-    const X509_ALGOR *palg;
-    ASN1_INTEGER *privkey = NULL;
-    DH *dh = NULL;
-
-    if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8))
-        return 0;
+    int ret = 0;
+    DH *dh = ossl_dh_key_from_pkcs8(p8, NULL, NULL);
 
-    X509_ALGOR_get0(NULL, &ptype, &pval, palg);
-
-    if (ptype != V_ASN1_SEQUENCE)
-        goto decerr;
-    if ((privkey = d2i_ASN1_INTEGER(NULL, &p, pklen)) == NULL)
-        goto decerr;
-
-    pstr = pval;
-    pm = pstr->data;
-    pmlen = pstr->length;
-    if ((dh = d2i_dhp(pkey, &pm, pmlen)) == NULL)
-        goto decerr;
-
-    /* We have parameters now set private key */
-    if ((dh->priv_key = BN_secure_new()) == NULL
-        || !ASN1_INTEGER_to_BN(privkey, dh->priv_key)) {
-        DHerr(DH_F_DH_PRIV_DECODE, DH_R_BN_ERROR);
-        goto dherr;
+    if (dh != NULL) {
+        ret = 1;
+        EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, dh);
     }
-    /* Calculate public key, increments dirty_cnt */
-    if (!DH_generate_key(dh))
-        goto dherr;
-
-    EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, dh);
 
-    ASN1_STRING_clear_free(privkey);
-
-    return 1;
-
- decerr:
-    DHerr(DH_F_DH_PRIV_DECODE, EVP_R_DECODE_ERROR);
- dherr:
-    DH_free(dh);
-    ASN1_STRING_clear_free(privkey);
-    return 0;
+    return ret;
 }
 
 static int dh_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
@@ -227,13 +184,13 @@ static int dh_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
     params = ASN1_STRING_new();
 
     if (params == NULL) {
-        DHerr(DH_F_DH_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
         goto err;
     }
 
     params->length = i2d_dhp(pkey, pkey->pkey.dh, &params->data);
     if (params->length <= 0) {
-        DHerr(DH_F_DH_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
         goto err;
     }
     params->type = V_ASN1_SEQUENCE;
@@ -242,7 +199,7 @@ static int dh_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
     prkey = BN_to_ASN1_INTEGER(pkey->pkey.dh->priv_key, NULL);
 
     if (prkey == NULL) {
-        DHerr(DH_F_DH_PRIV_ENCODE, DH_R_BN_ERROR);
+        ERR_raise(ERR_LIB_DH, DH_R_BN_ERROR);
         goto err;
     }
 
@@ -333,7 +290,7 @@ static int do_dh_print(BIO *bp, const DH *x, int indent, int ptype)
     return 1;
 
  err:
-    DHerr(DH_F_DO_DH_PRINT, reason);
+    ERR_raise(ERR_LIB_DH, reason);
     return 0;
 }
 
@@ -355,7 +312,7 @@ static int dh_security_bits(const EVP_PKEY *pkey)
 static int dh_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
 {
     return ossl_ffc_params_cmp(&a->pkey.dh->params, &a->pkey.dh->params,
-                               a->ameth != &dhx_asn1_meth);
+                               a->ameth != &ossl_dhx_asn1_meth);
 }
 
 static int int_dh_param_copy(DH *to, const DH *from, int is_x942)
@@ -391,7 +348,7 @@ static int dh_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
             return 0;
     }
     return int_dh_param_copy(to->pkey.dh, from->pkey.dh,
-                             from->ameth == &dhx_asn1_meth);
+                             from->ameth == &ossl_dhx_asn1_meth);
 }
 
 static int dh_missing_parameters(const EVP_PKEY *a)
@@ -438,9 +395,12 @@ static int dh_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
 {
     switch (op) {
     case ASN1_PKEY_CTRL_SET1_TLS_ENCPT:
-        return dh_buf2key(EVP_PKEY_get0_DH(pkey), arg2, arg1);
+        /* We should only be here if we have a legacy key */
+        if (!ossl_assert(evp_pkey_is_legacy(pkey)))
+            return 0;
+        return ossl_dh_buf2key(evp_pkey_get0_DH_int(pkey), arg2, arg1);
     case ASN1_PKEY_CTRL_GET1_TLS_ENCPT:
-        return dh_key2buf(EVP_PKEY_get0_DH(pkey), arg2, 0, 1);
+        return ossl_dh_key2buf(EVP_PKEY_get0_DH(pkey), arg2, 0, 1);
     default:
         return -2;
     }
@@ -449,11 +409,6 @@ static int dh_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
 static int dhx_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
 {
     switch (op) {
-#ifndef OPENSSL_NO_CMS
-    case ASN1_PKEY_CTRL_CMS_RI_TYPE:
-        *(int *)arg2 = CMS_RECIPINFO_AGREE;
-        return 1;
-#endif
     default:
         return -2;
     }
@@ -465,7 +420,7 @@ static int dh_pkey_public_check(const EVP_PKEY *pkey)
     DH *dh = pkey->pkey.dh;
 
     if (dh->pub_key == NULL) {
-        DHerr(DH_F_DH_PKEY_PUBLIC_CHECK, DH_R_MISSING_PUBKEY);
+        ERR_raise(ERR_LIB_DH, DH_R_MISSING_PUBKEY);
         return 0;
     }
 
@@ -485,12 +440,13 @@ static size_t dh_pkey_dirty_cnt(const EVP_PKEY *pkey)
 }
 
 static int dh_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
-                             EVP_KEYMGMT *to_keymgmt, OPENSSL_CTX *libctx,
+                             EVP_KEYMGMT *to_keymgmt, OSSL_LIB_CTX *libctx,
                              const char *propq)
 {
     DH *dh = from->pkey.dh;
     OSSL_PARAM_BLD *tmpl;
     const BIGNUM *p = DH_get0_p(dh), *g = DH_get0_g(dh), *q = DH_get0_q(dh);
+    long l = DH_get_length(dh);
     const BIGNUM *pub_key = DH_get0_pub_key(dh);
     const BIGNUM *priv_key = DH_get0_priv_key(dh);
     OSSL_PARAM *params = NULL;
@@ -501,7 +457,7 @@ static int dh_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
      * If the DH method is foreign, then we can't be sure of anything, and
      * can therefore not export or pretend to export.
      */
-    if (dh_get_method(dh) != DH_OpenSSL())
+    if (ossl_dh_get_method(dh) != DH_OpenSSL())
         return 0;
 
     if (p == NULL || g == NULL)
@@ -518,6 +474,11 @@ static int dh_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
             goto err;
     }
     selection |= OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS;
+    if (l > 0) {
+        if (!OSSL_PARAM_BLD_push_long(tmpl, OSSL_PKEY_PARAM_DH_PRIV_LEN, l))
+            goto err;
+        selection |= OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS;
+    }
     if (pub_key != NULL) {
         if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_PUB_KEY, pub_key))
             goto err;
@@ -536,7 +497,7 @@ static int dh_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
     /* We export, the provider imports */
     rv = evp_keymgmt_import(to_keymgmt, to_keydata, selection, params);
 
-    OSSL_PARAM_BLD_free_params(params);
+    OSSL_PARAM_free(params);
 err:
     OSSL_PARAM_BLD_free(tmpl);
     return rv;
@@ -547,7 +508,7 @@ static int dh_pkey_import_from_type(const OSSL_PARAM params[], void *vpctx,
 {
     EVP_PKEY_CTX *pctx = vpctx;
     EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pctx);
-    DH *dh = dh_new_ex(pctx->libctx);
+    DH *dh = ossl_dh_new_ex(pctx->libctx);
 
     if (dh == NULL) {
         ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
@@ -556,8 +517,8 @@ static int dh_pkey_import_from_type(const OSSL_PARAM params[], void *vpctx,
     DH_clear_flags(dh, DH_FLAG_TYPE_MASK);
     DH_set_flags(dh, type == EVP_PKEY_DH ? DH_FLAG_TYPE_DH : DH_FLAG_TYPE_DHX);
 
-    if (!dh_ffc_params_fromdata(dh, params)
-        || !dh_key_fromdata(dh, params)
+    if (!ossl_dh_params_fromdata(dh, params)
+        || !ossl_dh_key_fromdata(dh, params)
         || !EVP_PKEY_assign(pkey, type, dh)) {
         DH_free(dh);
         return 0;
@@ -575,7 +536,65 @@ static int dhx_pkey_import_from(const OSSL_PARAM params[], void *vpctx)
     return dh_pkey_import_from_type(params, vpctx, EVP_PKEY_DHX);
 }
 
-const EVP_PKEY_ASN1_METHOD dh_asn1_meth = {
+static ossl_inline int dh_bn_dup_check(BIGNUM **out, const BIGNUM *f)
+{
+    if (f != NULL && (*out = BN_dup(f)) == NULL)
+        return 0;
+    return 1;
+}
+
+static DH *dh_dup(const DH *dh)
+{
+    DH *dupkey = NULL;
+
+    /* Do not try to duplicate foreign DH keys */
+    if (ossl_dh_get_method(dh) != DH_OpenSSL())
+        return NULL;
+
+    if ((dupkey = ossl_dh_new_ex(dh->libctx)) == NULL)
+        return NULL;
+
+    dupkey->length = DH_get_length(dh);
+    if (!ossl_ffc_params_copy(&dupkey->params, &dh->params))
+        goto err;
+
+    dupkey->flags = dh->flags;
+
+    if (!dh_bn_dup_check(&dupkey->pub_key, dh->pub_key))
+        goto err;
+    if (!dh_bn_dup_check(&dupkey->priv_key, dh->priv_key))
+        goto err;
+
+    if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_DH,
+                            &dupkey->ex_data, &dh->ex_data))
+        goto err;
+
+    return dupkey;
+
+ err:
+    DH_free(dupkey);
+    return NULL;
+}
+
+static int dh_pkey_copy(EVP_PKEY *to, EVP_PKEY *from)
+{
+    DH *dh = from->pkey.dh;
+    DH *dupkey = NULL;
+    int ret;
+
+    if (dh != NULL) {
+        dupkey = dh_dup(dh);
+        if (dupkey == NULL)
+            return 0;
+    }
+
+    ret = EVP_PKEY_assign(to, from->type, dupkey);
+    if (!ret)
+        DH_free(dupkey);
+    return ret;
+}
+
+const EVP_PKEY_ASN1_METHOD ossl_dh_asn1_meth = {
     EVP_PKEY_DH,
     EVP_PKEY_DH,
     0,
@@ -618,9 +637,10 @@ const EVP_PKEY_ASN1_METHOD dh_asn1_meth = {
     dh_pkey_dirty_cnt,
     dh_pkey_export_to,
     dh_pkey_import_from,
+    dh_pkey_copy
 };
 
-const EVP_PKEY_ASN1_METHOD dhx_asn1_meth = {
+const EVP_PKEY_ASN1_METHOD ossl_dhx_asn1_meth = {
     EVP_PKEY_DHX,
     EVP_PKEY_DHX,
     0,
@@ -661,4 +681,5 @@ const EVP_PKEY_ASN1_METHOD dhx_asn1_meth = {
     dh_pkey_dirty_cnt,
     dh_pkey_export_to,
     dhx_pkey_import_from,
+    dh_pkey_copy
 };