summaryrefslogtreecommitdiff
path: root/lib/x509
diff options
context:
space:
mode:
Diffstat (limited to 'lib/x509')
-rw-r--r--lib/x509/common.c3
-rw-r--r--lib/x509/common.h3
-rw-r--r--lib/x509/key_decode.c22
-rw-r--r--lib/x509/key_encode.c39
-rw-r--r--lib/x509/output.c2
-rw-r--r--lib/x509/privkey_pkcs8.c56
6 files changed, 123 insertions, 2 deletions
diff --git a/lib/x509/common.c b/lib/x509/common.c
index c156bd96a9..94d206ff75 100644
--- a/lib/x509/common.c
+++ b/lib/x509/common.c
@@ -630,7 +630,8 @@ _gnutls_x509_decode_string(unsigned int etype,
if (td.data == NULL)
return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
- memcpy(td.data, str, str_size);
+ if (str_size > 0)
+ memcpy(td.data, str, str_size);
td.data[str_size] = 0;
if (allow_ber)
diff --git a/lib/x509/common.h b/lib/x509/common.h
index 4690d68825..c1df15980f 100644
--- a/lib/x509/common.h
+++ b/lib/x509/common.h
@@ -97,6 +97,9 @@
#define SIG_RSA_SHA3_384_OID "2.16.840.1.101.3.4.3.15"
#define SIG_RSA_SHA3_512_OID "2.16.840.1.101.3.4.3.16"
+#define ECDH_X25519_OID "1.3.101.110"
+#define ECDH_X448_OID "1.3.101.111"
+
#define SIG_EDDSA_SHA512_OID "1.3.101.112"
#define SIG_ED448_OID "1.3.101.113"
diff --git a/lib/x509/key_decode.c b/lib/x509/key_decode.c
index c7e69d8e1f..44e4297db0 100644
--- a/lib/x509/key_decode.c
+++ b/lib/x509/key_decode.c
@@ -41,6 +41,9 @@ static int _gnutls_x509_read_ecc_pubkey(uint8_t * der, int dersize,
static int _gnutls_x509_read_eddsa_pubkey(gnutls_ecc_curve_t curve,
uint8_t * der, int dersize,
gnutls_pk_params_st * params);
+static int _gnutls_x509_read_ecdh_pubkey(gnutls_ecc_curve_t curve,
+ uint8_t * der, int dersize,
+ gnutls_pk_params_st * params);
static int _gnutls_x509_read_gost_pubkey(uint8_t * der, int dersize,
gnutls_pk_params_st * params);
@@ -125,6 +128,17 @@ int _gnutls_x509_read_eddsa_pubkey(gnutls_ecc_curve_t curve,
return _gnutls_set_datum(&params->raw_pub, der, dersize);
}
+int _gnutls_x509_read_ecdh_pubkey(gnutls_ecc_curve_t curve,
+ uint8_t * der, int dersize,
+ gnutls_pk_params_st * params)
+{
+ int size = gnutls_ecc_curve_get_size(curve);
+ if (dersize != size)
+ return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
+
+ return _gnutls_set_datum(&params->raw_pub, der, dersize);
+}
+
/* Pubkey is a concatenation of X (in little endian) and Y (also LE)
* encoded into OCTET STRING. */
static int
@@ -564,6 +578,12 @@ int _gnutls_x509_read_pubkey(gnutls_pk_algorithm_t algo, uint8_t * der,
case GNUTLS_PK_EDDSA_ED448:
ret = _gnutls_x509_read_eddsa_pubkey(GNUTLS_ECC_CURVE_ED448, der, dersize, params);
break;
+ case GNUTLS_PK_ECDH_X25519:
+ ret = _gnutls_x509_read_ecdh_pubkey(GNUTLS_ECC_CURVE_X25519, der, dersize, params);
+ break;
+ case GNUTLS_PK_ECDH_X448:
+ ret = _gnutls_x509_read_ecdh_pubkey(GNUTLS_ECC_CURVE_X448, der, dersize, params);
+ break;
case GNUTLS_PK_GOST_01:
case GNUTLS_PK_GOST_12_256:
case GNUTLS_PK_GOST_12_512:
@@ -635,6 +655,8 @@ int _gnutls_x509_check_pubkey_params(gnutls_pk_params_st * params)
case GNUTLS_PK_ECDSA:
case GNUTLS_PK_EDDSA_ED25519:
case GNUTLS_PK_EDDSA_ED448:
+ case GNUTLS_PK_ECDH_X25519:
+ case GNUTLS_PK_ECDH_X448:
case GNUTLS_PK_GOST_01:
case GNUTLS_PK_GOST_12_256:
case GNUTLS_PK_GOST_12_512:
diff --git a/lib/x509/key_encode.c b/lib/x509/key_encode.c
index c3ff2a9b05..8428cd1733 100644
--- a/lib/x509/key_encode.c
+++ b/lib/x509/key_encode.c
@@ -161,6 +161,35 @@ _gnutls_x509_write_eddsa_pubkey(const gnutls_pk_params_st * params,
return 0;
}
+/*
+ * some x509 certificate functions that relate to MPI parameter
+ * setting. This writes a raw public key.
+ *
+ * Allocates the space used to store the data.
+ */
+static int
+_gnutls_x509_write_modern_ecdh_pubkey(const gnutls_pk_params_st * params,
+ gnutls_datum_t * raw)
+{
+ int ret;
+
+ raw->data = NULL;
+ raw->size = 0;
+
+ if (params->raw_pub.size == 0)
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+ if (params->curve != GNUTLS_ECC_CURVE_X25519 &&
+ params->curve != GNUTLS_ECC_CURVE_X448)
+ return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);
+
+ ret = _gnutls_set_datum(raw, params->raw_pub.data, params->raw_pub.size);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ return 0;
+}
+
int
_gnutls_x509_write_gost_pubkey(const gnutls_pk_params_st * params,
gnutls_datum_t * der)
@@ -254,6 +283,8 @@ _gnutls_x509_write_pubkey_params(const gnutls_pk_params_st * params,
return _gnutls_x509_write_ecc_params(params->curve, der);
case GNUTLS_PK_EDDSA_ED25519:
case GNUTLS_PK_EDDSA_ED448:
+ case GNUTLS_PK_ECDH_X25519:
+ case GNUTLS_PK_ECDH_X448:
der->data = NULL;
der->size = 0;
@@ -282,6 +313,9 @@ _gnutls_x509_write_pubkey(const gnutls_pk_params_st * params,
case GNUTLS_PK_EDDSA_ED25519:
case GNUTLS_PK_EDDSA_ED448:
return _gnutls_x509_write_eddsa_pubkey(params, der);
+ case GNUTLS_PK_ECDH_X25519:
+ case GNUTLS_PK_ECDH_X448:
+ return _gnutls_x509_write_modern_ecdh_pubkey(params, der);
case GNUTLS_PK_GOST_01:
case GNUTLS_PK_GOST_12_256:
case GNUTLS_PK_GOST_12_512:
@@ -835,7 +869,8 @@ _gnutls_asn1_encode_ecc(asn1_node * c2, gnutls_pk_params_st * params)
goto cleanup;
}
- if (curve_is_eddsa(params->curve)) {
+ if (curve_is_eddsa(params->curve) ||
+ curve_is_modern_ecdh(params->curve)) {
if (params->raw_pub.size == 0 || params->raw_priv.size == 0)
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
ret =
@@ -1039,6 +1074,8 @@ int _gnutls_asn1_encode_privkey(asn1_node * c2,
case GNUTLS_PK_ECDSA:
case GNUTLS_PK_EDDSA_ED25519:
case GNUTLS_PK_EDDSA_ED448:
+ case GNUTLS_PK_ECDH_X25519:
+ case GNUTLS_PK_ECDH_X448:
return _gnutls_asn1_encode_ecc(c2, params);
case GNUTLS_PK_GOST_01:
case GNUTLS_PK_GOST_12_256:
diff --git a/lib/x509/output.c b/lib/x509/output.c
index 70210847b8..1e58c3ca92 100644
--- a/lib/x509/output.c
+++ b/lib/x509/output.c
@@ -1453,6 +1453,8 @@ print_pubkey(gnutls_buffer_st * str, const char *key_name,
case GNUTLS_PK_EDDSA_ED25519:
case GNUTLS_PK_EDDSA_ED448:
+ case GNUTLS_PK_ECDH_X25519:
+ case GNUTLS_PK_ECDH_X448:
case GNUTLS_PK_ECDSA:
{
gnutls_datum_t x, y;
diff --git a/lib/x509/privkey_pkcs8.c b/lib/x509/privkey_pkcs8.c
index c54ad4a8b2..4aa8993307 100644
--- a/lib/x509/privkey_pkcs8.c
+++ b/lib/x509/privkey_pkcs8.c
@@ -69,6 +69,8 @@ _encode_privkey(gnutls_x509_privkey_t pkey, gnutls_datum_t * raw)
switch (pkey->params.algo) {
case GNUTLS_PK_EDDSA_ED25519:
case GNUTLS_PK_EDDSA_ED448:
+ case GNUTLS_PK_ECDH_X25519:
+ case GNUTLS_PK_ECDH_X448:
/* we encode as octet string (which is going to be stored inside
* another octet string). No comments. */
ret = _gnutls_x509_encode_string(ASN1_ETYPE_OCTET_STRING,
@@ -1136,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)
*/
@@ -1461,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: