diff options
31 files changed, 943 insertions, 123 deletions
diff --git a/doc/credentials/x509/Makefile.am b/doc/credentials/x509/Makefile.am index b40a52ed52..80529f5588 100644 --- a/doc/credentials/x509/Makefile.am +++ b/doc/credentials/x509/Makefile.am @@ -1,2 +1,3 @@ EXTRA_DIST = ca-key.pem ca.pem cert-rsa.pem key-rsa.pem clikey.pem clicert.pem \ - clicert-dsa.pem clikey-dsa.pem cert-dsa.pem key-dsa.pem cert-ecc.pem key-ecc.pem + clicert-dsa.pem clikey-dsa.pem cert-dsa.pem key-dsa.pem cert-ecc.pem key-ecc.pem \ + key-eddsa.pem cert-eddsa.pem diff --git a/doc/credentials/x509/cert-eddsa.pem b/doc/credentials/x509/cert-eddsa.pem new file mode 100644 index 0000000000..09d78c25a5 --- /dev/null +++ b/doc/credentials/x509/cert-eddsa.pem @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICeDCCATCgAwIBAgIIVgPhnwLsqdgwDQYJKoZIhvcNAQELBQAwGTEXMBUGA1UE +AxMOR251VExTIFRlc3QgQ0EwIBcNMTUwOTI0MTE0MjIzWhgPOTk5OTEyMzEyMzU5 +NTlaMCwxKjAoBgNVBAMTIVNhbXBsZSBFRERTQS1FZDI1NTE5cCBjZXJ0aWZpY2F0 +ZTAtMAgGAytlZAoBAgMhAOXFSeoir493GDgOl4bRshqYqMhUHCcHmk7ad9P8uMLd +o3YwdDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8GA1UdDwEB +/wQFAwMHgAAwHQYDVR0OBBYEFMRMRRGSs7LUJRL6DNAMONoJK3rzMB8GA1UdIwQY +MBaAFE1Wt2oAWPFnkvSmdVUbjlMBA+/PMA0GCSqGSIb3DQEBCwUAA4IBMQCb+OFV +XeIHDFW717AyLK6YM5RSPn4wrp63aTx13NYbJjwohj54u49MBlA+0hk+W4N4mrIu +Yft7bj2lUYbPZbl5r+hH4CuPbDNf7ezOnSZtPWls9lEi6aQHZ1fU5ao5h7tQQ9Vz +ccOgsaA2vx0CudSMoMnUXIqQ8t4gh9WKJuaH6uS3FYFLFZXhDwgQqtld+kyW0M7d +dh+GQBOp4pgR9EFA2soYryC8TyclRx7LPFFgUlYzj1R3y4EDS3xxkOzp75qqz2Oy +MRy11WFeq+FPucSrN4Ma8wPgnYp6b8kFCQKseAOPltA3x95TKZRGgVuO1FyyPTDh +sBSLXS8q9SNIfpQjiNlGVCNitsgRjUESD+VvrpBy2dtUNMe/Aow5HaFFsNwn4t1Q +xDe2n5f7Ei0HTh8M +-----END CERTIFICATE----- diff --git a/doc/credentials/x509/key-eddsa.pem b/doc/credentials/x509/key-eddsa.pem new file mode 100644 index 0000000000..8aed6cd6b3 --- /dev/null +++ b/doc/credentials/x509/key-eddsa.pem @@ -0,0 +1,34 @@ +Setting log level to 4 +Public Key Info: + Public Key Algorithm: EdDSA + Key Security Level: High (256 bits) + +curve: Ed25519p +private key: + fa:da:b9:f4:db:7b:41:d6:ef:57:25:2a:47:fd:90:e6 + 75:f8:18:44:0e:ce:a0:87:34:50:79:cf:11:8b:f3:2a + + +x: + e5:c5:49:ea:22:af:8f:77:18:38:0e:97:86:d1:b2:1a + 98:a8:c8:54:1c:27:07:9a:4e:da:77:d3:fc:b8:c2:dd + + + +Public Key ID: C4:4C:45:11:92:B3:B2:D4:25:12:FA:0C:D0:0C:38:DA:09:2B:7A:F3 +Public key's random art: ++--[Ed25519p]-----+ +| .o+ ..o+=o | +|+ .o..++.. | +|.= .o o+= | +|+ o +o.o | +|o .ooS | +|. o . | +| . o | +| E | +| | ++-----------------+ + +-----BEGIN EDDSA PRIVATE KEY----- +MCUKAQEEIPraufTbe0HW71clKkf9kOZ1+BhEDs6ghzRQec8Ri/Mq +-----END EDDSA PRIVATE KEY----- diff --git a/lib/algorithms.h b/lib/algorithms.h index db6dd44535..eea9625e5a 100644 --- a/lib/algorithms.h +++ b/lib/algorithms.h @@ -318,6 +318,7 @@ unsigned int _gnutls_pk_bits_to_subgroup_bits(unsigned int pk_bits); struct gnutls_ecc_curve_entry_st { const char *name; const char *oid; + gnutls_pk_algorithm_t pk; /* PK_EDDSA, or PK_ECDSA */ gnutls_ecc_curve_t id; int tls_id; /* The RFC4492 namedCurve ID */ int size; /* the size in bytes */ @@ -329,9 +330,29 @@ const gnutls_ecc_curve_entry_st gnutls_ecc_curve_t gnutls_ecc_curve_get_id(const char *name); int _gnutls_tls_id_to_ecc_curve(int num); int _gnutls_ecc_curve_get_tls_id(gnutls_ecc_curve_t supported_ecc); -gnutls_ecc_curve_t _gnutls_ecc_bits_to_curve(int bits); +gnutls_ecc_curve_t _gnutls_ecc_bits_to_curve(gnutls_pk_algorithm_t pk, int bits); #define MAX_ECC_CURVE_SIZE 66 +inline static int _curve_is_eddsa(const gnutls_ecc_curve_entry_st * e) +{ + size_t ret = 0; + + if (unlikely(e == NULL)) + return ret; + + if (e->pk == GNUTLS_PK_EDDSA) + return 1; + return 0; +} + +#define algo_is_ecc(x) (((x)==GNUTLS_PK_ECDSA||(x)==GNUTLS_PK_EDDSA)?1:0) + +inline static int curve_is_eddsa(gnutls_ecc_curve_t id) +{ + const gnutls_ecc_curve_entry_st *e = _gnutls_ecc_curve_get_params(id); + return _curve_is_eddsa(e); +} + static inline int _gnutls_kx_is_ecc(gnutls_kx_algorithm_t kx) { if (kx == GNUTLS_KX_ECDHE_RSA || kx == GNUTLS_KX_ECDHE_ECDSA || diff --git a/lib/algorithms/ecc.c b/lib/algorithms/ecc.c index b42d95aa4d..5bbfac3660 100644 --- a/lib/algorithms/ecc.c +++ b/lib/algorithms/ecc.c @@ -34,6 +34,7 @@ static const gnutls_ecc_curve_entry_st ecc_curves[] = { .name = "SECP192R1", .oid = "1.2.840.10045.3.1.1", .id = GNUTLS_ECC_CURVE_SECP192R1, + .pk = GNUTLS_PK_ECDSA, .tls_id = 19, .size = 24, }, @@ -41,6 +42,7 @@ static const gnutls_ecc_curve_entry_st ecc_curves[] = { .name = "SECP224R1", .oid = "1.3.132.0.33", .id = GNUTLS_ECC_CURVE_SECP224R1, + .pk = GNUTLS_PK_ECDSA, .tls_id = 21, .size = 28, }, @@ -48,6 +50,7 @@ static const gnutls_ecc_curve_entry_st ecc_curves[] = { .name = "SECP256R1", .oid = "1.2.840.10045.3.1.7", .id = GNUTLS_ECC_CURVE_SECP256R1, + .pk = GNUTLS_PK_ECDSA, .tls_id = 23, .size = 32, }, @@ -55,6 +58,7 @@ static const gnutls_ecc_curve_entry_st ecc_curves[] = { .name = "SECP384R1", .oid = "1.3.132.0.34", .id = GNUTLS_ECC_CURVE_SECP384R1, + .pk = GNUTLS_PK_ECDSA, .tls_id = 24, .size = 48, }, @@ -62,9 +66,18 @@ static const gnutls_ecc_curve_entry_st ecc_curves[] = { .name = "SECP521R1", .oid = "1.3.132.0.35", .id = GNUTLS_ECC_CURVE_SECP521R1, + .pk = GNUTLS_PK_ECDSA, .tls_id = 25, .size = 66, }, + { + .name = "Ed25519ph", + .oid = "1.3.101.100", /* shared across all EDDSA curves */ + .id = GNUTLS_ECC_CURVE_ED25519PH, + .pk = GNUTLS_PK_EDDSA, + .tls_id = 5, /* draft-josefsson-tls-eddsa2-02 */ + .size = 32, + }, {0, 0, 0} }; @@ -188,12 +201,17 @@ gnutls_ecc_curve_t gnutls_ecc_curve_get_id(const char *name) * Returns: return a #gnutls_ecc_curve_t value corresponding to * the specified bit length, or %GNUTLS_ECC_CURVE_INVALID on error. -*/ -gnutls_ecc_curve_t _gnutls_ecc_bits_to_curve(int bits) +gnutls_ecc_curve_t _gnutls_ecc_bits_to_curve(gnutls_pk_algorithm_t pk, int bits) { - gnutls_ecc_curve_t ret = GNUTLS_ECC_CURVE_SECP256R1; + gnutls_ecc_curve_t ret; + + if (pk == GNUTLS_PK_ECDSA) + ret = GNUTLS_ECC_CURVE_SECP256R1; + else + ret = GNUTLS_ECC_CURVE_ED25519PH; GNUTLS_ECC_CURVE_LOOP( - if (8 * p->size >= bits && _gnutls_pk_curve_exists(p->id)) { + if (pk == p->pk && 8 * p->size >= bits && _gnutls_pk_curve_exists(p->id)) { ret = p->id; break; } @@ -298,3 +316,25 @@ int gnutls_ecc_curve_get_size(gnutls_ecc_curve_t curve) return ret; } + +/** + * gnutls_ecc_curve_get_pk: + * @curve: is an ECC curve + * + * Returns: the public key algorithm associated with the named curve or %GNUTLS_PK_UNKNOWN. + * + * Since: 3.5.0 + **/ +gnutls_pk_algorithm_t gnutls_ecc_curve_get_pk(gnutls_ecc_curve_t curve) +{ + int ret = GNUTLS_PK_UNKNOWN; + + GNUTLS_ECC_CURVE_LOOP( + if (p->id == curve) { + ret = p->pk; + break; + } + ); + + return ret; +} diff --git a/lib/algorithms/publickey.c b/lib/algorithms/publickey.c index 183f436899..70ff31e0e2 100644 --- a/lib/algorithms/publickey.c +++ b/lib/algorithms/publickey.c @@ -96,7 +96,8 @@ static const gnutls_pk_entry pk_algorithms[] = { {"DSA", PK_DSA_OID, GNUTLS_PK_DSA}, {"GOST R 34.10-2001", PK_GOST_R3410_2001_OID, GNUTLS_PK_UNKNOWN}, {"GOST R 34.10-94", PK_GOST_R3410_94_OID, GNUTLS_PK_UNKNOWN}, - {"EC", "1.2.840.10045.2.1", GNUTLS_PK_EC}, + {"EC", "1.2.840.10045.2.1", GNUTLS_PK_ECDSA}, + {"EdDSA", "1.3.101.100", GNUTLS_PK_EDDSA}, {0, 0, 0} }; diff --git a/lib/algorithms/secparams.c b/lib/algorithms/secparams.c index bb9b90d962..0e207c5510 100644 --- a/lib/algorithms/secparams.c +++ b/lib/algorithms/secparams.c @@ -88,7 +88,7 @@ gnutls_sec_param_to_pk_bits(gnutls_pk_algorithm_t algo, if (p->sec_param == param) { if (algo == GNUTLS_PK_DSA) ret = p->dsa_bits; - else if (algo == GNUTLS_PK_EC) + else if (algo == GNUTLS_PK_ECDSA || algo == GNUTLS_PK_EDDSA) ret = p->ecc_bits; else ret = p->pk_bits; break; @@ -185,7 +185,7 @@ gnutls_pk_bits_to_sec_param(gnutls_pk_algorithm_t algo, unsigned int bits) if (bits == 0) return GNUTLS_SEC_PARAM_UNKNOWN; - if (algo == GNUTLS_PK_EC) { + if (algo == GNUTLS_PK_ECDSA || algo == GNUTLS_PK_EDDSA) { GNUTLS_SEC_PARAM_LOOP( if (p->ecc_bits > bits) { break; diff --git a/lib/algorithms/sign.c b/lib/algorithms/sign.c index f2ac184667..c42205c8c3 100644 --- a/lib/algorithms/sign.c +++ b/lib/algorithms/sign.c @@ -96,6 +96,9 @@ static const gnutls_sign_entry sign_algorithms[] = { GNUTLS_PK_DSA, GNUTLS_DIG_SHA384, {5, 2}}, {"DSA-SHA512", SIG_DSA_SHA512_OID, GNUTLS_SIGN_DSA_SHA512, GNUTLS_PK_DSA, GNUTLS_DIG_SHA512, {6, 2}}, + /* draft-josefsson-tls-eddsa2-01 + draft-josefsson-pkix-eddsa-02 */ + {"EdDSA-SHA512", "1.3.101.101", GNUTLS_SIGN_EDDSA_SHA512, + GNUTLS_PK_EDDSA, GNUTLS_DIG_SHA512, {6, 4}}, {0, 0, 0, 0, 0, TLS_SIGN_AID_UNKNOWN} }; diff --git a/lib/crypto-backend.h b/lib/crypto-backend.h index 3aba11a842..34eb7123b5 100644 --- a/lib/crypto-backend.h +++ b/lib/crypto-backend.h @@ -267,6 +267,9 @@ void gnutls_pk_params_init(gnutls_pk_params_st * p); #define ECC_Y 1 #define ECC_K 2 +#define EDDSA_PUB 0 +#define EDDSA_PRIV 1 + #define DSA_P 0 #define DSA_Q 1 #define DSA_G 2 diff --git a/lib/gnutls.asn b/lib/gnutls.asn index 6342995330..afaefc8403 100644 --- a/lib/gnutls.asn +++ b/lib/gnutls.asn @@ -90,6 +90,12 @@ DSAPrivateKey ::= SEQUENCE { seed [1] ProvableSeed OPTIONAL } +EdDSAParameters ::= ENUMERATED { ed25519 (1), ed25519p (2) } +EdDSAPrivateKey ::= SEQUENCE { + curve EdDSAParameters, + priv OCTET STRING +} + -- from PKCS#3 DHParameter ::= SEQUENCE { prime INTEGER, -- p diff --git a/lib/gnutls_asn1_tab.c b/lib/gnutls_asn1_tab.c index 5da8f7d742..f7d2163e80 100644 --- a/lib/gnutls_asn1_tab.c +++ b/lib/gnutls_asn1_tab.c @@ -61,6 +61,12 @@ const asn1_static_node gnutls_asn1_tab[] = { { "priv", 1073741827, NULL }, { "seed", 536895490, "ProvableSeed"}, { NULL, 2056, "1"}, + { "EdDSAParameters", 1610874901, NULL }, + { "ed25519", 1073741825, "1"}, + { "ed25519p", 1, "2"}, + { "EdDSAPrivateKey", 1610612741, NULL }, + { "curve", 1073741826, "EdDSAParameters"}, + { "priv", 7, NULL }, { "DHParameter", 1610612741, NULL }, { "prime", 1073741827, NULL }, { "base", 1073741827, NULL }, diff --git a/lib/includes/gnutls/abstract.h b/lib/includes/gnutls/abstract.h index 772bd36255..6601fea614 100644 --- a/lib/includes/gnutls/abstract.h +++ b/lib/includes/gnutls/abstract.h @@ -154,6 +154,10 @@ int gnutls_pubkey_export_ecc_x962(gnutls_pubkey_t key, gnutls_datum_t * parameters, gnutls_datum_t * ecpoint); +int gnutls_pubkey_export_eddsa_raw(gnutls_pubkey_t key, + gnutls_ecc_curve_t * curve, + gnutls_datum_t * pub); + int gnutls_pubkey_export(gnutls_pubkey_t key, gnutls_x509_crt_fmt_t format, void *output_data, size_t * output_data_size); @@ -430,6 +434,12 @@ gnutls_privkey_export_dsa_raw(gnutls_privkey_t key, gnutls_datum_t * x); int +gnutls_privkey_export_eddsa_raw(gnutls_privkey_t key, + gnutls_ecc_curve_t * curve, + gnutls_datum_t *pub, + gnutls_datum_t *priv); + +int gnutls_privkey_export_ecc_raw(gnutls_privkey_t key, gnutls_ecc_curve_t * curve, gnutls_datum_t * x, diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in index 91df048b3c..351090f6a8 100644 --- a/lib/includes/gnutls/gnutls.h.in +++ b/lib/includes/gnutls/gnutls.h.in @@ -657,13 +657,15 @@ typedef enum gnutls_certificate_print_formats { } gnutls_certificate_print_formats_t; #define GNUTLS_PK_ECC GNUTLS_PK_EC +#define GNUTLS_PK_EC GNUTLS_PK_ECDSA /** * gnutls_pk_algorithm_t: * @GNUTLS_PK_UNKNOWN: Unknown public-key algorithm. * @GNUTLS_PK_RSA: RSA public-key algorithm. * @GNUTLS_PK_DSA: DSA public-key algorithm. * @GNUTLS_PK_DH: Diffie-Hellman algorithm. Used to generate parameters. - * @GNUTLS_PK_EC: Elliptic curve algorithm. Used to generate parameters. + * @GNUTLS_PK_ECDSA: Elliptic curve DSA algorithm. + * @GNUTLS_PK_EDDSA: Edwards curve Digital signature algorithm. * * Enumeration of different public-key algorithms. */ @@ -672,7 +674,8 @@ typedef enum { GNUTLS_PK_RSA = 1, GNUTLS_PK_DSA = 2, GNUTLS_PK_DH = 3, - GNUTLS_PK_EC = 4 + GNUTLS_PK_ECDSA = 4, + GNUTLS_PK_EDDSA = 5 } gnutls_pk_algorithm_t; const char *gnutls_pk_algorithm_get_name(gnutls_pk_algorithm_t algorithm); @@ -700,6 +703,7 @@ const char *gnutls_pk_algorithm_get_name(gnutls_pk_algorithm_t algorithm); * @GNUTLS_SIGN_ECDSA_SHA384: Digital signature algorithm ECDSA with SHA-384. * @GNUTLS_SIGN_ECDSA_SHA512: Digital signature algorithm ECDSA with SHA-512. * @GNUTLS_SIGN_ECDSA_SHA224: Digital signature algorithm ECDSA with SHA-224. + * @GNUTLS_SIGN_EDDSA_SHA512: Digital signature algorithm EdDSA with SHA-512. * * Enumeration of different digital signature algorithms. */ @@ -724,7 +728,8 @@ typedef enum { GNUTLS_SIGN_ECDSA_SHA384 = 15, GNUTLS_SIGN_ECDSA_SHA512 = 16, GNUTLS_SIGN_DSA_SHA384 = 17, - GNUTLS_SIGN_DSA_SHA512 = 18 + GNUTLS_SIGN_DSA_SHA512 = 18, + GNUTLS_SIGN_EDDSA_SHA512 = 19 } gnutls_sign_algorithm_t; /** @@ -735,6 +740,7 @@ typedef enum { * @GNUTLS_ECC_CURVE_SECP256R1: the SECP256R1 curve * @GNUTLS_ECC_CURVE_SECP384R1: the SECP384R1 curve * @GNUTLS_ECC_CURVE_SECP521R1: the SECP521R1 curve + * @GNUTLS_ECC_CURVE_ED25519PH: the Ed25519 curve (in prehash mode) * * Enumeration of ECC curves. */ @@ -744,7 +750,8 @@ typedef enum { GNUTLS_ECC_CURVE_SECP256R1, GNUTLS_ECC_CURVE_SECP384R1, GNUTLS_ECC_CURVE_SECP521R1, - GNUTLS_ECC_CURVE_SECP192R1 + GNUTLS_ECC_CURVE_SECP192R1, + GNUTLS_ECC_CURVE_ED25519PH } gnutls_ecc_curve_t; /* macros to allow specifying a specific curve in gnutls_privkey_generate() @@ -866,6 +873,7 @@ unsigned int gnutls_sec_param_to_symmetric_bits(gnutls_sec_param_t param) __GNUTLS_CONST__; /* Elliptic curves */ +gnutls_pk_algorithm_t gnutls_ecc_curve_get_pk(gnutls_ecc_curve_t curve); const char * gnutls_ecc_curve_get_name(gnutls_ecc_curve_t curve) __GNUTLS_CONST__; const char * diff --git a/lib/libgnutls.map b/lib/libgnutls.map index 7885153be3..fde4f81b73 100644 --- a/lib/libgnutls.map +++ b/lib/libgnutls.map @@ -1072,6 +1072,7 @@ GNUTLS_3_4 gnutls_decode_ber_digest_info; gnutls_encode_ber_digest_info; gnutls_pkcs7_get_embedded_data; + gnutls_ecc_curve_get_pk; local: *; }; diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c index c7ef0d78c5..e05a84f4c9 100644 --- a/lib/nettle/pk.c +++ b/lib/nettle/pk.c @@ -46,10 +46,11 @@ #include <nettle/ecc.h> #include <nettle/ecdsa.h> #include <nettle/ecc-curve.h> +#include <nettle/eddsa.h> #include <gnettle.h> #include <fips.h> -static inline const struct ecc_curve *get_supported_curve(int curve); +static inline const struct ecc_curve *get_supported_nist_curve(int curve); static void rnd_func(void *_ctx, size_t length, uint8_t * data) { @@ -251,7 +252,7 @@ dh_cleanup: out->data = NULL; - curve = get_supported_curve(priv->flags); + curve = get_supported_nist_curve(priv->flags); if (curve == NULL) return gnutls_assert_val @@ -445,14 +446,44 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo, const mac_entry_st *me; switch (algo) { - case GNUTLS_PK_EC: /* we do ECDSA */ + case GNUTLS_PK_EDDSA: + { + uint8_t key[32]; + uint8_t pub[32]; + int curve_id = pk_params->flags; + + if (curve_id != GNUTLS_ECC_CURVE_ED25519PH) + return + gnutls_assert_val + (GNUTLS_E_ECC_UNSUPPORTED_CURVE); + + /* curve25519 for now */ + if (nettle_mpz_sizeinbase_256_u(TOMPZ(pk_params->params[EDDSA_PRIV])) > 32) + return gnutls_assert_val(GNUTLS_E_PK_SIGN_FAILED); + + if (nettle_mpz_sizeinbase_256_u(TOMPZ(pk_params->params[EDDSA_PUB])) > 32) + return gnutls_assert_val(GNUTLS_E_PK_SIGN_FAILED); + + nettle_mpz_get_str_256(32, key, TOMPZ(pk_params->params[EDDSA_PRIV])); + nettle_mpz_get_str_256(32, pub, TOMPZ(pk_params->params[EDDSA_PUB])); + + signature->data = gnutls_malloc(ED25519_SIGNATURE_SIZE); + if (signature->data == NULL) + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + + signature->size = ED25519_SIGNATURE_SIZE; + + ed25519_sha512_sign(pub, key, vdata->size, vdata->data, signature->data); + break; + } + case GNUTLS_PK_ECDSA: /* we do ECDSA */ { struct ecc_scalar priv; struct dsa_signature sig; int curve_id = pk_params->flags; const struct ecc_curve *curve; - curve = get_supported_curve(curve_id); + curve = get_supported_nist_curve(curve_id); if (curve == NULL) return gnutls_assert_val @@ -599,14 +630,41 @@ _wrap_nettle_pk_verify(gnutls_pk_algorithm_t algo, bigint_t tmp[2] = { NULL, NULL }; switch (algo) { - case GNUTLS_PK_EC: /* ECDSA */ + case GNUTLS_PK_EDDSA: /* EdDSA */ + { + uint8_t pub[32]; + int curve_id = pk_params->flags; + + if (curve_id != GNUTLS_ECC_CURVE_ED25519PH) + return + gnutls_assert_val + (GNUTLS_E_ECC_UNSUPPORTED_CURVE); + + /* curve25519 for now */ + if (signature->size != ED25519_SIGNATURE_SIZE) + return gnutls_assert_val(GNUTLS_E_PK_SIG_VERIFY_FAILED); + + if (nettle_mpz_sizeinbase_256_u(pk_params->params[EDDSA_PUB]) > 32) + return gnutls_assert_val(GNUTLS_E_PK_SIG_VERIFY_FAILED); + + nettle_mpz_get_str_256(32, pub, pk_params->params[EDDSA_PUB]); + + ret = ed25519_sha512_verify(pub, vdata->size, vdata->data, signature->data); + if (ret == 0) { + gnutls_assert(); + ret = GNUTLS_E_PK_SIG_VERIFY_FAILED; + } else + ret = 0; + break; + } + case GNUTLS_PK_ECDSA: /* ECDSA */ { struct ecc_point pub; struct dsa_signature sig; int curve_id = pk_params->flags; const struct ecc_curve *curve; - curve = get_supported_curve(curve_id); + curve = get_supported_nist_curve(curve_id); if (curve == NULL) return gnutls_assert_val @@ -724,7 +782,7 @@ _wrap_nettle_pk_verify(gnutls_pk_algorithm_t algo, return ret; } -static inline const struct ecc_curve *get_supported_curve(int curve) +static inline const struct ecc_curve *get_supported_nist_curve(int curve) { switch (curve) { #ifdef ENABLE_NON_SUITEB_CURVES @@ -744,15 +802,25 @@ static inline const struct ecc_curve *get_supported_curve(int curve) } } +static inline bool get_supported_ed_curve(int curve) +{ + switch (curve) { + case GNUTLS_ECC_CURVE_ED25519PH: + return 1; + default: + return 0; + } +} + static int _wrap_nettle_pk_curve_exists(gnutls_ecc_curve_t curve) { - return ((get_supported_curve(curve)!=NULL)?1:0); + return ((get_supported_nist_curve(curve)!=NULL||get_supported_ed_curve(curve))?1:0); } /* Generates algorithm's parameters. That is: * For DSA: p, q, and g are generated. * For RSA: nothing - * For ECDSA: just checks the curve is ok + * For ECDSA/EDDSA: nothing */ static int wrap_nettle_pk_generate_params(gnutls_pk_algorithm_t algo, @@ -868,7 +936,8 @@ wrap_nettle_pk_generate_params(gnutls_pk_algorithm_t algo, break; } case GNUTLS_PK_RSA: - case GNUTLS_PK_EC: + case GNUTLS_PK_ECDSA: + case GNUTLS_PK_EDDSA: ret = 0; break; default: @@ -1337,7 +1406,34 @@ wrap_nettle_pk_generate_keys(gnutls_pk_algorithm_t algo, break; } - case GNUTLS_PK_EC: + case GNUTLS_PK_EDDSA: + { + /* one option for now -> curve25519 */ + uint8_t key[32]; + uint8_t pub[32]; + + if (params->flags & GNUTLS_PK_FLAG_PROVABLE) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + ret = gnutls_rnd(GNUTLS_RND_RANDOM, key, sizeof(key)); + if (ret < 0) + return gnutls_assert_val(ret); + + ed25519_sha512_public_key(pub, key); + + ret = _gnutls_mpi_init_multi(¶ms->params[EDDSA_PRIV], ¶ms->params[EDDSA_PUB], NULL); + if (ret < 0) + return gnutls_assert_val(ret); + + nettle_mpz_set_str_256_u(TOMPZ(params->params[EDDSA_PRIV]), 32, key); + nettle_mpz_set_str_256_u(TOMPZ(params->params[EDDSA_PUB]), 32, pub); + + params->flags = GNUTLS_ECC_CURVE_ED25519PH; + params->params_nr = 2; + + break; + } + case GNUTLS_PK_ECDSA: if (params->flags & GNUTLS_PK_FLAG_PROVABLE) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); @@ -1346,7 +1442,7 @@ wrap_nettle_pk_generate_keys(gnutls_pk_algorithm_t algo, struct ecc_point pub; const struct ecc_curve *curve; - curve = get_supported_curve(level); + curve = get_supported_nist_curve(level); if (curve == NULL) return gnutls_assert_val @@ -1526,7 +1622,7 @@ wrap_nettle_pk_verify_priv_params(gnutls_pk_algorithm_t algo, } break; - case GNUTLS_PK_EC: + case GNUTLS_PK_ECDSA: { struct ecc_point r, pub; struct ecc_scalar priv; @@ -1538,7 +1634,7 @@ wrap_nettle_pk_verify_priv_params(gnutls_pk_algorithm_t algo, gnutls_assert_val (GNUTLS_E_INVALID_REQUEST); - curve = get_supported_curve(params->flags); + curve = get_supported_nist_curve(params->flags); if (curve == NULL) return gnutls_assert_val @@ -1599,6 +1695,9 @@ wrap_nettle_pk_verify_priv_params(gnutls_pk_algorithm_t algo, mpz_clear(y2); } break; + case GNUTLS_PK_EDDSA: + ret = 0; + break; default: ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); } @@ -1615,8 +1714,9 @@ wrap_nettle_pk_verify_pub_params(gnutls_pk_algorithm_t algo, switch (algo) { case GNUTLS_PK_RSA: case GNUTLS_PK_DSA: + case GNUTLS_PK_EDDSA: return 0; - case GNUTLS_PK_EC: + case GNUTLS_PK_ECDSA: { /* just verify that x and y lie on the curve */ struct ecc_point r, pub; @@ -1627,7 +1727,7 @@ wrap_nettle_pk_verify_pub_params(gnutls_pk_algorithm_t algo, gnutls_assert_val (GNUTLS_E_INVALID_REQUEST); - curve = get_supported_curve(params->flags); + curve = get_supported_nist_curve(params->flags); if (curve == NULL) return gnutls_assert_val @@ -1741,6 +1841,27 @@ wrap_nettle_pk_fixup(gnutls_pk_algorithm_t algo, params->params_nr = RSA_PRIVATE_PARAMS; } + if (direction == GNUTLS_IMPORT && algo == GNUTLS_PK_EDDSA) { + uint8_t key[32]; + uint8_t pub[32]; + + if (params->flags != GNUTLS_ECC_CURVE_ED25519PH) + return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE); + + nettle_mpz_get_str_256(32, key, params->params[EDDSA_PRIV]); + + ed25519_sha512_public_key(pub, key); + + zrelease_mpi_key(¶ms->params[EDDSA_PUB]); + + ret = + _gnutls_mpi_init_scan_nz(¶ms->params[EDDSA_PUB], pub, sizeof(pub)); + if (ret < 0) + return gnutls_assert_val(ret); + + params->params_nr = 2; + } + return 0; } @@ -649,36 +649,63 @@ int _gnutls_params_get_ecc_raw(const gnutls_pk_params_st* params, if (curve) *curve = params->flags; - /* X */ - if (x) { - ret = _gnutls_mpi_dprint_lz(params->params[ECC_X], x); - if (ret < 0) { - gnutls_assert(); - return ret; + if (params->algo == GNUTLS_PK_EDDSA) { + unsigned size; + size = gnutls_ecc_curve_get_size(params->flags); + + if (x) { + ret = _gnutls_mpi_dprint_size(params->params[EDDSA_PUB], x, size); + if (ret < 0) { + gnutls_assert(); + return ret; + } } - } - /* Y */ - if (y) { - ret = _gnutls_mpi_dprint_lz(params->params[ECC_Y], y); - if (ret < 0) { - gnutls_assert(); - _gnutls_free_datum(x); - return ret; + if (y) { + y->data = NULL; + y->size = 0; } - } + if (k) { + ret = _gnutls_mpi_dprint_size(params->params[EDDSA_PRIV], k, size); + if (ret < 0) { + gnutls_assert(); + _gnutls_free_datum(x); + return ret; + } + } + } else if (params->algo == GNUTLS_PK_ECDSA) { + /* X */ + if (x) { + ret = _gnutls_mpi_dprint_lz(params->params[ECC_X], x); + if (ret < 0) { + gnutls_assert(); + return ret; + } + } - /* K */ - if (k) { - ret = _gnutls_mpi_dprint_lz(params->params[ECC_K], k); - if (ret < 0) { - gnutls_assert(); - _gnutls_free_datum(x); - _gnutls_free_datum(y); - return ret; + /* Y */ + if (y) { + ret = _gnutls_mpi_dprint_lz(params->params[ECC_Y], y); + if (ret < 0) { + gnutls_assert(); + _gnutls_free_datum(x); + return ret; + } } - } + + /* K */ + if (k) { + ret = _gnutls_mpi_dprint_lz(params->params[ECC_K], k); + if (ret < 0) { + gnutls_assert(); + _gnutls_free_datum(x); + _gnutls_free_datum(y); + return ret; + } + } + } else + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); return 0; @@ -742,7 +769,8 @@ pk_prepare_hash(gnutls_pk_algorithm_t pk, _gnutls_free_datum(&old_digest); break; case GNUTLS_PK_DSA: - case GNUTLS_PK_EC: + case GNUTLS_PK_ECDSA: + case GNUTLS_PK_EDDSA: break; default: gnutls_assert(); @@ -751,3 +779,4 @@ pk_prepare_hash(gnutls_pk_algorithm_t pk, return 0; } + diff --git a/lib/pkcs11_privkey.c b/lib/pkcs11_privkey.c index 237af98c18..e7430ec211 100644 --- a/lib/pkcs11_privkey.c +++ b/lib/pkcs11_privkey.c @@ -835,7 +835,7 @@ gnutls_pkcs11_privkey_generate3(const char *url, gnutls_pk_algorithm_t pk, a[a_val].value_len = sizeof(_bits); a_val++; break; - case GNUTLS_PK_EC: + case GNUTLS_PK_ECDSA: p[p_val].type = CKA_SIGN; if (key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE) { p[p_val].value = (void *) &tval; @@ -854,7 +854,7 @@ gnutls_pkcs11_privkey_generate3(const char *url, gnutls_pk_algorithm_t pk, if (GNUTLS_BITS_ARE_CURVE(bits)) { bits = GNUTLS_BITS_TO_CURVE(bits); } else { - bits = _gnutls_ecc_bits_to_curve(bits); + bits = _gnutls_ecc_bits_to_curve(pk, bits); } ret = _gnutls_x509_write_ecc_params(bits, &der); diff --git a/lib/privkey.c b/lib/privkey.c index 90a6304796..addc31938d 100644 --- a/lib/privkey.c +++ b/lib/privkey.c @@ -202,6 +202,18 @@ privkey_to_pubkey(gnutls_pk_algorithm_t pk, } break; + case GNUTLS_PK_EDDSA: + pub->params[EDDSA_PUB] = _gnutls_mpi_copy(priv->params[EDDSA_PUB]); + + pub->params_nr = 1; + + if (pub->params[EDDSA_PUB] == NULL) { + gnutls_assert(); + ret = GNUTLS_E_MEMORY_ERROR; + goto cleanup; + } + + break; default: gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; diff --git a/lib/privkey_raw.c b/lib/privkey_raw.c index 47754831ee..fe6190b8ce 100644 --- a/lib/privkey_raw.c +++ b/lib/privkey_raw.c @@ -127,7 +127,6 @@ int ret; return ret; } - /** * gnutls_privkey_export_ecc_raw: * @key: Holds the public key @@ -138,7 +137,8 @@ int ret; * * This function will export the ECC private key's parameters found * in the given structure. The new parameters will be allocated using - * gnutls_malloc() and will be stored in the appropriate datum. + * gnutls_malloc() and will be stored in the appropriate datum. For + * EdDSA keys, the @y value should be %NULL. * * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code. * diff --git a/lib/pubkey.c b/lib/pubkey.c index 23b0625f5b..331e8991bb 100644 --- a/lib/pubkey.c +++ b/lib/pubkey.c @@ -50,7 +50,8 @@ int pubkey_to_bits(gnutls_pk_algorithm_t pk, gnutls_pk_params_st * params) return _gnutls_mpi_get_nbits(params->params[RSA_MODULUS]); case GNUTLS_PK_DSA: return _gnutls_mpi_get_nbits(params->params[DSA_P]); - case GNUTLS_PK_EC: + case GNUTLS_PK_ECDSA: + case GNUTLS_PK_EDDSA: return gnutls_ecc_curve_get_size(params->flags) * 8; default: return 0; @@ -289,14 +290,19 @@ gnutls_pubkey_get_preferred_hash_algorithm(gnutls_pubkey_t key, if (mand) *mand = 1; /* fallthrough */ - case GNUTLS_PK_EC: - + case GNUTLS_PK_ECDSA: me = _gnutls_dsa_q_to_hash(key->pk_algorithm, &key->params, NULL); if (hash) *hash = (gnutls_digest_algorithm_t)me->id; ret = 0; break; + case GNUTLS_PK_EDDSA: + if (hash) + *hash = GNUTLS_DIG_SHA512; + + ret = 0; + break; case GNUTLS_PK_RSA: if (hash) *hash = GNUTLS_DIG_SHA256; @@ -952,6 +958,7 @@ gnutls_pubkey_export_dsa_raw(gnutls_pubkey_t key, * This function will export the ECC public key's parameters found in * the given key. The new parameters will be allocated using * gnutls_malloc() and will be stored in the appropriate datum. + * For EdDSA public keys, @y will be set to %NULL. * * This function allows for %NULL parameters since 3.4.1. * @@ -971,7 +978,7 @@ gnutls_pubkey_export_ecc_raw(gnutls_pubkey_t key, return GNUTLS_E_INVALID_REQUEST; } - if (key->pk_algorithm != GNUTLS_PK_EC) { + if (key->pk_algorithm != GNUTLS_PK_EDDSA && key->pk_algorithm != GNUTLS_PK_ECDSA) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } @@ -979,6 +986,21 @@ gnutls_pubkey_export_ecc_raw(gnutls_pubkey_t key, if (curve) *curve = key->params.flags; + if (key->pk_algorithm == GNUTLS_PK_EDDSA) { + /* X */ + if (x) { + ret = _gnutls_mpi_dprint_size(key->params.params[EDDSA_PUB], x, gnutls_ecc_curve_get_size(key->params.flags)); + if (ret < 0) { + gnutls_assert(); + return ret; + } + } + + return 0; + } + + /* ECDSA keys */ + /* X */ if (x) { ret = _gnutls_mpi_dprint_lz(key->params.params[ECC_X], x); @@ -1426,14 +1448,18 @@ gnutls_pubkey_import_ecc_raw(gnutls_pubkey_t key, } key->params.params_nr++; - if (_gnutls_mpi_init_scan_nz - (&key->params.params[ECC_Y], y->data, y->size)) { - gnutls_assert(); - ret = GNUTLS_E_MPI_SCAN_FAILED; - goto cleanup; + if (!curve_is_eddsa(curve)) { + if (_gnutls_mpi_init_scan_nz + (&key->params.params[ECC_Y], y->data, y->size)) { + gnutls_assert(); + ret = GNUTLS_E_MPI_SCAN_FAILED; + goto cleanup; + } + key->params.params_nr++; + key->pk_algorithm = GNUTLS_PK_ECDSA; + } else { + key->pk_algorithm = GNUTLS_PK_EDDSA; } - key->params.params_nr++; - key->pk_algorithm = GNUTLS_PK_EC; return 0; @@ -1891,6 +1917,30 @@ dsa_verify_data(gnutls_pk_algorithm_t pk, return _gnutls_pk_verify(pk, &digest, signature, params); } +static int +eddsa_verify_data(gnutls_pk_algorithm_t pk, + const mac_entry_st * algo, + const gnutls_datum_t * data, + const gnutls_datum_t * signature, + gnutls_pk_params_st * params) +{ + int ret; + uint8_t _digest[MAX_HASH_SIZE]; + gnutls_datum_t digest; + + if (algo == NULL) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + ret = _gnutls_hash_fast(algo->id, data->data, data->size, _digest); + if (ret < 0) + return gnutls_assert_val(ret); + + digest.data = _digest; + digest.size = _gnutls_hash_get_algo_len(algo); + + return _gnutls_pk_verify(pk, &digest, signature, params); +} + /* Verifies the signature data, and returns GNUTLS_E_PK_SIG_VERIFY_FAILED if * not verified, or 1 otherwise. */ @@ -1965,6 +2015,15 @@ pubkey_verify_data(gnutls_pk_algorithm_t pk, return 1; break; + case GNUTLS_PK_EDDSA: + if (eddsa_verify_data(pk, me, data, signature, issuer_params) + != 0) { + gnutls_assert(); + return GNUTLS_E_PK_SIG_VERIFY_FAILED; + } + + return 1; + break; default: gnutls_assert(); return GNUTLS_E_INTERNAL_ERROR; diff --git a/lib/x509/key_decode.c b/lib/x509/key_decode.c index 049e93a951..11548b22f2 100644 --- a/lib/x509/key_decode.c +++ b/lib/x509/key_decode.c @@ -37,6 +37,8 @@ static int _gnutls_x509_read_dsa_pubkey(uint8_t * der, int dersize, gnutls_pk_params_st * params); static int _gnutls_x509_read_ecc_pubkey(uint8_t * der, int dersize, gnutls_pk_params_st * params); +static int _gnutls_x509_read_eddsa_pubkey(uint8_t * der, int dersize, + gnutls_pk_params_st * params); static int _gnutls_x509_read_dsa_params(uint8_t * der, int dersize, @@ -109,6 +111,12 @@ _gnutls_x509_read_ecc_pubkey(uint8_t * der, int dersize, ¶ms->params[ECC_Y]); } +int +_gnutls_x509_read_eddsa_pubkey(uint8_t * der, int dersize, + gnutls_pk_params_st * params) +{ + return _gnutls_mpi_init_scan(¶ms->params[EDDSA_PUB], der, dersize); +} /* reads p,q and g * from the certificate (subjectPublicKey BIT STRING). @@ -228,7 +236,55 @@ _gnutls_x509_read_ecc_params(uint8_t * der, int dersize, asn1_delete_structure(&spk); return ret; +} + +/* params as defined in draft-josefsson-pkix-eddsa-02 + */ +int +_gnutls_x509_read_eddsa_params(uint8_t * der, int dersize, + unsigned int * curve) +{ + int ret; + ASN1_TYPE spk = ASN1_TYPE_EMPTY; + unsigned int cid; + if ((ret = asn1_create_element + (_gnutls_get_gnutls_asn(), "GNUTLS.EdDSAParameters", + &spk)) != ASN1_SUCCESS) { + gnutls_assert(); + return _gnutls_asn2err(ret); + } + + ret = asn1_der_decoding(&spk, der, dersize, NULL); + if (ret != ASN1_SUCCESS) { + gnutls_assert(); + ret = _gnutls_asn2err(ret); + goto cleanup; + } + + /* read the curve */ + ret = _gnutls_x509_read_uint(spk, "", &cid); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + if (cid != 2) { + _gnutls_debug_log("EdDSA curve %u is not supported\n", cid); + gnutls_assert(); + ret = GNUTLS_E_ECC_UNSUPPORTED_CURVE; + goto cleanup; + } + + *curve = GNUTLS_ECC_CURVE_ED25519PH; + + ret = 0; + + cleanup: + + asn1_delete_structure(&spk); + + return ret; } int _gnutls_x509_read_pubkey(gnutls_pk_algorithm_t algo, uint8_t * der, @@ -247,11 +303,16 @@ int _gnutls_x509_read_pubkey(gnutls_pk_algorithm_t algo, uint8_t * der, if (ret >= 0) params->params_nr = DSA_PUBLIC_PARAMS; break; - case GNUTLS_PK_EC: + case GNUTLS_PK_ECDSA: ret = _gnutls_x509_read_ecc_pubkey(der, dersize, params); if (ret >= 0) params->params_nr = ECC_PUBLIC_PARAMS; break; + case GNUTLS_PK_EDDSA: + ret = _gnutls_x509_read_eddsa_pubkey(der, dersize, params); + if (ret >= 0) + params->params_nr = 1; + break; default: ret = gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE); break; @@ -268,8 +329,10 @@ int _gnutls_x509_read_pubkey_params(gnutls_pk_algorithm_t algo, return 0; case GNUTLS_PK_DSA: return _gnutls_x509_read_dsa_params(der, dersize, params); - case GNUTLS_PK_EC: + case GNUTLS_PK_ECDSA: return _gnutls_x509_read_ecc_params(der, dersize, ¶ms->flags); + case GNUTLS_PK_EDDSA: + return _gnutls_x509_read_eddsa_params(der, dersize, ¶ms->flags); default: return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE); } diff --git a/lib/x509/key_encode.c b/lib/x509/key_encode.c index 8ebc9fabc7..fd0b034bd2 100644 --- a/lib/x509/key_encode.c +++ b/lib/x509/key_encode.c @@ -128,6 +128,34 @@ _gnutls_x509_write_ecc_pubkey(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. + */ +int +_gnutls_x509_write_eddsa_pubkey(gnutls_pk_params_st * params, + gnutls_datum_t * raw) +{ + int ret; + + raw->data = NULL; + raw->size = 0; + + if (params->params_nr < 1) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + if (params->flags != GNUTLS_ECC_CURVE_ED25519PH) + return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE); + + ret = _gnutls_mpi_dprint_size(params->params[EDDSA_PUB], raw, 32); + if (ret < 0) + return gnutls_assert_val(ret); + + return 0; +} + int _gnutls_x509_write_pubkey_params(gnutls_pk_algorithm_t algo, gnutls_pk_params_st * params, @@ -144,8 +172,10 @@ _gnutls_x509_write_pubkey_params(gnutls_pk_algorithm_t algo, memcpy(der->data, ASN1_NULL, ASN1_NULL_SIZE); der->size = ASN1_NULL_SIZE; return 0; - case GNUTLS_PK_EC: + case GNUTLS_PK_ECDSA: return _gnutls_x509_write_ecc_params(params->flags, der); + case GNUTLS_PK_EDDSA: + return _gnutls_x509_write_eddsa_params(params->flags, der); default: return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE); } @@ -161,8 +191,10 @@ _gnutls_x509_write_pubkey(gnutls_pk_algorithm_t algo, return _gnutls_x509_write_dsa_pubkey(params, der); case GNUTLS_PK_RSA: return _gnutls_x509_write_rsa_pubkey(params, der); - case GNUTLS_PK_EC: + case GNUTLS_PK_ECDSA: return _gnutls_x509_write_ecc_pubkey(params, der); + case GNUTLS_PK_EDDSA: + return _gnutls_x509_write_eddsa_pubkey(params, der); default: return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE); } @@ -286,6 +318,58 @@ _gnutls_x509_write_ecc_params(gnutls_ecc_curve_t curve, } /* + * This function writes the parameters for EdDSA keys. + * That is the EdDSAParameters struct. + * + * Allocates the space used to store the DER data. + */ +int +_gnutls_x509_write_eddsa_params(gnutls_ecc_curve_t curve, + gnutls_datum_t * der) +{ + int result; + ASN1_TYPE spk = ASN1_TYPE_EMPTY; + const uint8_t two = '\x02'; + const char *oid; + + der->data = NULL; + der->size = 0; + + if (curve != GNUTLS_ECC_CURVE_ED25519PH) + return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE); + + oid = gnutls_ecc_curve_get_oid(curve); + if (oid == NULL) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + if ((result = asn1_create_element + (_gnutls_get_gnutls_asn(), "GNUTLS.EdDSAParameters", &spk)) + != ASN1_SUCCESS) { + gnutls_assert(); + return _gnutls_asn2err(result); + } + + if ((result = + asn1_write_value(spk, "", &two, 1)) != ASN1_SUCCESS) { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + + result = _gnutls_x509_der_encode(spk, "", der, 0); + if (result < 0) { + gnutls_assert(); + goto cleanup; + } + + result = 0; + + cleanup: + asn1_delete_structure(&spk); + return result; +} + +/* * This function writes the public parameters for DSS keys. * Needs 1 parameter (y). * @@ -579,6 +663,69 @@ cleanup: return ret; } +/* Encodes the EDDSA parameters into an ASN.1 ECPrivateKey structure. + */ +static int +_gnutls_asn1_encode_eddsa(ASN1_TYPE * c2, gnutls_pk_params_st * params) +{ + int ret; + const uint8_t two = '\x01'; + gnutls_datum_t key = {NULL, 0}; + const char *oid; + + oid = gnutls_ecc_curve_get_oid(params->flags); + + if (params->params_nr != 2 || oid == NULL) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + if (params->flags != GNUTLS_ECC_CURVE_ED25519PH) + return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE); + + ret = _gnutls_mpi_dprint_size(params->params[EDDSA_PRIV], &key, 32); + if (ret < 0) + return gnutls_assert_val(ret); + + /* Ok. Now we have the data. Create the asn1 structures + */ + + /* first make sure that no previously allocated data are leaked */ + if (*c2 != ASN1_TYPE_EMPTY) { + asn1_delete_structure(c2); + *c2 = ASN1_TYPE_EMPTY; + } + + if ((ret = asn1_create_element + (_gnutls_get_gnutls_asn(), "GNUTLS.EdDSAPrivateKey", c2)) + != ASN1_SUCCESS) { + gnutls_assert(); + ret = _gnutls_asn2err(ret); + goto cleanup; + } + + if ((ret = + asn1_write_value(*c2, "curve", &two, 1)) != ASN1_SUCCESS) { + gnutls_assert(); + ret = _gnutls_asn2err(ret); + goto cleanup; + } + + if ((ret = + asn1_write_value(*c2, "priv", key.data, key.size)) != ASN1_SUCCESS) { + gnutls_assert(); + ret = _gnutls_asn2err(ret); + goto cleanup; + } + + _gnutls_free_datum(&key); + return 0; + +cleanup: + asn1_delete_structure2(c2, ASN1_DELETE_FLAG_ZEROIZE); + _gnutls_free_datum(&key); + + return ret; +} + /* Encodes the DSA parameters into an ASN.1 DSAPrivateKey structure. */ @@ -686,6 +833,8 @@ int _gnutls_asn1_encode_privkey(gnutls_pk_algorithm_t pk, ASN1_TYPE * c2, return _gnutls_asn1_encode_dsa(c2, params, compat); case GNUTLS_PK_EC: return _gnutls_asn1_encode_ecc(c2, params); + case GNUTLS_PK_EDDSA: + return _gnutls_asn1_encode_eddsa(c2, params); default: return GNUTLS_E_UNIMPLEMENTED_FEATURE; } diff --git a/lib/x509/output.c b/lib/x509/output.c index 633d3ee1af..11f2892140 100644 --- a/lib/x509/output.c +++ b/lib/x509/output.c @@ -1464,7 +1464,7 @@ static void print_keyid(gnutls_buffer_st * str, gnutls_x509_crt_t cert) if (err < 0) return; - if (err == GNUTLS_PK_EC) { + if (err == GNUTLS_PK_ECDSA || err == GNUTLS_PK_EDDSA) { gnutls_ecc_curve_t curve; err = gnutls_x509_crt_get_pk_ecc_raw(cert, &curve, NULL, NULL); diff --git a/lib/x509/privkey.c b/lib/x509/privkey.c index 3c6b04f73a..a1f9a0bc51 100644 --- a/lib/x509/privkey.c +++ b/lib/x509/privkey.c @@ -279,7 +279,7 @@ _gnutls_privkey_decode_ecc_key(ASN1_TYPE* pkey_asn, const gnutls_datum_t * raw_k gnutls_pk_params_init(&pkey->params); - pkey->params.algo = GNUTLS_PK_EC; + pkey->params.algo = GNUTLS_PK_ECDSA; if ((ret = asn1_create_element(_gnutls_get_gnutls_asn(), "GNUTLS.ECPrivateKey", @@ -376,6 +376,81 @@ _gnutls_privkey_decode_ecc_key(ASN1_TYPE* pkey_asn, const gnutls_datum_t * raw_k } +/* Converts an ECC key to + * an internal structure (gnutls_private_key) + */ +int +_gnutls_privkey_decode_eddsa_key(ASN1_TYPE* pkey_asn, const gnutls_datum_t * raw_key, + gnutls_x509_privkey_t pkey, gnutls_ecc_curve_t curve) +{ + int ret; + unsigned int stored_curve; + + gnutls_pk_params_init(&pkey->params); + + pkey->params.algo = GNUTLS_PK_EDDSA; + if ((ret = + asn1_create_element(_gnutls_get_gnutls_asn(), + "GNUTLS.EdDSAPrivateKey", + pkey_asn)) != ASN1_SUCCESS) { + gnutls_assert(); + return _gnutls_asn2err(ret); + } + + ret = + _asn1_strict_der_decode(pkey_asn, raw_key->data, raw_key->size, + NULL); + if (ret != ASN1_SUCCESS) { + gnutls_assert(); + ret = _gnutls_asn2err(ret); + goto error; + } + + ret = _gnutls_x509_read_uint(*pkey_asn, "curve", &stored_curve); + if (ret < 0) { + gnutls_assert(); + goto error; + } + + if (stored_curve != 1) { + _gnutls_debug_log + ("EdDSA private key algorithm %u is not supported\n", + stored_curve); + gnutls_assert(); + ret = GNUTLS_E_ECC_UNSUPPORTED_CURVE; + goto error; + } + + /* read the curve */ + pkey->params.flags = GNUTLS_ECC_CURVE_ED25519PH; + + ret = + _gnutls_x509_read_key_int(*pkey_asn, "priv", + &pkey->params.params[EDDSA_PRIV]); + if (ret < 0) { + gnutls_assert(); + goto error; + } + + pkey->params.params_nr = 1; + + /* make the public key */ + ret = _gnutls_pk_fixup(GNUTLS_PK_EDDSA, GNUTLS_IMPORT, &pkey->params); + if (ret < 0) { + gnutls_assert(); + goto error; + } + + return 0; + + error: + asn1_delete_structure2(pkey_asn, ASN1_DELETE_FLAG_ZEROIZE); + gnutls_pk_params_clear(&pkey->params); + gnutls_pk_params_release(&pkey->params); + return ret; + +} + static ASN1_TYPE decode_dsa_key(const gnutls_datum_t * raw_key, gnutls_x509_privkey_t pkey) @@ -477,6 +552,7 @@ decode_dsa_key(const gnutls_datum_t * raw_key, gnutls_x509_privkey_t pkey) #define PEM_KEY_DSA_PROVABLE "FIPS186-4 DSA PRIVATE KEY" #define PEM_KEY_RSA_PROVABLE "FIPS186-4 RSA PRIVATE KEY" #define PEM_KEY_ECC "EC PRIVATE KEY" +#define PEM_KEY_EDDSA "EDDSA PRIVATE KEY" #define PEM_KEY_PKCS8 "PRIVATE KEY" #define MAX_PEM_HEADER_SIZE 25 @@ -556,6 +632,7 @@ gnutls_x509_privkey_import(gnutls_x509_privkey_t key, if (ptr != NULL) { IF_CHECK_FOR(PEM_KEY_RSA, GNUTLS_PK_RSA, ptr, begin_ptr, left, key) else IF_CHECK_FOR(PEM_KEY_ECC, GNUTLS_PK_EC, ptr, begin_ptr, left, key) + else IF_CHECK_FOR(PEM_KEY_EDDSA, GNUTLS_PK_EDDSA, ptr, begin_ptr, left, key) else IF_CHECK_FOR(PEM_KEY_DSA, GNUTLS_PK_DSA, ptr, begin_ptr, left, key) else IF_CHECK_FOR(PEM_KEY_RSA_PROVABLE, GNUTLS_PK_RSA, ptr, begin_ptr, left, key) else IF_CHECK_FOR(PEM_KEY_DSA_PROVABLE, GNUTLS_PK_DSA, ptr, begin_ptr, left, key) @@ -606,12 +683,18 @@ gnutls_x509_privkey_import(gnutls_x509_privkey_t key, key->key = decode_dsa_key(&_data, key); if (key->key == NULL) gnutls_assert(); - } else if (key->pk_algorithm == GNUTLS_PK_EC) { + } else if (key->pk_algorithm == GNUTLS_PK_ECDSA) { result = _gnutls_privkey_decode_ecc_key(&key->key, &_data, key, 0); if (result < 0) { gnutls_assert(); key->key = NULL; } + } else if (key->pk_algorithm == GNUTLS_PK_EDDSA) { + result = _gnutls_privkey_decode_eddsa_key(&key->key, &_data, key, 0); + if (result < 0) { + gnutls_assert(); + key->key = NULL; + } } else { /* Try decoding each of the keys, and accept the one that * succeeds. @@ -624,20 +707,25 @@ gnutls_x509_privkey_import(gnutls_x509_privkey_t key, key->pk_algorithm = GNUTLS_PK_DSA; key->key = decode_dsa_key(&_data, key); if (key->key == NULL) { - key->pk_algorithm = GNUTLS_PK_EC; + key->pk_algorithm = GNUTLS_PK_EDDSA; result = - _gnutls_privkey_decode_ecc_key(&key->key, &_data, key, 0); - if (result < 0) { + _gnutls_privkey_decode_eddsa_key(&key->key, &_data, key, 0); + + if (key->key == NULL) { + key->pk_algorithm = GNUTLS_PK_EC; result = - gnutls_x509_privkey_import_pkcs8(key, data, format, - NULL, - GNUTLS_PKCS_PLAIN); + _gnutls_privkey_decode_ecc_key(&key->key, &_data, key, 0); if (result < 0) { - gnutls_assert(); - key->key = NULL; + result = + gnutls_x509_privkey_import_pkcs8(key, data, format, + NULL, + GNUTLS_PKCS_PLAIN); + if (result < 0) { + gnutls_assert(); + key->key = NULL; + } } } - } } } @@ -741,9 +829,9 @@ gnutls_x509_privkey_import2(gnutls_x509_privkey_t key, if (ptr != NULL) { left = data->size - ((ptrdiff_t)ptr - (ptrdiff_t)data->data); - if (data->size - left > 15) { - ptr -= 15; - left += 15; + if (data->size - left > MAX_PEM_HEADER_SIZE) { + ptr -= MAX_PEM_HEADER_SIZE; + left += MAX_PEM_HEADER_SIZE; } else { ptr = (char*)data->data; left = data->size; @@ -758,6 +846,7 @@ gnutls_x509_privkey_import2(gnutls_x509_privkey_t key, if (ptr != NULL && left > sizeof(PEM_KEY_RSA)) { if (memcmp(ptr, PEM_KEY_RSA, sizeof(PEM_KEY_RSA)-1) == 0 || memcmp(ptr, PEM_KEY_ECC, sizeof(PEM_KEY_ECC)-1) == 0 || + memcmp(ptr, PEM_KEY_EDDSA, sizeof(PEM_KEY_EDDSA)-1) == 0 || memcmp(ptr, PEM_KEY_DSA, sizeof(PEM_KEY_DSA)-1) == 0) { head_enc = 0; } @@ -1112,32 +1201,54 @@ gnutls_x509_privkey_import_ecc_raw(gnutls_x509_privkey_t key, } key->params.flags = curve; + if (curve_is_eddsa(curve)) + key->params.algo = GNUTLS_PK_EDDSA; + else + key->params.algo = GNUTLS_PK_ECDSA; - if (_gnutls_mpi_init_scan_nz - (&key->params.params[ECC_X], x->data, x->size)) { - gnutls_assert(); - ret = GNUTLS_E_MPI_SCAN_FAILED; - goto cleanup; - } - key->params.params_nr++; + if (!curve_is_eddsa(curve)) { + if (_gnutls_mpi_init_scan_nz + (&key->params.params[ECC_X], x->data, x->size)) { + gnutls_assert(); + ret = GNUTLS_E_MPI_SCAN_FAILED; + goto cleanup; + } + key->params.params_nr++; - if (_gnutls_mpi_init_scan_nz - (&key->params.params[ECC_Y], y->data, y->size)) { - gnutls_assert(); - ret = GNUTLS_E_MPI_SCAN_FAILED; - goto cleanup; - } - key->params.params_nr++; + if (_gnutls_mpi_init_scan_nz + (&key->params.params[ECC_Y], y->data, y->size)) { + gnutls_assert(); + ret = GNUTLS_E_MPI_SCAN_FAILED; + goto cleanup; + } + key->params.params_nr++; - if (_gnutls_mpi_init_scan_nz - (&key->params.params[ECC_K], k->data, k->size)) { - gnutls_assert(); - ret = GNUTLS_E_MPI_SCAN_FAILED; - goto cleanup; - } - key->params.params_nr++; + if (_gnutls_mpi_init_scan_nz + (&key->params.params[ECC_K], k->data, k->size)) { + gnutls_assert(); + ret = GNUTLS_E_MPI_SCAN_FAILED; + goto cleanup; + } + key->params.params_nr++; + key->pk_algorithm = GNUTLS_PK_ECDSA; + } else { + if (_gnutls_mpi_init_scan_nz + (&key->params.params[EDDSA_PUB], x->data, x->size)) { + gnutls_assert(); + ret = GNUTLS_E_MPI_SCAN_FAILED; + goto cleanup; + } + key->params.params_nr++; - key->pk_algorithm = GNUTLS_PK_EC; + if (_gnutls_mpi_init_scan_nz + (&key->params.params[EDDSA_PRIV], k->data, k->size)) { + gnutls_assert(); + ret = GNUTLS_E_MPI_SCAN_FAILED; + goto cleanup; + } + key->params.params_nr++; + key->pk_algorithm = GNUTLS_PK_EDDSA; + } return 0; @@ -1215,6 +1326,8 @@ static const char *set_msg(gnutls_x509_privkey_t key) return PEM_KEY_DSA; } else if (key->pk_algorithm == GNUTLS_PK_EC) return PEM_KEY_ECC; + else if (key->pk_algorithm == GNUTLS_PK_EDDSA) + return PEM_KEY_EDDSA; else return "UNKNOWN"; } @@ -1344,6 +1457,7 @@ gnutls_sec_param_t gnutls_x509_privkey_sec_param(gnutls_x509_privkey_t key) * This function will export the ECC private key's parameters found * in the given structure. The new parameters will be allocated using * gnutls_malloc() and will be stored in the appropriate datum. + * For EdDSA keys, the @y value should be %NULL. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. @@ -1456,7 +1570,7 @@ const char const_data[20] = "onetwothreefourfive"; gnutls_datum_t ddata, tmp = {NULL,0}; char* gen_data = NULL; - if (algo == GNUTLS_PK_DSA || algo == GNUTLS_PK_EC) { + if (algo == GNUTLS_PK_DSA || algo == GNUTLS_PK_ECDSA) { unsigned hash_len; _gnutls_dsa_q_to_hash(algo, params, &hash_len); @@ -1503,7 +1617,8 @@ char* gen_data = NULL; /* Here we don't know the purpose of the key. Check both * signing and encryption. */ - case GNUTLS_PK_EC: /* we only do keys for ECDSA */ + case GNUTLS_PK_ECDSA: /* we only do keys for ECDSA */ + case GNUTLS_PK_EDDSA: /* we only do keys for ECDSA */ case GNUTLS_PK_DSA: ret = _gnutls_pk_sign(algo, &sig, &ddata, params); if (ret < 0) { @@ -1618,11 +1733,16 @@ gnutls_x509_privkey_generate2(gnutls_x509_privkey_t key, } } - if (algo == GNUTLS_PK_EC) { + if (algo_is_ecc(algo)) { if (GNUTLS_BITS_ARE_CURVE(bits)) bits = GNUTLS_BITS_TO_CURVE(bits); else - bits = _gnutls_ecc_bits_to_curve(bits); + bits = _gnutls_ecc_bits_to_curve(algo, bits); + + if (gnutls_ecc_curve_get_pk(bits) != algo) { + _gnutls_debug_log("curve is incompatible with public key algorithm\n"); + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + } } if (flags & GNUTLS_PRIVKEY_FLAG_PROVABLE) { diff --git a/lib/x509/x509_int.h b/lib/x509/x509_int.h index 9d666ee55d..1d23304aaf 100644 --- a/lib/x509/x509_int.h +++ b/lib/x509/x509_int.h @@ -219,10 +219,17 @@ int _gnutls_privkey_decode_ecc_key(ASN1_TYPE* pkey_asn, const gnutls_datum_t * raw_key, gnutls_x509_privkey_t pkey, gnutls_ecc_curve_t curve); +int _gnutls_privkey_decode_eddsa_key(ASN1_TYPE* pkey_asn, const gnutls_datum_t * + raw_key, + gnutls_x509_privkey_t pkey, + gnutls_ecc_curve_t curve); int _gnutls_x509_read_ecc_params(uint8_t * der, int dersize, unsigned int *curve); +int +_gnutls_x509_read_eddsa_params(uint8_t * der, int dersize, + unsigned int *curve); int _gnutls_asn1_encode_privkey(gnutls_pk_algorithm_t pk, ASN1_TYPE * c2, gnutls_pk_params_st * params, unsigned compat); @@ -297,6 +304,11 @@ int _gnutls_x509_write_ecc_params(gnutls_ecc_curve_t curve, int _gnutls_x509_write_ecc_pubkey(gnutls_pk_params_st * params, gnutls_datum_t * der); +int _gnutls_x509_write_eddsa_params(gnutls_ecc_curve_t curve, + gnutls_datum_t * der); +int _gnutls_x509_write_eddsa_pubkey(gnutls_pk_params_st * params, + gnutls_datum_t * der); + int _gnutls_x509_write_pubkey_params(gnutls_pk_algorithm_t algo, gnutls_pk_params_st * params, diff --git a/src/certtool-args.def b/src/certtool-args.def index 95a07b04a8..9ea9f30add 100644 --- a/src/certtool-args.def +++ b/src/certtool-args.def @@ -431,6 +431,12 @@ flag = { }; flag = { + name = eddsa; + descrip = "Generate EdDSA key"; + doc = "When combined with --generate-privkey generates an elliptic curve private key to be used with EdDSA."; +}; + +flag = { name = ecc; descrip = "Generate ECC (ECDSA) key"; doc = "When combined with --generate-privkey generates an elliptic curve private key to be used with ECDSA."; diff --git a/src/certtool-common.c b/src/certtool-common.c index 41b1655f19..f4c2a24626 100644 --- a/src/certtool-common.c +++ b/src/certtool-common.c @@ -859,14 +859,18 @@ print_ecc_pkey(FILE * outfile, gnutls_ecc_curve_t curve, fprintf(outfile, "curve:\t%s\n", gnutls_ecc_curve_get_name(curve)); - if (k) { + if (k && k->data) { print_head(outfile, "private key", k->size, cprint); print_hex_datum(outfile, k, cprint); } - print_head(outfile, "x", x->size, cprint); - print_hex_datum(outfile, x, cprint); - print_head(outfile, "y", y->size, cprint); - print_hex_datum(outfile, y, cprint); + if (x && x->data) { + print_head(outfile, "x", x->size, cprint); + print_hex_datum(outfile, x, cprint); + } + if (y && y->data) { + print_head(outfile, "y", y->size, cprint); + print_hex_datum(outfile, y, cprint); + } } diff --git a/src/certtool.c b/src/certtool.c index 7fb5f5d8fb..bbde0f4618 100644 --- a/src/certtool.c +++ b/src/certtool.c @@ -128,8 +128,12 @@ generate_private_key_int(common_info_st * cinfo) bits = get_bits(key_type, cinfo->bits, cinfo->sec_param, 1); - fprintf(stdlog, "Generating a %d bit %s private key...\n", - bits, gnutls_pk_algorithm_get_name(key_type)); + if (GNUTLS_BITS_ARE_CURVE(bits)) + fprintf(stdlog, "Generating an %s private key...\n", + gnutls_pk_algorithm_get_name(key_type)); + else + fprintf(stdlog, "Generating a %d bit %s private key...\n", + bits, gnutls_pk_algorithm_get_name(key_type)); if (bits < 256 && key_type == GNUTLS_PK_EC) fprintf(stderr, @@ -1161,7 +1165,9 @@ static void cmd_parser(int argc, char **argv) if (HAVE_OPT(DSA)) req_key_type = GNUTLS_PK_DSA; else if (HAVE_OPT(ECC)) - req_key_type = GNUTLS_PK_ECC; + req_key_type = GNUTLS_PK_ECDSA; + else if (HAVE_OPT(EDDSA)) + req_key_type = GNUTLS_PK_EDDSA; else req_key_type = GNUTLS_PK_RSA; @@ -2007,7 +2013,7 @@ static void privkey_info_int(common_info_st * cinfo, gnutls_free(q.data); gnutls_free(g.data); } - } else if (key_type == GNUTLS_PK_EC) { + } else if (key_type == GNUTLS_PK_ECDSA || key_type == GNUTLS_PK_EDDSA) { gnutls_datum_t y, x, k; gnutls_ecc_curve_t curve; diff --git a/tests/cert-tests/Makefile.am b/tests/cert-tests/Makefile.am index 630d0f1a4d..0e93b20727 100644 --- a/tests/cert-tests/Makefile.am +++ b/tests/cert-tests/Makefile.am @@ -38,7 +38,8 @@ EXTRA_DIST = ca-no-pathlen.pem no-ca-or-pathlen.pem aki-cert.pem \ template-unique.tmpl template-unique.pem dist_check_SCRIPTS = pathlen aki certtool invalid-sig email \ - pkcs7 privkey-import name-constraints certtool-long-cn crl provable-privkey + pkcs7 privkey-import name-constraints certtool-long-cn crl provable-privkey \ + ed25519 if !HAVE_BUGGY_LIBIDN dist_check_SCRIPTS += certtool-utf8 diff --git a/tests/cert-tests/ed25519 b/tests/cert-tests/ed25519 new file mode 100755 index 0000000000..d442e04e2c --- /dev/null +++ b/tests/cert-tests/ed25519 @@ -0,0 +1,81 @@ +#!/bin/sh + +# Copyright (C) 2015 Nikos Mavrogiannopoulos +# +# This file is part of GnuTLS. +# +# GnuTLS is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 3 of the License, or (at +# your option) any later version. +# +# GnuTLS is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GnuTLS; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +#set -e + +srcdir="${srcdir:-.}" +CERTTOOL="${CERTTOOL:-../../src/certtool${EXEEXT}}" +DIFF="${DIFF:-diff}" +if ! test -z "${VALGRIND}"; then + VALGRIND="${LIBTOOL:-libtool} --mode=execute ${VALGRIND} --error-exitcode=15" +fi +OUTFILE=out-ed25519.tmp +OUTFILE2=out2-ed25519.tmp + +# Verifying and existing sig +FILE="shipped-sig-verify" +${VALGRIND} "${CERTTOOL}" --p7-verify --load-certificate "${srcdir}/../../doc/credentials/x509/cert-eddsa.pem" <"pkcs7-detached.eddsa.sig" +rc=$? +if test "${rc}" != "0"; then + echo "${FILE}: PKCS7-Ed25519 struct signing failed verification" + exit ${rc} +fi + +# Test signing +FILE="signing" +${VALGRIND} "${CERTTOOL}" --p7-sign --load-privkey "${srcdir}/../../doc/credentials/x509/key-eddsa.pem" --load-certificate "${srcdir}/../../doc/credentials/x509/cert-eddsa.pem" --infile "${srcdir}/pkcs7-detached.txt" >"${OUTFILE}" +rc=$? + +if test "${rc}" != "0"; then + echo "${FILE}: PKCS7-Ed25519 struct signing failed" + exit ${rc} +fi + +FILE="signing-verify" +${VALGRIND} "${CERTTOOL}" --p7-verify --load-certificate "${srcdir}/../../doc/credentials/x509/cert-eddsa.pem" <"${OUTFILE}" +rc=$? + +if test "${rc}" != "0"; then + echo "${FILE}: PKCS7-Ed25519 struct signing failed verification" + exit ${rc} +fi + +FILE="signing-detached" +${VALGRIND} "${CERTTOOL}" --p7-detached-sign --load-privkey "${srcdir}/../../doc/credentials/x509/key-eddsa.pem" --load-certificate "${srcdir}/../../doc/credentials/x509/cert-eddsa.pem" --infile "${srcdir}/pkcs7-detached.txt" >"${OUTFILE}" +rc=$? + +if test "${rc}" != "0"; then + echo "${FILE}: PKCS7-Ed25519 struct signing-detached failed" + exit ${rc} +fi + +FILE="signing-detached-verify" +${VALGRIND} "${CERTTOOL}" --p7-verify --load-certificate "${srcdir}/../../doc/credentials/x509/cert-eddsa.pem" --load-data "${srcdir}/pkcs7-detached.txt" <"${OUTFILE}" +rc=$? + +if test "${rc}" != "0"; then + echo "${FILE}: PKCS7-Ed25519 struct signing-detached failed verification" + exit ${rc} +fi + +rm -f "${OUTFILE}" +rm -f "${OUTFILE2}" + +exit 0 diff --git a/tests/cert-tests/pkcs7-detached.eddsa.sig b/tests/cert-tests/pkcs7-detached.eddsa.sig new file mode 100644 index 0000000000..e72459722e --- /dev/null +++ b/tests/cert-tests/pkcs7-detached.eddsa.sig @@ -0,0 +1,7 @@ +-----BEGIN PKCS7----- +MIHYBgkqhkiG9w0BBwKggcowgccCAQExDTALBglghkgBZQMEAgMwKQYJKoZIhvcN +AQcBoBwEGkhlbGxvIHRoZXJlLiBIb3cgYXJlIHlvdT8KoAChADGBgzCBgAIBATAl +MBkxFzAVBgNVBAMTDkdudVRMUyBUZXN0IENBAghWA+GfAuyp2DALBglghkgBZQME +AgMwBQYDK2VlBEAHosGIoUwRhvoJsa6aPBu3syH61HFfyl9LEvBAuGag5+A1G9dK +WsQX3+hmRAMUpVDC1DDgFrYhC22lF/43OLIH +-----END PKCS7----- |