]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
x509: enable importing secret keys for X448 and X25519.
authorDaniel Kahn Gillmor <dkg@fifthhorseman.net>
Sat, 8 May 2021 00:23:41 +0000 (20:23 -0400)
committerDaniel Kahn Gillmor <dkg@fifthhorseman.net>
Fri, 17 Sep 2021 20:33:07 +0000 (16:33 -0400)
_decode_pkcs8_modern_ecdh_key is virtually the same as
_decode_pkcs8_eddsa_key.  Another implementation would be
to collapse these two functions into one, since their structure
is identical.

Signed-off-by: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
lib/x509/privkey_pkcs8.c

index 3c7c9f8eee629a2922e729788d0b298ad5300bc5..4aa89933074422ba9e9623f2b4319cb63a923164 100644 (file)
@@ -1138,6 +1138,56 @@ _decode_pkcs8_eddsa_key(asn1_node pkcs8_asn, gnutls_x509_privkey_t pkey, const c
        }
 }
 
+static int
+_decode_pkcs8_modern_ecdh_key(ASN1_TYPE pkcs8_asn, gnutls_x509_privkey_t pkey, const char *oid)
+{
+       int ret;
+       gnutls_datum_t tmp;
+       gnutls_ecc_curve_t curve = GNUTLS_ECC_CURVE_INVALID;
+       const gnutls_ecc_curve_entry_st *ce;
+
+       gnutls_pk_params_init(&pkey->params);
+
+       curve = gnutls_oid_to_ecc_curve(oid);
+       if (curve == GNUTLS_ECC_CURVE_INVALID) {
+               _gnutls_debug_log("PKCS#8: unknown curve OID %s\n", oid);
+               return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);
+       }
+
+       ce = _gnutls_ecc_curve_get_params(curve);
+       if (_curve_is_modern_ecdh(ce)) {
+               ret = _gnutls_x509_read_string(pkcs8_asn, "privateKey", &tmp, ASN1_ETYPE_OCTET_STRING, 1);
+               if (ret < 0) {
+                       gnutls_assert();
+                       return gnutls_assert_val(ret);
+               }
+
+               if (tmp.size != ce->size) {
+                       gnutls_free(tmp.data);
+                       return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
+               }
+               gnutls_free(pkey->params.raw_priv.data);
+               switch (curve) {
+               case GNUTLS_ECC_CURVE_X25519:
+                       pkey->params.algo = GNUTLS_PK_ECDH_X25519;
+                       break;
+               case GNUTLS_ECC_CURVE_X448:
+                       pkey->params.algo = GNUTLS_PK_ECDH_X448;
+                       break;
+               default:
+                       return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+               }
+               pkey->params.raw_priv.data = tmp.data;
+               pkey->params.raw_priv.size = tmp.size;
+               pkey->params.curve = curve;
+
+               tmp.data = NULL;
+               return 0;
+       } else {
+               return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);
+       }
+}
+
 /* Converts a GOST key to
  * an internal structure (gnutls_private_key)
  */
@@ -1463,6 +1513,10 @@ decode_private_key_info(const gnutls_datum_t * der,
                case GNUTLS_PK_EDDSA_ED448:
                        result = _decode_pkcs8_eddsa_key(pkcs8_asn, pkey, oid);
                        break;
+               case GNUTLS_PK_ECDH_X25519:
+               case GNUTLS_PK_ECDH_X448:
+                       result = _decode_pkcs8_modern_ecdh_key(pkcs8_asn, pkey, oid);
+                       break;
                case GNUTLS_PK_GOST_01:
                case GNUTLS_PK_GOST_12_256:
                case GNUTLS_PK_GOST_12_512: