diff options
Diffstat (limited to 'lib/x509')
-rw-r--r-- | lib/x509/common.c | 3 | ||||
-rw-r--r-- | lib/x509/common.h | 3 | ||||
-rw-r--r-- | lib/x509/key_decode.c | 22 | ||||
-rw-r--r-- | lib/x509/key_encode.c | 39 | ||||
-rw-r--r-- | lib/x509/output.c | 2 | ||||
-rw-r--r-- | lib/x509/privkey_pkcs8.c | 56 |
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(¶ms->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(¶ms->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: |