enabled both on a server and a client. It is recommended for now to disable
TLS 1.3 in setups where GOST ciphersuites are enabled on GnuTLS-based servers.
+** libgnutls: Added support for X448 key exchange (RFC 7748) and Ed448
+ signature algorithm (RFC 8032) under TLS (#984).
+
** libgnutls: The min-verification-profile from system configuration applies
for all certificate verifications, not only under TLS. The configuration can
be overriden using the GNUTLS_SYSTEM_PRIORITY_FILE environment variable.
<enumerator name='GNUTLS_MAC_AES_GMAC_192' value='206'/>
<enumerator name='GNUTLS_MAC_AES_GMAC_256' value='207'/>
<enumerator name='GNUTLS_MAC_GOST28147_TC26Z_IMIT' value='208'/>
+ <enumerator name='GNUTLS_MAC_SHAKE_128' value='209'/>
+ <enumerator name='GNUTLS_MAC_SHAKE_256' value='210'/>
</enum-decl>
<typedef-decl name='gnutls_mac_algorithm_t' type-id='type-id-50' id='type-id-38'/>
<enum-decl name='__anonymous_enum__' is-anonymous='yes' id='type-id-51'>
<enumerator name='GNUTLS_GROUP_SECP384R1' value='3'/>
<enumerator name='GNUTLS_GROUP_SECP521R1' value='4'/>
<enumerator name='GNUTLS_GROUP_X25519' value='6'/>
+ <enumerator name='GNUTLS_GROUP_X448' value='20'/>
<enumerator name='GNUTLS_GROUP_GC256A' value='16'/>
<enumerator name='GNUTLS_GROUP_GC256B' value='17'/>
<enumerator name='GNUTLS_GROUP_GC256C' value='18'/>
<enumerator name='GNUTLS_ECC_CURVE_GOST256B' value='17'/>
<enumerator name='GNUTLS_ECC_CURVE_GOST256C' value='18'/>
<enumerator name='GNUTLS_ECC_CURVE_GOST256D' value='19'/>
- <enumerator name='GNUTLS_ECC_CURVE_MAX' value='19'/>
+ <enumerator name='GNUTLS_ECC_CURVE_X448' value='20'/>
+ <enumerator name='GNUTLS_ECC_CURVE_ED448' value='21'/>
+ <enumerator name='GNUTLS_ECC_CURVE_MAX' value='21'/>
</enum-decl>
<typedef-decl name='gnutls_ecc_curve_t' type-id='type-id-71' id='type-id-66'/>
<enum-decl name='__anonymous_enum__' is-anonymous='yes' id='type-id-72'>
<enumerator name='GNUTLS_PK_GOST_01' value='8'/>
<enumerator name='GNUTLS_PK_GOST_12_256' value='9'/>
<enumerator name='GNUTLS_PK_GOST_12_512' value='10'/>
- <enumerator name='GNUTLS_PK_MAX' value='10'/>
+ <enumerator name='GNUTLS_PK_ECDH_X448' value='11'/>
+ <enumerator name='GNUTLS_PK_EDDSA_ED448' value='12'/>
+ <enumerator name='GNUTLS_PK_MAX' value='12'/>
</enum-decl>
<typedef-decl name='gnutls_pk_algorithm_t' type-id='type-id-72' id='type-id-67'/>
<typedef-decl name='gnutls_group_entry_st' type-id='type-id-62' id='type-id-73'/>
<enumerator name='GNUTLS_SIGN_GOST_94' value='43'/>
<enumerator name='GNUTLS_SIGN_GOST_256' value='44'/>
<enumerator name='GNUTLS_SIGN_GOST_512' value='45'/>
- <enumerator name='GNUTLS_SIGN_MAX' value='45'/>
+ <enumerator name='GNUTLS_SIGN_EDDSA_ED448' value='46'/>
+ <enumerator name='GNUTLS_SIGN_MAX' value='46'/>
</enum-decl>
<typedef-decl name='gnutls_sign_algorithm_t' type-id='type-id-75' id='type-id-29'/>
<class-decl name='__anonymous_struct__' size-in-bits='320' is-struct='yes' is-anonymous='yes' naming-typedef-id='type-id-76' visibility='default' id='type-id-77'>
<enumerator name='GNUTLS_DIG_GOSTR_94' value='15'/>
<enumerator name='GNUTLS_DIG_STREEBOG_256' value='16'/>
<enumerator name='GNUTLS_DIG_STREEBOG_512' value='17'/>
+ <enumerator name='GNUTLS_DIG_SHAKE_128' value='209'/>
+ <enumerator name='GNUTLS_DIG_SHAKE_256' value='210'/>
</enum-decl>
<typedef-decl name='gnutls_digest_algorithm_t' type-id='type-id-218' id='type-id-215'/>
<class-decl name='__anonymous_struct__' size-in-bits='24' is-struct='yes' is-anonymous='yes' naming-typedef-id='type-id-219' visibility='default' id='type-id-220'>
<enumerator name='GNUTLS_MAC_AES_GMAC_192' value='206'/>
<enumerator name='GNUTLS_MAC_AES_GMAC_256' value='207'/>
<enumerator name='GNUTLS_MAC_GOST28147_TC26Z_IMIT' value='208'/>
+ <enumerator name='GNUTLS_MAC_SHAKE_128' value='209'/>
+ <enumerator name='GNUTLS_MAC_SHAKE_256' value='210'/>
</enum-decl>
<typedef-decl name='gnutls_mac_algorithm_t' type-id='type-id-44' id='type-id-31'/>
<enum-decl name='__anonymous_enum__' is-anonymous='yes' id='type-id-45'>
<enumerator name='GNUTLS_GROUP_SECP384R1' value='3'/>
<enumerator name='GNUTLS_GROUP_SECP521R1' value='4'/>
<enumerator name='GNUTLS_GROUP_X25519' value='6'/>
+ <enumerator name='GNUTLS_GROUP_X448' value='20'/>
<enumerator name='GNUTLS_GROUP_GC256A' value='16'/>
<enumerator name='GNUTLS_GROUP_GC256B' value='17'/>
<enumerator name='GNUTLS_GROUP_GC256C' value='18'/>
<enumerator name='GNUTLS_ECC_CURVE_GOST256B' value='17'/>
<enumerator name='GNUTLS_ECC_CURVE_GOST256C' value='18'/>
<enumerator name='GNUTLS_ECC_CURVE_GOST256D' value='19'/>
- <enumerator name='GNUTLS_ECC_CURVE_MAX' value='19'/>
+ <enumerator name='GNUTLS_ECC_CURVE_X448' value='20'/>
+ <enumerator name='GNUTLS_ECC_CURVE_ED448' value='21'/>
+ <enumerator name='GNUTLS_ECC_CURVE_MAX' value='21'/>
</enum-decl>
<typedef-decl name='gnutls_ecc_curve_t' type-id='type-id-67' id='type-id-59'/>
<enum-decl name='__anonymous_enum__' is-anonymous='yes' id='type-id-68'>
<enumerator name='GNUTLS_PK_GOST_01' value='8'/>
<enumerator name='GNUTLS_PK_GOST_12_256' value='9'/>
<enumerator name='GNUTLS_PK_GOST_12_512' value='10'/>
- <enumerator name='GNUTLS_PK_MAX' value='10'/>
+ <enumerator name='GNUTLS_PK_ECDH_X448' value='11'/>
+ <enumerator name='GNUTLS_PK_EDDSA_ED448' value='12'/>
+ <enumerator name='GNUTLS_PK_MAX' value='12'/>
</enum-decl>
<typedef-decl name='gnutls_pk_algorithm_t' type-id='type-id-68' id='type-id-60'/>
<typedef-decl name='gnutls_group_entry_st' type-id='type-id-55' id='type-id-69'/>
<enumerator name='GNUTLS_SIGN_GOST_94' value='43'/>
<enumerator name='GNUTLS_SIGN_GOST_256' value='44'/>
<enumerator name='GNUTLS_SIGN_GOST_512' value='45'/>
- <enumerator name='GNUTLS_SIGN_MAX' value='45'/>
+ <enumerator name='GNUTLS_SIGN_EDDSA_ED448' value='46'/>
+ <enumerator name='GNUTLS_SIGN_MAX' value='46'/>
</enum-decl>
<typedef-decl name='gnutls_sign_algorithm_t' type-id='type-id-71' id='type-id-21'/>
<type-decl name='int' size-in-bits='32' id='type-id-22'/>
<enumerator name='GNUTLS_DIG_GOSTR_94' value='15'/>
<enumerator name='GNUTLS_DIG_STREEBOG_256' value='16'/>
<enumerator name='GNUTLS_DIG_STREEBOG_512' value='17'/>
+ <enumerator name='GNUTLS_DIG_SHAKE_128' value='209'/>
+ <enumerator name='GNUTLS_DIG_SHAKE_256' value='210'/>
</enum-decl>
<typedef-decl name='gnutls_digest_algorithm_t' type-id='type-id-214' id='type-id-211'/>
<class-decl name='__anonymous_struct__' size-in-bits='24' is-struct='yes' is-anonymous='yes' naming-typedef-id='type-id-215' visibility='default' id='type-id-216'>
@subsection Key generation
-All supported key types (including RSA, DSA, ECDSA, Ed25519) can be generated
+All supported key types (including RSA, DSA, ECDSA, Ed25519, Ed448) can be generated
with GnuTLS. They can be generated with the simpler @funcref{gnutls_privkey_generate}
or with the more advanced @funcref{gnutls_privkey_generate2}.
This option is only considered for TLS 1.2 and later.
@item Groups @tab
-GROUP-SECP256R1, GROUP-SECP384R1, GROUP-SECP521R1, GROUP-X25519,
+GROUP-SECP256R1, GROUP-SECP384R1, GROUP-SECP521R1, GROUP-X25519, GROUP-X448,
GROUP-FFDHE2048, GROUP-FFDHE3072, GROUP-FFDHE4096, GROUP-FFDHE6144, and
GROUP-FFDHE8192.
Groups include both elliptic curve groups, e.g., SECP256R1, as well as
@item Elliptic curves (legacy) @tab
CURVE-SECP192R1, CURVE-SECP224R1, CURVE-SECP256R1, CURVE-SECP384R1,
-CURVE-SECP521R1, and CURVE-X25519.
+CURVE-SECP521R1, CURVE-X25519, and CURVE-X448.
Catch all which enables all curves from NORMAL priority is CURVE-ALL. Note
that the CURVE keyword is kept for backwards compatibility only, for new
applications see the GROUP keyword above.
--- /dev/null
+-----BEGIN CERTIFICATE-----
+MIIChjCCAT6gAwIBAgIUcXZDPNExk2Hd9zkOd9c1QTud7Y0wDQYJKoZIhvcNAQEL
+BQAwGTEXMBUGA1UEAxMOR251VExTIFRlc3QgQ0EwIBcNMTkwNDI0MTQ1NjU4WhgP
+OTk5OTEyMzEyMzU5NTlaMAAwQzAFBgMrZXEDOgCa3d5h9mjy28CsJIdK20eiqmrV
+n6iIvcXUMHBe0HlqjDMHgrUYYHhb5j/Xmxx89Y/XKLK/PXc5UQCjgY0wgYowDAYD
+VR0TAQH/BAIwADAUBgNVHREEDTALgglsb2NhbGhvc3QwEwYDVR0lBAwwCgYIKwYB
+BQUHAwEwDwYDVR0PAQH/BAUDAweAADAdBgNVHQ4EFgQUYBo0B3El7CNa5XG8lewb
+i5oZ3PswHwYDVR0jBBgwFoAUTVa3agBY8WeS9KZ1VRuOUwED788wDQYJKoZIhvcN
+AQELBQADggExAC/syIXeeAirbS7Xwp8E4btQc/z1FbBIpTkMm+Bv9n/9SrIIoifn
+aBs3KN7UGaTSdv8dpgIGhz0eB/x8i/fceBDJxmaT0xk8pne37uMdFdVZKNnZf0zC
+bnkAr93cYWjrLpY53dZMmxBpTQWE11wDY/HjbXnYLrVAJ7g/l7Xql1t4XZ9zAPST
+Y5kTNvkh74LcFvSallzpzniFSH9b/32O3rVwgSQ5jtKqYfNrVGGsJ/Yf7DXmItK4
+7x2UR44pcIcunzZTuuhPl6LNelInuPovoJp8zsHecA8se2oYO3I0fBF3CpwdLBjE
+NKdYWrdY/y982nCqeKSJBlXuv1KJvxgKbwhRokdZlgbZDgFyWz9+dOlqL1QApB44
+A2ygsrT4MxZMGwwAp32EozNEMZZQmpnySt0=
+-----END CERTIFICATE-----
--- /dev/null
+-----BEGIN CERTIFICATE-----
+MIIChzCCAT+gAwIBAgIUIQqoC9+469QU4oVvjLFOlEXj1dowDQYJKoZIhvcNAQEL
+BQAwGTEXMBUGA1UEAxMOR251VExTIFRlc3QgQ0EwIBcNMjAwMTEzMTAyMzQwWhgP
+OTk5OTEyMzEyMzU5NTlaMBkxFzAVBgNVBAMTDmVkMjU1MTkgY2xpZW50MEMwBQYD
+K2VxAzoAbUzL5LCjH5iTXzngBUzpalQzDhz4lUsOpQvWiXG5/MusIzLkIDc8CrQK
+xBQh6UgFC7nWVrQrQB4Ao3YwdDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsG
+AQUFBwMCMA8GA1UdDwEB/wQFAwMHgAAwHQYDVR0OBBYEFIsD4KoMJwNc+Cq6lEuC
+tINDOBwDMB8GA1UdIwQYMBaAFE1Wt2oAWPFnkvSmdVUbjlMBA+/PMA0GCSqGSIb3
+DQEBCwUAA4IBMQAGt8G7QHCEsYix0G5keG8FRtbrTdPmb7FobrRp2Mxq8LOKykap
+LuCQjenVO/KOYseFGvn76NSrOpMdVef2cu4rvBdDq7Mer6bgRABugBOBTlhfrTOF
+6XjNkVjSIpOZjumD1rtYmeTGWGC437FtqDOgbVHBnIrOyxduLr6NrbtC7nnRr3px
+DTmeUG0Pa+AG9jGH25tRug+AI7Si9wTFEE1UZJdsyyliL3Rm+Br/XnYaVN/p97hL
+MUeOIgdHS6ejPiYL281zjN3H6uRbG/9Hzv2X52uAHnRWIzJDGVL1E1jt025txW/q
+toEoBRGN30M6xf1YYy7hBt6DYgZAzTdljeKPMMO/6QpiGF678uc+xoVBMlTn1bhb
+/rWiMWo03Ee1W8Ymx2H3Aj2maD8h9ovps2wx
+-----END CERTIFICATE-----
--- /dev/null
+Public Key Info:
+ Public Key Algorithm: EdDSA (Ed448)
+ Key Security Level: Ultra (456 bits)
+
+curve: Ed448
+private key:
+ f0:c4:7b:22:dd:ef:95:e4:67:bb:d7:49:43:7f:12:56
+ 44:7a:2c:53:a2:7d:1a:33:83:2f:2a:7c:54:aa:02:b5
+ ed:ad:68:39:5b:6a:e6:3a:fc:9e:7f:de:08:47:a4:9c
+ f2:ec:bc:a1:2c:04:ad:71:fa:
+
+x:
+ 6d:4c:cb:e4:b0:a3:1f:98:93:5f:39:e0:05:4c:e9:6a
+ 54:33:0e:1c:f8:95:4b:0e:a5:0b:d6:89:71:b9:fc:cb
+ ac:23:32:e4:20:37:3c:0a:b4:0a:c4:14:21:e9:48:05
+ 0b:b9:d6:56:b4:2b:40:1e:00:
+
+
+Public Key PIN:
+ pin-sha256:2Rn8YAmzw19rFmh80LoUYPsqLZq7UQWpxDmGYO+J994=
+Public Key ID:
+ sha256:d919fc6009b3c35f6b16687cd0ba1460fb2a2d9abb5105a9c4398660ef89f7de
+ sha1:8b03e0aa0c27035cf82aba944b82b48343381c03
+
+-----BEGIN PRIVATE KEY-----
+MEcCAQAwBQYDK2VxBDsEOfDEeyLd75XkZ7vXSUN/ElZEeixTon0aM4MvKnxUqgK1
+7a1oOVtq5jr8nn/eCEeknPLsvKEsBK1x+g==
+-----END PRIVATE KEY-----
--- /dev/null
+Public Key Info:
+ Public Key Algorithm: EdDSA (Ed448)
+ Key Security Level: Ultra (456 bits)
+
+curve: Ed448
+private key:
+ 0c:f8:7e:b0:94:bf:46:d1:61:bd:e3:b9:9d:1d:32:85
+ 6f:ec:fa:e0:14:23:92:cd:98:c0:91:db:20:6d:17:4b
+ bf:8e:f4:76:a9:cf:74:6d:94:30:6c:56:5f:97:ac:50
+ 79:6f:02:1e:ff:8d:77:9c:a5:
+
+x:
+ 9a:dd:de:61:f6:68:f2:db:c0:ac:24:87:4a:db:47:a2
+ aa:6a:d5:9f:a8:88:bd:c5:d4:30:70:5e:d0:79:6a:8c
+ 33:07:82:b5:18:60:78:5b:e6:3f:d7:9b:1c:7c:f5:8f
+ d7:28:b2:bf:3d:77:39:51:00:
+
+
+Public Key PIN:
+ pin-sha256:tZSB72Ha+TK+0mlTzgErm+T+WcmLAXNCqpjSbzFC8JE=
+Public Key ID:
+ sha256:b59481ef61daf932bed26953ce012b9be4fe59c98b017342aa98d26f3142f091
+ sha1:601a34077125ec235ae571bc95ec1b8b9a19dcfb
+
+-----BEGIN PRIVATE KEY-----
+MEcCAQAwBQYDK2VxBDsEOQz4frCUv0bRYb3juZ0dMoVv7PrgFCOSzZjAkdsgbRdL
+v470dqnPdG2UMGxWX5esUHlvAh7/jXecpQ==
+-----END PRIVATE KEY-----
((x)==GNUTLS_PK_GOST_12_256)|| \
((x)==GNUTLS_PK_GOST_12_512))
-#define IS_EC(x) (((x)==GNUTLS_PK_ECDSA)||((x)==GNUTLS_PK_ECDH_X25519)||((x)==GNUTLS_PK_EDDSA_ED25519))
+#define IS_EC(x) (((x)==GNUTLS_PK_ECDSA)|| \
+ ((x)==GNUTLS_PK_ECDH_X25519)||((x)==GNUTLS_PK_EDDSA_ED25519)|| \
+ ((x)==GNUTLS_PK_ECDH_X448)||((x)==GNUTLS_PK_EDDSA_ED448))
#define SIG_SEM_PRE_TLS12 (1<<1)
#define SIG_SEM_TLS13 (1<<2)
{
if (unlikely(e == NULL))
return 0;
- if (e->pk == GNUTLS_PK_EDDSA_ED25519)
+ if (e->pk == GNUTLS_PK_EDDSA_ED25519 ||
+ e->pk == GNUTLS_PK_EDDSA_ED448)
return 1;
return 0;
}
.sig_size = 64,
.supported = 1,
},
+ {
+ .name = "X448",
+ .id = GNUTLS_ECC_CURVE_X448,
+ .pk = GNUTLS_PK_ECDH_X448,
+ .size = 56,
+ .supported = 1,
+ },
+ {
+ .name = "Ed448",
+ .oid = SIG_ED448_OID,
+ .id = GNUTLS_ECC_CURVE_ED448,
+ .pk = GNUTLS_PK_EDDSA_ED448,
+ .size = 57,
+ .sig_size = 114,
+ .supported = 1,
+ },
#if ENABLE_GOST
/* Curves for usage in GOST digital signature algorithm (GOST R
* 34.10-2001/-2012) and key agreement (VKO GOST R 34.10-2001/-2012).
.tls_id = 40,
},
#endif
+ {
+ .name = "X448",
+ .id = GNUTLS_GROUP_X448,
+ .curve = GNUTLS_ECC_CURVE_X448,
+ .tls_id = 30,
+ .pk = GNUTLS_PK_ECDH_X448
+ },
#ifdef ENABLE_DHE
{
.name = "FFDHE2048",
.key_size = 32,
.block_size = 8,
.flags = GNUTLS_MAC_FLAG_CONTINUOUS_MAC},
+ {.name = "SHAKE-128",
+ .oid = HASH_OID_SHAKE_128,
+ .id = GNUTLS_MAC_SHAKE_128,
+ .block_size = 168},
+ {.name = "SHAKE-256",
+ .oid = HASH_OID_SHAKE_256,
+ .id = GNUTLS_MAC_SHAKE_256,
+ .block_size = 136},
{.name = "MAC-NULL",
.id = GNUTLS_MAC_NULL},
{0, 0, 0, 0, 0, 0, 0, 0, 0}
{GNUTLS_KX_ECDHE_RSA, GNUTLS_PK_RSA, CIPHER_SIGN},
{GNUTLS_KX_ECDHE_ECDSA, GNUTLS_PK_EC, CIPHER_SIGN},
{GNUTLS_KX_ECDHE_ECDSA, GNUTLS_PK_EDDSA_ED25519, CIPHER_SIGN},
+ {GNUTLS_KX_ECDHE_ECDSA, GNUTLS_PK_EDDSA_ED448, CIPHER_SIGN},
{GNUTLS_KX_DHE_DSS, GNUTLS_PK_DSA, CIPHER_SIGN},
{GNUTLS_KX_DHE_RSA, GNUTLS_PK_RSA_PSS, CIPHER_SIGN},
{GNUTLS_KX_ECDHE_RSA, GNUTLS_PK_RSA_PSS, CIPHER_SIGN},
.curve = GNUTLS_ECC_CURVE_INVALID },
{ .name = "EdDSA (Ed25519)", .oid = SIG_EDDSA_SHA512_OID, .id = GNUTLS_PK_EDDSA_ED25519,
.curve = GNUTLS_ECC_CURVE_ED25519, .no_prehashed = 1 },
+ { .name = "EdDSA (Ed448)", .oid = SIG_ED448_OID, .id = GNUTLS_PK_EDDSA_ED448,
+ .curve = GNUTLS_ECC_CURVE_ED448, .no_prehashed = 1 },
{ .name = "DH", .oid = NULL, .id = GNUTLS_PK_DH,
.curve = GNUTLS_ECC_CURVE_INVALID },
{ .name = "ECDH (X25519)", .oid = "1.3.101.110", .id = GNUTLS_PK_ECDH_X25519,
.curve = GNUTLS_ECC_CURVE_X25519 },
+ { .name = "ECDH (X448)", .oid = "1.3.101.111", .id = GNUTLS_PK_ECDH_X448,
+ .curve = GNUTLS_ECC_CURVE_X448 },
{ .name = "UNKNOWN", .oid = NULL, .id = GNUTLS_PK_UNKNOWN,
.curve = GNUTLS_ECC_CURVE_INVALID },
{0, 0, 0, 0}
.flags = GNUTLS_SIGN_FLAG_TLS13_OK,
.aid = {{8, 7}, SIG_SEM_DEFAULT}},
+ /* Ed448: The hash algorithm here is set to be SHAKE256, although that is
+ * an internal detail of Ed448; we set it, because CMS/PKCS#7 requires
+ * that mapping. */
+ {.name = "EdDSA-Ed448",
+ .oid = SIG_ED448_OID,
+ .id = GNUTLS_SIGN_EDDSA_ED448,
+ .pk = GNUTLS_PK_EDDSA_ED448,
+ .hash = GNUTLS_DIG_SHAKE_256,
+ .flags = GNUTLS_SIGN_FLAG_TLS13_OK,
+ .aid = {{8, 8}, SIG_SEM_DEFAULT}},
+
/* ECDSA */
/* The following three signature algorithms
* have different semantics when used under TLS 1.2
gnutls_assert();
goto cleanup;
}
- } else if (ecurve->pk == GNUTLS_PK_ECDH_X25519) {
+ } else if (ecurve->pk == GNUTLS_PK_ECDH_X25519 ||
+ ecurve->pk == GNUTLS_PK_ECDH_X448) {
if (ecurve->size != point_size)
return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
goto cleanup;
}
- /* RFC7748 requires to mask the MSB in the final byte */
+ /* RFC7748 requires to mask the MSB in the final byte
+ * for X25519 (not X448) */
if (ecurve->id == GNUTLS_ECC_CURVE_X25519) {
session->key.proto.tls12.ecdh.raw.data[point_size-1] &= 0x7f;
}
gnutls_assert();
goto cleanup;
}
- } else if (pk == GNUTLS_PK_ECDH_X25519) {
+ } else if (pk == GNUTLS_PK_ECDH_X25519 || pk == GNUTLS_PK_ECDH_X448) {
ret =
_gnutls_buffer_append_data_prefix(data, 8,
session->key.proto.tls12.ecdh.params.raw_pub.data,
if (ret < 0)
return gnutls_assert_val(ret);
- } else if (ecurve->pk == GNUTLS_PK_ECDH_X25519) {
+ } else if (ecurve->pk == GNUTLS_PK_ECDH_X25519 ||
+ ecurve->pk == GNUTLS_PK_ECDH_X448) {
if (ecurve->size != point_size)
return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
if (ret < 0)
return gnutls_assert_val(ret);
- /* RFC7748 requires to mask the MSB in the final byte */
+ /* RFC7748 requires to mask the MSB in the final byte
+ * for X25519 (not X448) */
if (ecurve->id == GNUTLS_ECC_CURVE_X25519) {
session->key.proto.tls12.ecdh.raw.data[point_size-1] &= 0x7f;
}
if (ret < 0)
return gnutls_assert_val(ret);
- } else if (group->pk == GNUTLS_PK_ECDH_X25519) {
+ } else if (group->pk == GNUTLS_PK_ECDH_X25519 ||
+ group->pk == GNUTLS_PK_ECDH_X448) {
ret =
_gnutls_buffer_append_data_prefix(data, 8,
session->key.proto.tls12.ecdh.params.raw_pub.data,
int ret;
if (group->pk != GNUTLS_PK_EC && group->pk != GNUTLS_PK_ECDH_X25519 &&
+ group->pk != GNUTLS_PK_ECDH_X448 &&
group->pk != GNUTLS_PK_DH) {
_gnutls_debug_log("Cannot send key share for group %s!\n", group->name);
return GNUTLS_E_INT_RET_0;
ret = 0;
- } else if (group->pk == GNUTLS_PK_ECDH_X25519) {
+ } else if (group->pk == GNUTLS_PK_ECDH_X25519 ||
+ group->pk == GNUTLS_PK_ECDH_X448) {
gnutls_pk_params_release(&session->key.kshare.ecdhx_params);
gnutls_pk_params_init(&session->key.kshare.ecdhx_params);
int ret;
if (group->pk != GNUTLS_PK_EC && group->pk != GNUTLS_PK_ECDH_X25519 &&
+ group->pk != GNUTLS_PK_ECDH_X448 &&
group->pk != GNUTLS_PK_DH) {
_gnutls_debug_log("Cannot send key share for group %s!\n", group->name);
return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
ret = 0;
- } else if (group->pk == GNUTLS_PK_ECDH_X25519) {
+ } else if (group->pk == GNUTLS_PK_ECDH_X25519 ||
+ group->pk == GNUTLS_PK_ECDH_X448) {
ret =
_gnutls_buffer_append_data_prefix(extdata, 16,
session->key.kshare.ecdhx_params.raw_pub.data,
ret = 0;
- } else if (group->pk == GNUTLS_PK_ECDH_X25519) {
+ } else if (group->pk == GNUTLS_PK_ECDH_X25519 ||
+ group->pk == GNUTLS_PK_ECDH_X448) {
gnutls_pk_params_st pub;
gnutls_pk_params_release(&session->key.kshare.ecdhx_params);
ret = 0;
- } else if (group->pk == GNUTLS_PK_ECDH_X25519) {
+ } else if (group->pk == GNUTLS_PK_ECDH_X25519 ||
+ group->pk == GNUTLS_PK_ECDH_X448) {
gnutls_pk_params_st pub;
curve = _gnutls_ecc_curve_get_params(group->curve);
* @GNUTLS_MAC_SHA3_384: Reserved; unimplemented.
* @GNUTLS_MAC_SHA3_512: Reserved; unimplemented.
* @GNUTLS_MAC_GOST28147_TC26Z_IMIT: The GOST 28147-89 working in IMIT mode with TC26 Z S-box.
+ * @GNUTLS_MAC_SHAKE_128: Reserved; unimplemented.
+ * @GNUTLS_MAC_SHAKE_256: Reserved; unimplemented.
*
* Enumeration of different Message Authentication Code (MAC)
* algorithms.
GNUTLS_MAC_AES_GMAC_192 = 206,
GNUTLS_MAC_AES_GMAC_256 = 207,
GNUTLS_MAC_GOST28147_TC26Z_IMIT = 208,
+ GNUTLS_MAC_SHAKE_128 = 209,
+ GNUTLS_MAC_SHAKE_256 = 210
} gnutls_mac_algorithm_t;
/**
* @GNUTLS_DIG_GOSTR_94: GOST R 34.11-94 algorithm.
* @GNUTLS_DIG_STREEBOG_256: GOST R 34.11-2001 (Streebog) algorithm, 256 bit.
* @GNUTLS_DIG_STREEBOG_512: GOST R 34.11-2001 (Streebog) algorithm, 512 bit.
+ * @GNUTLS_DIG_SHAKE_128: Reserved; unimplemented.
+ * @GNUTLS_DIG_SHAKE_256: Reserved; unimplemented.
*
* Enumeration of different digest (hash) algorithms.
*/
GNUTLS_DIG_MD5_SHA1 = GNUTLS_MAC_MD5_SHA1,
GNUTLS_DIG_GOSTR_94 = GNUTLS_MAC_GOSTR_94,
GNUTLS_DIG_STREEBOG_256 = GNUTLS_MAC_STREEBOG_256,
- GNUTLS_DIG_STREEBOG_512 = GNUTLS_MAC_STREEBOG_512
+ GNUTLS_DIG_STREEBOG_512 = GNUTLS_MAC_STREEBOG_512,
+ GNUTLS_DIG_SHAKE_128 = GNUTLS_MAC_SHAKE_128,
+ GNUTLS_DIG_SHAKE_256 = GNUTLS_MAC_SHAKE_256
/* If you add anything here, make sure you align with
gnutls_mac_algorithm_t. */
} gnutls_digest_algorithm_t;
* @GNUTLS_PK_GOST_01: GOST R 34.10-2001 algorithm per rfc5832.
* @GNUTLS_PK_GOST_12_256: GOST R 34.10-2012 algorithm, 256-bit key per rfc7091.
* @GNUTLS_PK_GOST_12_512: GOST R 34.10-2012 algorithm, 512-bit key per rfc7091.
+ * @GNUTLS_PK_ECDH_X448: Elliptic curve algorithm, restricted to ECDH as per rfc7748.
+ * @GNUTLS_PK_EDDSA_ED448: Edwards curve Digital signature algorithm. Used with SHAKE256 on signatures.
*
* Enumeration of different public-key algorithms.
*/
GNUTLS_PK_GOST_01 = 8,
GNUTLS_PK_GOST_12_256 = 9,
GNUTLS_PK_GOST_12_512 = 10,
- GNUTLS_PK_MAX = GNUTLS_PK_GOST_12_512
+ GNUTLS_PK_ECDH_X448 = 11,
+ GNUTLS_PK_EDDSA_ED448 = 12,
+ GNUTLS_PK_MAX = GNUTLS_PK_EDDSA_ED448
} gnutls_pk_algorithm_t;
* @GNUTLS_SIGN_GOST_94: Digital signature algorithm GOST R 34.10-2001 with GOST R 34.11-94
* @GNUTLS_SIGN_GOST_256: Digital signature algorithm GOST R 34.10-2012 with GOST R 34.11-2012 256 bit
* @GNUTLS_SIGN_GOST_512: Digital signature algorithm GOST R 34.10-2012 with GOST R 34.11-2012 512 bit
+ * @GNUTLS_SIGN_EDDSA_ED448: Digital signature algorithm EdDSA with Ed448 curve.
*
* Enumeration of different digital signature algorithms.
*/
GNUTLS_SIGN_GOST_94 = 43,
GNUTLS_SIGN_GOST_256 = 44,
GNUTLS_SIGN_GOST_512 = 45,
- GNUTLS_SIGN_MAX = GNUTLS_SIGN_GOST_512
+ GNUTLS_SIGN_EDDSA_ED448 = 46,
+ GNUTLS_SIGN_MAX = GNUTLS_SIGN_EDDSA_ED448
} gnutls_sign_algorithm_t;
/**
* @GNUTLS_ECC_CURVE_GOST256B: GOST R 34.10 TC26 256 B curve
* @GNUTLS_ECC_CURVE_GOST256C: GOST R 34.10 TC26 256 C curve
* @GNUTLS_ECC_CURVE_GOST256D: GOST R 34.10 TC26 256 D curve
+ * @GNUTLS_ECC_CURVE_X448: the X448 curve (ECDH only)
+ * @GNUTLS_ECC_CURVE_ED448: the Ed448 curve
*
* Enumeration of ECC curves.
*/
GNUTLS_ECC_CURVE_GOST256B,
GNUTLS_ECC_CURVE_GOST256C,
GNUTLS_ECC_CURVE_GOST256D,
- GNUTLS_ECC_CURVE_MAX = GNUTLS_ECC_CURVE_GOST256D
+ GNUTLS_ECC_CURVE_X448,
+ GNUTLS_ECC_CURVE_ED448,
+ GNUTLS_ECC_CURVE_MAX = GNUTLS_ECC_CURVE_ED448
} gnutls_ecc_curve_t;
/**
* @GNUTLS_GROUP_FFDHE4096: the FFDHE4096 group
* @GNUTLS_GROUP_FFDHE6144: the FFDHE6144 group
* @GNUTLS_GROUP_FFDHE8192: the FFDHE8192 group
+ * @GNUTLS_GROUP_X448: the X448 curve group
*
* Enumeration of supported groups. It is intended to be backwards
* compatible with the enumerations in %gnutls_ecc_curve_t for the groups
GNUTLS_GROUP_SECP384R1 = GNUTLS_ECC_CURVE_SECP384R1,
GNUTLS_GROUP_SECP521R1 = GNUTLS_ECC_CURVE_SECP521R1,
GNUTLS_GROUP_X25519 = GNUTLS_ECC_CURVE_X25519,
+ GNUTLS_GROUP_X448 = GNUTLS_ECC_CURVE_X448,
GNUTLS_GROUP_GC256A = GNUTLS_ECC_CURVE_GOST256A,
GNUTLS_GROUP_GC256B = GNUTLS_ECC_CURVE_GOST256B,
#include <nettle/ecdsa.h>
#include <nettle/ecc-curve.h>
#include <nettle/curve25519.h>
+#if HAVE_CURVE448
+#include <nettle/curve448.h>
+#else
+#include "curve448/curve448.h"
+#include "curve448/eddsa.h"
+#endif
#include <nettle/eddsa.h>
#include <nettle/version.h>
#if ENABLE_GOST
*/
#define DH_EXPONENT_SIZE(p_size) (2*_gnutls_pk_bits_to_subgroup_bits(p_size))
+static inline int
+edwards_curve_mul(gnutls_pk_algorithm_t algo,
+ uint8_t *q, const uint8_t *n, const uint8_t *p)
+{
+ switch (algo) {
+ case GNUTLS_PK_ECDH_X25519:
+ curve25519_mul(q, n, p);
+ return 0;
+ case GNUTLS_PK_ECDH_X448:
+ curve448_mul(q, n, p);
+ return 0;
+ default:
+ return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);
+ }
+}
+
/* This is used for DH or ECDH key derivation. In DH for example
* it is given the peers Y and our x, and calculates Y^x
*/
break;
}
case GNUTLS_PK_ECDH_X25519:
+ case GNUTLS_PK_ECDH_X448:
{
unsigned size = gnutls_ecc_curve_get_size(priv->curve);
out->size = size;
- curve25519_mul(out->data, priv->raw_priv.data, pub->raw_pub.data);
+ ret = edwards_curve_mul(algo, out->data, priv->raw_priv.data, pub->raw_pub.data);
+ if (ret < 0)
+ goto cleanup;
if (_gnutls_mem_is_zero(out->data, out->size)) {
gnutls_free(out->data);
return ret;
}
+static inline gnutls_ecc_curve_t
+get_eddsa_curve(gnutls_pk_algorithm_t algo)
+{
+ switch (algo) {
+ case GNUTLS_PK_EDDSA_ED25519:
+ return GNUTLS_ECC_CURVE_ED25519;
+ case GNUTLS_PK_EDDSA_ED448:
+ return GNUTLS_ECC_CURVE_ED448;
+ default:
+ return gnutls_assert_val(GNUTLS_ECC_CURVE_INVALID);
+ }
+}
+
+static inline int
+eddsa_sign(gnutls_pk_algorithm_t algo,
+ const uint8_t *pub,
+ const uint8_t *priv,
+ size_t length, const uint8_t *msg,
+ uint8_t *signature)
+{
+ switch (algo) {
+ case GNUTLS_PK_EDDSA_ED25519:
+ ed25519_sha512_sign(pub, priv, length, msg, signature);
+ return 0;
+ case GNUTLS_PK_EDDSA_ED448:
+ ed448_shake256_sign(pub, priv, length, msg, signature);
+ return 0;
+ default:
+ return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM);
+ }
+}
+
/* This is the lower-level part of privkey_sign_raw_data().
*
* It accepts data in the appropriate hash form, i.e., DigestInfo
* for PK_RSA, hash for PK_ECDSA, PK_DSA, PK_RSA_PSS, and raw data
- * for Ed25519.
+ * for Ed25519 and Ed448.
*
* in case of EC/DSA, signed data are encoded into r,s values
*/
switch (algo) {
case GNUTLS_PK_EDDSA_ED25519: /* we do EdDSA */
+ case GNUTLS_PK_EDDSA_ED448:
{
const gnutls_ecc_curve_entry_st *e;
- if (pk_params->curve != GNUTLS_ECC_CURVE_ED25519)
+ if (unlikely(get_eddsa_curve(algo) != pk_params->curve))
return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);
e = _gnutls_ecc_curve_get_params(pk_params->curve);
signature->size = e->sig_size;
- if (pk_params->raw_pub.size != e->size || pk_params->raw_priv.size != e->size)
- return gnutls_assert_val(GNUTLS_E_PK_SIGN_FAILED);
+ if (pk_params->raw_pub.size != e->size || pk_params->raw_priv.size != e->size) {
+ ret = gnutls_assert_val(GNUTLS_E_PK_SIGN_FAILED);
+ goto cleanup;
+ }
- ed25519_sha512_sign(pk_params->raw_pub.data,
- pk_params->raw_priv.data,
- vdata->size, vdata->data, signature->data);
+ ret = eddsa_sign(algo,
+ pk_params->raw_pub.data,
+ pk_params->raw_priv.data,
+ vdata->size, vdata->data,
+ signature->data);
+ if (ret < 0)
+ goto cleanup;
break;
}
return verify_func(pub, salt_size, digest, s);
}
+static inline int
+eddsa_verify(gnutls_pk_algorithm_t algo,
+ const uint8_t *pub,
+ size_t length, const uint8_t *msg,
+ const uint8_t *signature)
+{
+ int ret;
+
+ switch (algo) {
+ case GNUTLS_PK_EDDSA_ED25519:
+ ret = ed25519_sha512_verify(pub, length, msg, signature);
+ if (ret == 0)
+ return gnutls_assert_val(GNUTLS_E_PK_SIG_VERIFY_FAILED);
+ return 0;
+ case GNUTLS_PK_EDDSA_ED448:
+ ret = ed448_shake256_verify(pub, length, msg, signature);
+ if (ret == 0)
+ return gnutls_assert_val(GNUTLS_E_PK_SIG_VERIFY_FAILED);
+ return 0;
+ default:
+ return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM);
+ }
+}
+
static int
_wrap_nettle_pk_verify(gnutls_pk_algorithm_t algo,
const gnutls_datum_t * vdata,
switch (algo) {
case GNUTLS_PK_EDDSA_ED25519: /* we do EdDSA */
+ case GNUTLS_PK_EDDSA_ED448:
{
const gnutls_ecc_curve_entry_st *e;
- if (pk_params->curve != GNUTLS_ECC_CURVE_ED25519)
+ if (unlikely(get_eddsa_curve(algo) != pk_params->curve))
return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);
e = _gnutls_ecc_curve_get_params(pk_params->curve);
if (pk_params->raw_pub.size != e->size)
return gnutls_assert_val(GNUTLS_E_PK_SIGN_FAILED);
- ret = ed25519_sha512_verify(pk_params->raw_pub.data, vdata->size, vdata->data, signature->data);
- if (ret == 0) {
- gnutls_assert();
- ret = GNUTLS_E_PK_SIG_VERIFY_FAILED;
- } else {
- ret = 0;
- }
+ ret = eddsa_verify(algo,
+ pk_params->raw_pub.data,
+ vdata->size, vdata->data,
+ signature->data);
break;
}
#if ENABLE_GOST
switch (curve) {
case GNUTLS_ECC_CURVE_ED25519:
case GNUTLS_ECC_CURVE_X25519:
+ case GNUTLS_ECC_CURVE_ED448:
+ case GNUTLS_ECC_CURVE_X448:
return 1;
default:
return ((get_supported_nist_curve(curve)!=NULL ||
case GNUTLS_PK_RSA:
case GNUTLS_PK_ECDSA:
case GNUTLS_PK_EDDSA_ED25519:
+ case GNUTLS_PK_EDDSA_ED448:
#if ENABLE_GOST
case GNUTLS_PK_GOST_01:
case GNUTLS_PK_GOST_12_256:
FALLTHROUGH;
case GNUTLS_PK_EC: /* we only do keys for ECDSA */
case GNUTLS_PK_EDDSA_ED25519:
+ case GNUTLS_PK_EDDSA_ED448:
case GNUTLS_PK_DSA:
case GNUTLS_PK_RSA_PSS:
case GNUTLS_PK_GOST_01:
break;
case GNUTLS_PK_DH:
case GNUTLS_PK_ECDH_X25519:
+ case GNUTLS_PK_ECDH_X448:
ret = 0;
goto cleanup;
default:
}
#endif
+static inline int
+eddsa_public_key(gnutls_pk_algorithm_t algo,
+ uint8_t *pub, const uint8_t *priv)
+{
+ switch (algo) {
+ case GNUTLS_PK_EDDSA_ED25519:
+ ed25519_sha512_public_key(pub, priv);
+ return 0;
+ case GNUTLS_PK_EDDSA_ED448:
+ ed448_shake256_public_key(pub, priv);
+ return 0;
+ default:
+ return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM);
+ }
+}
+
+static inline int
+edwards_curve_mul_g(gnutls_pk_algorithm_t algo,
+ uint8_t *q, const uint8_t *n)
+{
+ switch (algo) {
+ case GNUTLS_PK_ECDH_X25519:
+ curve25519_mul_g(q, n);
+ return 0;
+ case GNUTLS_PK_ECDH_X448:
+ curve448_mul_g(q, n);
+ return 0;
+ default:
+ return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);
+ }
+}
+
/* To generate a DH key either q must be set in the params or
* level should be set to the number of required bits.
*/
break;
}
case GNUTLS_PK_EDDSA_ED25519:
+ case GNUTLS_PK_EDDSA_ED448:
{
unsigned size = gnutls_ecc_curve_get_size(level);
if (params->pkflags & GNUTLS_PK_FLAG_PROVABLE)
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
- if (level != GNUTLS_ECC_CURVE_ED25519)
+ if (unlikely(get_eddsa_curve(algo) != level))
return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);
if (size == 0)
params->raw_pub.size = size;
params->raw_priv.size = size;
- ed25519_sha512_public_key(params->raw_pub.data, params->raw_priv.data);
+ ret = eddsa_public_key(algo,
+ params->raw_pub.data,
+ params->raw_priv.data);
+ if (ret < 0)
+ goto fail;
break;
}
}
#endif
case GNUTLS_PK_ECDH_X25519:
+ case GNUTLS_PK_ECDH_X448:
{
unsigned size = gnutls_ecc_curve_get_size(level);
params->raw_pub.size = size;
params->raw_priv.size = size;
- curve25519_mul_g(params->raw_pub.data, params->raw_priv.data);
+ ret = edwards_curve_mul_g(algo, params->raw_pub.data, params->raw_priv.data);
+ if (ret < 0)
+ goto fail;
break;
}
default:
mpz_clear(y2);
}
break;
- case GNUTLS_PK_EDDSA_ED25519: {
- uint8_t pub[32];
+ case GNUTLS_PK_EDDSA_ED25519:
+ case GNUTLS_PK_EDDSA_ED448: {
+ gnutls_ecc_curve_t curve;
+ const gnutls_ecc_curve_entry_st *e;
+ uint8_t pub[57]; /* can accommodate both curves */
+
+ curve = get_eddsa_curve(algo);
+ e = _gnutls_ecc_curve_get_params(curve);
+ if (e == NULL)
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
if (params->raw_pub.data == NULL) {
return 0; /* nothing to verify */
}
- if (params->raw_pub.size != 32)
+ if (params->raw_pub.size != e->size)
return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
- ed25519_sha512_public_key(pub, params->raw_priv.data);
- if (memcmp(params->raw_pub.data, pub, 32) != 0)
+ ret = eddsa_public_key(algo, pub, params->raw_priv.data);
+ if (ret < 0)
+ return ret;
+
+ if (memcmp(params->raw_pub.data, pub, e->size) != 0)
return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
ret = 0;
case GNUTLS_PK_RSA_PSS:
case GNUTLS_PK_DSA:
case GNUTLS_PK_EDDSA_ED25519:
+ case GNUTLS_PK_EDDSA_ED448:
return 0;
case GNUTLS_PK_ECDSA:
{
if (ret == 0) {
return gnutls_assert_val(GNUTLS_E_PK_INVALID_PRIVKEY);
}
- } else if (algo == GNUTLS_PK_EDDSA_ED25519) {
- if (params->curve != GNUTLS_ECC_CURVE_ED25519)
+ } else if (algo == GNUTLS_PK_EDDSA_ED25519 ||
+ algo == GNUTLS_PK_EDDSA_ED448) {
+ if (unlikely(get_eddsa_curve(algo) != params->curve))
return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);
if (params->raw_priv.data == NULL)
if (params->raw_pub.data == NULL)
return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
- ed25519_sha512_public_key(params->raw_pub.data, params->raw_priv.data);
+ ret = eddsa_public_key(algo,
+ params->raw_pub.data,
+ params->raw_priv.data);
+ if (ret < 0) {
+ gnutls_free(params->raw_pub.data);
+ return ret;
+ }
+
params->raw_pub.size = params->raw_priv.size;
} else if (algo == GNUTLS_PK_RSA_PSS) {
if (params->params_nr < RSA_PRIVATE_PARAMS - 3)
case GNUTLS_PK_DSA:
case GNUTLS_PK_ECDSA:
case GNUTLS_PK_EDDSA_ED25519:
+ case GNUTLS_PK_EDDSA_ED448:
case GNUTLS_PK_GOST_01:
case GNUTLS_PK_GOST_12_256:
case GNUTLS_PK_GOST_12_512:
GNUTLS_GROUP_SECP256R1,
GNUTLS_GROUP_SECP384R1,
GNUTLS_GROUP_SECP521R1,
- GNUTLS_GROUP_X25519, /* draft-ietf-tls-rfc4492bis */
+ GNUTLS_GROUP_X25519, /* RFC 8422 */
+ GNUTLS_GROUP_X448, /* RFC 8422 */
0
};
GNUTLS_GROUP_SECP256R1,
GNUTLS_GROUP_SECP384R1,
GNUTLS_GROUP_SECP521R1,
- GNUTLS_GROUP_X25519, /* draft-ietf-tls-rfc4492bis */
+ GNUTLS_GROUP_X25519, /* RFC 8422 */
+ GNUTLS_GROUP_X448, /* RFC 8422 */
/* These should stay last as our default behavior
* is to send key shares for two top types (GNUTLS_KEY_SHARE_TOP2)
GNUTLS_GROUP_SECP256R1,
GNUTLS_GROUP_SECP384R1,
GNUTLS_GROUP_SECP521R1,
- GNUTLS_GROUP_X25519, /* draft-ietf-tls-rfc4492bis */
+ GNUTLS_GROUP_X25519, /* RFC 8422 */
+ GNUTLS_GROUP_X448, /* RFC 8422 */
GNUTLS_GROUP_FFDHE2048,
GNUTLS_GROUP_FFDHE3072,
GNUTLS_GROUP_FFDHE4096,
GNUTLS_SIGN_ECDSA_SHA384,
GNUTLS_SIGN_ECDSA_SECP384R1_SHA384,
+ GNUTLS_SIGN_EDDSA_ED448,
+
GNUTLS_SIGN_RSA_SHA512,
GNUTLS_SIGN_RSA_PSS_SHA512,
GNUTLS_SIGN_RSA_PSS_RSAE_SHA512,
GNUTLS_SIGN_RSA_PSS_RSAE_SHA256,
GNUTLS_SIGN_ECDSA_SHA256,
GNUTLS_SIGN_ECDSA_SECP256R1_SHA256,
+
GNUTLS_SIGN_EDDSA_ED25519,
GNUTLS_SIGN_RSA_SHA384,
GNUTLS_SIGN_ECDSA_SHA384,
GNUTLS_SIGN_ECDSA_SECP384R1_SHA384,
+ GNUTLS_SIGN_EDDSA_ED448,
+
GNUTLS_SIGN_RSA_SHA512,
GNUTLS_SIGN_RSA_PSS_SHA512,
GNUTLS_SIGN_RSA_PSS_RSAE_SHA512,
break;
case GNUTLS_PK_EDDSA_ED25519:
+ case GNUTLS_PK_EDDSA_ED448:
ret = _gnutls_set_datum(&pub->raw_pub, priv->raw_pub.data, priv->raw_pub.size);
if (ret < 0)
return gnutls_assert_val(ret);
return _gnutls_mpi_get_nbits(params->params[DSA_P]);
case GNUTLS_PK_ECDSA:
case GNUTLS_PK_EDDSA_ED25519:
+ case GNUTLS_PK_EDDSA_ED448:
case GNUTLS_PK_GOST_01:
case GNUTLS_PK_GOST_12_256:
case GNUTLS_PK_GOST_12_512:
if (hash)
*hash = GNUTLS_DIG_SHA512;
+ ret = 0;
+ break;
+ case GNUTLS_PK_EDDSA_ED448:
+ if (hash)
+ *hash = GNUTLS_DIG_SHAKE_256;
+
ret = 0;
break;
case GNUTLS_PK_GOST_01:
if (curve)
*curve = key->params.curve;
- if (key->params.algo == GNUTLS_PK_EDDSA_ED25519) {
+ if (key->params.algo == GNUTLS_PK_EDDSA_ED25519 ||
+ key->params.algo == GNUTLS_PK_EDDSA_ED448) {
if (x) {
ret = _gnutls_set_datum(x, key->params.raw_pub.data, key->params.raw_pub.size);
if (ret < 0)
goto cleanup;
}
- key->params.algo = GNUTLS_PK_EDDSA_ED25519;
+ switch (curve) {
+ case GNUTLS_ECC_CURVE_ED25519:
+ key->params.algo = GNUTLS_PK_EDDSA_ED25519;
+ break;
+ case GNUTLS_ECC_CURVE_ED448:
+ key->params.algo = GNUTLS_PK_EDDSA_ED448;
+ break;
+ default:
+ break;
+ }
key->params.curve = curve;
key->bits = pubkey_to_bits(&key->params);
break;
case GNUTLS_PK_EDDSA_ED25519:
+ case GNUTLS_PK_EDDSA_ED448:
if (_gnutls_pk_verify(se->pk, data, signature, params, sign_params) != 0) {
gnutls_assert();
return GNUTLS_E_PK_SIG_VERIFY_FAILED;
#define SIG_RSA_SHA3_512_OID "2.16.840.1.101.3.4.3.16"
#define SIG_EDDSA_SHA512_OID "1.3.101.112"
+#define SIG_ED448_OID "1.3.101.113"
#define XMPP_OID "1.3.6.1.5.5.7.8.5"
#define KRB5_PRINCIPAL_OID "1.3.6.1.5.2.2"
case GNUTLS_PK_EDDSA_ED25519:
ret = _gnutls_x509_read_eddsa_pubkey(GNUTLS_ECC_CURVE_ED25519, der, dersize, params);
break;
+ case GNUTLS_PK_EDDSA_ED448:
+ ret = _gnutls_x509_read_eddsa_pubkey(GNUTLS_ECC_CURVE_ED448, der, dersize, params);
+ break;
case GNUTLS_PK_GOST_01:
case GNUTLS_PK_GOST_12_256:
case GNUTLS_PK_GOST_12_512:
switch (algo) {
case GNUTLS_PK_RSA:
case GNUTLS_PK_EDDSA_ED25519:
+ case GNUTLS_PK_EDDSA_ED448:
return 0;
case GNUTLS_PK_RSA_PSS:
return _gnutls_x509_read_rsa_pss_params(der, dersize, ¶ms->spki);
case GNUTLS_PK_DSA:
case GNUTLS_PK_ECDSA:
case GNUTLS_PK_EDDSA_ED25519:
+ case GNUTLS_PK_EDDSA_ED448:
case GNUTLS_PK_GOST_01:
case GNUTLS_PK_GOST_12_256:
case GNUTLS_PK_GOST_12_512:
if (params->raw_pub.size == 0)
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
- if (params->curve != GNUTLS_ECC_CURVE_ED25519)
+ if (params->curve != GNUTLS_ECC_CURVE_ED25519 &&
+ params->curve != GNUTLS_ECC_CURVE_ED448)
return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);
ret = _gnutls_set_datum(raw, params->raw_pub.data, params->raw_pub.size);
case GNUTLS_PK_ECDSA:
return _gnutls_x509_write_ecc_params(params->curve, der);
case GNUTLS_PK_EDDSA_ED25519:
+ case GNUTLS_PK_EDDSA_ED448:
der->data = NULL;
der->size = 0;
case GNUTLS_PK_ECDSA:
return _gnutls_x509_write_ecc_pubkey(params, der);
case GNUTLS_PK_EDDSA_ED25519:
+ case GNUTLS_PK_EDDSA_ED448:
return _gnutls_x509_write_eddsa_pubkey(params, der);
case GNUTLS_PK_GOST_01:
case GNUTLS_PK_GOST_12_256:
return _gnutls_asn1_encode_dsa(c2, params);
case GNUTLS_PK_ECDSA:
case GNUTLS_PK_EDDSA_ED25519:
+ case GNUTLS_PK_EDDSA_ED448:
return _gnutls_asn1_encode_ecc(c2, params);
case GNUTLS_PK_GOST_01:
case GNUTLS_PK_GOST_12_256:
_asnstr_append_name(name, sizeof(name), root,
".algorithm.parameters");
- if (pk_algorithm != GNUTLS_PK_RSA && pk_algorithm != GNUTLS_PK_EDDSA_ED25519 && pk_algorithm != GNUTLS_PK_ECDH_X25519) {
+ if (pk_algorithm != GNUTLS_PK_RSA &&
+ pk_algorithm != GNUTLS_PK_EDDSA_ED25519 && pk_algorithm != GNUTLS_PK_ECDH_X25519 &&
+ pk_algorithm != GNUTLS_PK_EDDSA_ED448 && pk_algorithm != GNUTLS_PK_ECDH_X448) {
/* RSA and EdDSA do not use parameters */
result = _gnutls_x509_read_value(asn, name, &tmp);
if (pk_algorithm == GNUTLS_PK_RSA_PSS &&
break;
case GNUTLS_PK_EDDSA_ED25519:
+ case GNUTLS_PK_EDDSA_ED448:
case GNUTLS_PK_ECDSA:
{
gnutls_datum_t x, y;
if (curve_is_eddsa(curve)) {
unsigned size;
- key->params.algo = GNUTLS_PK_EDDSA_ED25519;
+ switch (curve) {
+ case GNUTLS_ECC_CURVE_ED25519:
+ key->params.algo = GNUTLS_PK_EDDSA_ED25519;
+ break;
+ case GNUTLS_ECC_CURVE_ED448:
+ key->params.algo = GNUTLS_PK_EDDSA_ED448;
+ break;
+ default:
+ ret = gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+ goto cleanup;
+ }
size = gnutls_ecc_curve_get_size(curve);
if (x->size != size || k->size != size) {
switch (pkey->params.algo) {
case GNUTLS_PK_EDDSA_ED25519:
+ case GNUTLS_PK_EDDSA_ED448:
/* 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,
return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
}
gnutls_free(pkey->params.raw_priv.data);
- pkey->params.algo = GNUTLS_PK_EDDSA_ED25519;
+ switch (curve) {
+ case GNUTLS_ECC_CURVE_ED25519:
+ pkey->params.algo = GNUTLS_PK_EDDSA_ED25519;
+ break;
+ case GNUTLS_ECC_CURVE_ED448:
+ pkey->params.algo = GNUTLS_PK_EDDSA_ED448;
+ 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;
result = _decode_pkcs8_ecc_key(pkcs8_asn, pkey);
break;
case GNUTLS_PK_EDDSA_ED25519:
+ case GNUTLS_PK_EDDSA_ED448:
result = _decode_pkcs8_eddsa_key(pkcs8_asn, pkey, oid);
break;
case GNUTLS_PK_GOST_01:
#define HASH_OID_SHA3_256 "2.16.840.1.101.3.4.2.8"
#define HASH_OID_SHA3_384 "2.16.840.1.101.3.4.2.9"
#define HASH_OID_SHA3_512 "2.16.840.1.101.3.4.2.10"
+#define HASH_OID_SHAKE_128 "2.16.840.1.101.3.4.2.11"
+#define HASH_OID_SHAKE_256 "2.16.840.1.101.3.4.2.12"
#define HASH_OID_GOST_R_3411_94 "1.2.643.2.2.9"
#define HASH_OID_STREEBOG_256 "1.2.643.7.1.1.2.2"
#define HASH_OID_STREEBOG_512 "1.2.643.7.1.1.2.3"
arg-type = string;
descrip = "Specify the key type to use on key generation";
doc = "This option can be combined with --generate-privkey, to specify
-the key type to be generated. Valid options are, 'rsa', 'rsa-pss', 'dsa', 'ecdsa', and 'ed25519'.
+the key type to be generated. Valid options are, 'rsa', 'rsa-pss', 'dsa', 'ecdsa', 'ed25519, and 'ed448'.'.
When combined with certificate generation it can be used to specify an
RSA-PSS certificate when an RSA key is given.";
};
gnutls_free(q.data);
gnutls_free(g.data);
}
- } else if (key_type == GNUTLS_PK_ECDSA || key_type == GNUTLS_PK_EDDSA_ED25519) {
+ } else if (key_type == GNUTLS_PK_ECDSA ||
+ key_type == GNUTLS_PK_EDDSA_ED25519 ||
+ key_type == GNUTLS_PK_EDDSA_ED448) {
gnutls_datum_t y, x, k;
gnutls_ecc_curve_t curve;
return GNUTLS_PK_RSA_PSS;
else if (strcasecmp(key_type, "ed25519") == 0 || strcasecmp(key_type, "eddsa") == 0)
return GNUTLS_PK_EDDSA_ED25519;
+ else if (strcasecmp(key_type, "ed448") == 0)
+ return GNUTLS_PK_EDDSA_ED448;
else if (strcasecmp(key_type, "dsa") == 0)
return GNUTLS_PK_DSA;
else if (strcasecmp(key_type, "ecdsa") == 0 || strcasecmp(key_type, "ecc") == 0)
if (cinfo->pkcs8)
return;
- if (key_type == GNUTLS_PK_RSA_PSS || key_type == GNUTLS_PK_EDDSA_ED25519 ||
+ if (key_type == GNUTLS_PK_RSA_PSS || key_type == GNUTLS_PK_EDDSA_ED25519 || key_type == GNUTLS_PK_EDDSA_ED448 ||
key_type == GNUTLS_PK_GOST_01 || key_type == GNUTLS_PK_GOST_12_256 ||
key_type == GNUTLS_PK_GOST_12_512) {
if (cinfo->verbose)
if (key_type == GNUTLS_PK_ECDSA ||
key_type == GNUTLS_PK_EDDSA_ED25519 ||
+ key_type == GNUTLS_PK_EDDSA_ED448 ||
key_type == GNUTLS_PK_GOST_01 ||
key_type == GNUTLS_PK_GOST_12_256 ||
key_type == GNUTLS_PK_GOST_12_512) {
check_unique_non_null(gnutls_ecc_curve_get_name(i));
if (i == GNUTLS_ECC_CURVE_X25519)
continue; /* no oid yet */
+ if (i == GNUTLS_ECC_CURVE_X448)
+ continue; /* no oid yet */
check_unique_non_null(gnutls_ecc_curve_get_oid(i));
}
gnutls_datum_t signature;
gnutls_digest_algorithm_t digest;
- if (algorithm == GNUTLS_PK_EDDSA_ED25519)
- digest = GNUTLS_DIG_SHA512;
- else if (algorithm == GNUTLS_PK_GOST_01)
- digest = GNUTLS_DIG_GOSTR_94;
- else if (algorithm == GNUTLS_PK_GOST_12_256)
- digest = GNUTLS_DIG_STREEBOG_256;
- else if (algorithm == GNUTLS_PK_GOST_12_512)
- digest = GNUTLS_DIG_STREEBOG_512;
- else
- digest = GNUTLS_DIG_SHA256;
-
- /* sign arbitrary data */
assert(gnutls_privkey_init(&privkey) >= 0);
ret = gnutls_privkey_import_x509(privkey, pkey, 0);
if (ret < 0)
fail("gnutls_privkey_import_x509\n");
- ret = gnutls_privkey_sign_data(privkey, digest, 0,
- &raw_data, &signature);
- if (ret < 0)
- fail("gnutls_x509_privkey_sign_data\n");
-
- /* verify data */
assert(gnutls_pubkey_init(&pubkey) >= 0);
ret = gnutls_pubkey_import_privkey(pubkey, privkey, 0, 0);
if (ret < 0)
fail("gnutls_pubkey_import_privkey\n");
+ ret = gnutls_pubkey_get_preferred_hash_algorithm (pubkey, &digest, NULL);
+ if (ret < 0)
+ fail("gnutls_pubkey_get_preferred_hash_algorithm\n");
+
+ /* sign arbitrary data */
+ ret = gnutls_privkey_sign_data(privkey, digest, 0,
+ &raw_data, &signature);
+ if (ret < 0)
+ fail("gnutls_privkey_sign_data\n");
+
+ /* verify data */
ret = gnutls_pubkey_verify_data2(pubkey, gnutls_pk_to_sign(gnutls_pubkey_get_pk_algorithm(pubkey, NULL),digest),
0, &raw_data, &signature);
if (ret < 0)
for (algorithm = GNUTLS_PK_RSA; algorithm <= GNUTLS_PK_MAX;
algorithm++) {
if (algorithm == GNUTLS_PK_DH ||
- algorithm == GNUTLS_PK_ECDH_X25519)
+ algorithm == GNUTLS_PK_ECDH_X25519 ||
+ algorithm == GNUTLS_PK_ECDH_X448)
continue;
if (algorithm == GNUTLS_PK_GOST_01 ||
ED25519_CLI_CERT="${srcdir}/../../doc/credentials/x509/clicert-ed25519.pem"
ED25519_CLI_KEY="${srcdir}/../../doc/credentials/x509/clikey-ed25519.pem"
+ED448_CLI_CERT="${srcdir}/../../doc/credentials/x509/clicert-ed448.pem"
+ED448_CLI_KEY="${srcdir}/../../doc/credentials/x509/clikey-ed448.pem"
+
RSA_PSS_CERT="${srcdir}/../../doc/credentials/x509/cert-rsa-pss.pem"
RSA_PSS_KEY="${srcdir}/../../doc/credentials/x509/key-rsa-pss.pem"
ED25519_CERT="${srcdir}/../../doc/credentials/x509/cert-ed25519.pem"
ED25519_KEY="${srcdir}/../../doc/credentials/x509/key-ed25519.pem"
+ED448_CERT="${srcdir}/../../doc/credentials/x509/cert-ed448.pem"
+ED448_KEY="${srcdir}/../../doc/credentials/x509/key-ed448.pem"
+
ECC_CERT="${srcdir}/../../doc/credentials/x509/cert-ecc.pem"
ECC_KEY="${srcdir}/../../doc/credentials/x509/key-ecc.pem"
kill ${PID}
wait
+ echo_cmd "${PREFIX}Checking TLS 1.3 with Ed448 certificate..."
+ eval "${GETPORT}"
+ launch_bare_server $$ s_server -quiet -www -accept "${PORT}" -keyform pem -certform pem ${OPENSSL_DH_PARAMS_OPT} -key "${ED448_KEY}" -cert "${ED448_CERT}" -CAfile "${CA_CERT}"
+ PID=$!
+ wait_server ${PID}
+
+ ${VALGRIND} "${CLI}" ${DEBUG} -p "${PORT}" 127.0.0.1 --priority "NORMAL:-VERS-ALL:+VERS-TLS1.3${ADD}" --insecure </dev/null >>${OUTPUT} || \
+ fail ${PID} "Failed"
+
+ kill ${PID}
+ wait
+
echo_cmd "${PREFIX}Checking TLS 1.3 with secp256r1 certificate..."
eval "${GETPORT}"
launch_bare_server $$ s_server -quiet -www -accept "${PORT}" -keyform pem -certform pem ${OPENSSL_DH_PARAMS_OPT} -key "${ECC_KEY}" -cert "${ECC_CERT}" -CAfile "${CA_CERT}"
wait
done
- for i in GROUP-X25519 GROUP-SECP256R1 GROUP-SECP384R1 GROUP-SECP521R1;do
+ GROUPS="GROUP-X25519 GROUP-X448 GROUP-SECP256R1 GROUP-SECP384R1 GROUP-SECP521R1"
+ for i in $GROUPS;do
echo_cmd "${PREFIX}Checking TLS 1.3 with ${i}..."
eval "${GETPORT}"
${OPENSSL_CLI} s_client -host localhost -port "${PORT}" -cert "${ED25519_CLI_CERT}" -key "${ED25519_CLI_KEY}" -CAfile "${CA_CERT}" </dev/null 2>&1 | grep "\:error\:" && \
fail ${PID} "Failed"
+ echo_cmd "${PREFIX}Checking TLS 1.3 with Ed448 client certificate..."
+ ${OPENSSL_CLI} s_client -host localhost -port "${PORT}" -cert "${ED448_CLI_CERT}" -key "${ED448_CLI_KEY}" -CAfile "${CA_CERT}" </dev/null 2>&1 | grep "\:error\:" && \
+ fail ${PID} "Failed"
+
kill ${PID}
wait
kill ${PID}
wait
+ echo_cmd "${PREFIX}Checking TLS 1.3 with Ed448 certificate..."
+
+ eval "${GETPORT}"
+ launch_server $$ --priority "NORMAL:-VERS-ALL:+VERS-TLS1.3${ADD}" --x509certfile "${ED448_CERT}" --x509keyfile "${ED448_KEY}" --x509cafile "${CA_CERT}" >>${OUTPUT} 2>&1
+ PID=$!
+ wait_server ${PID}
+
+ ${OPENSSL_CLI} s_client -host localhost -port "${PORT}" -cert "${CLI_CERT}" -key "${CLI_KEY}" -CAfile "${CA_CERT}" </dev/null 2>&1 | grep "\:error\:" && \
+ fail ${PID} "Failed"
+
+ kill ${PID}
+ wait
+
echo_cmd "${PREFIX}Checking TLS 1.3 with secp256r1 certificate..."
eval "${GETPORT}"