]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
algorithms: implement X448 key exchange and Ed448 signature scheme
authorDaiki Ueno <dueno@redhat.com>
Mon, 22 Apr 2019 06:27:43 +0000 (08:27 +0200)
committerDaiki Ueno <dueno@redhat.com>
Thu, 23 Jan 2020 06:07:22 +0000 (07:07 +0100)
Signed-off-by: Daiki Ueno <dueno@redhat.com>
39 files changed:
NEWS
devel/libdane-latest-x86_64.abi
devel/libgnutls-latest-x86_64.abi
doc/cha-crypto.texi
doc/cha-gtls-app.texi
doc/credentials/x509/cert-ed448.pem [new file with mode: 0644]
doc/credentials/x509/clicert-ed448.pem [new file with mode: 0644]
doc/credentials/x509/clikey-ed448.pem [new file with mode: 0644]
doc/credentials/x509/key-ed448.pem [new file with mode: 0644]
lib/algorithms.h
lib/algorithms/ecc.c
lib/algorithms/groups.c
lib/algorithms/mac.c
lib/algorithms/publickey.c
lib/algorithms/sign.c
lib/auth/ecdhe.c
lib/ext/key_share.c
lib/includes/gnutls/gnutls.h.in
lib/nettle/pk.c
lib/pk.c
lib/priority.c
lib/privkey.c
lib/pubkey.c
lib/x509/common.h
lib/x509/key_decode.c
lib/x509/key_encode.c
lib/x509/mpi.c
lib/x509/output.c
lib/x509/privkey.c
lib/x509/privkey_pkcs8.c
lib/x509/x509_int.h
src/certtool-args.def
src/certtool-common.c
src/certtool-common.h
src/certtool.c
tests/gnutls-strcodes.c
tests/privkey-keygen.c
tests/suite/testcompat-common
tests/suite/testcompat-tls13-openssl.sh

diff --git a/NEWS b/NEWS
index fdc94fc88d5fc99a0b327a5f9b9b3b3589b50291..3b977c6c20df62d8ebe5d88e975f0f725b7e49e1 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -27,6 +27,9 @@ See the end for copying conditions.
    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.
index ad8a13635250b8a5ab4ab25ec11fb6c2ccd6cded..9e66a95bee927118b20739ed77d976c7bbc9e4c7 100644 (file)
       <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'>
index bf45d3c5b11c90c94e2a88620954e57aa83340ce..cab31da9a8188e2a55029a4441c132333f4b31f8 100644 (file)
       <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'>
index da2ce2052898f7a7f470e5cb134169ff7b0a669a..5fad4fdf6e3a249906d58395ad49753292c3ac50 100644 (file)
@@ -90,7 +90,7 @@ structures functions such as @funcref{gnutls_privkey_set_pin_function}.
 
 @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}.
 
index 75ac509e342da15f7820f866bf8c91c87e8a4a4d..ab82f14aad1d37956f15f29f68b6a40927a707b4 100644 (file)
@@ -1462,7 +1462,7 @@ Shortcut which enables secure GOST algorithms is SIGN-GOST-ALL.
 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 
@@ -1473,7 +1473,7 @@ to finite fields (DH), GOST curves and generic elliptic curves.
 
 @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.
diff --git a/doc/credentials/x509/cert-ed448.pem b/doc/credentials/x509/cert-ed448.pem
new file mode 100644 (file)
index 0000000..5633c1c
--- /dev/null
@@ -0,0 +1,16 @@
+-----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-----
diff --git a/doc/credentials/x509/clicert-ed448.pem b/doc/credentials/x509/clicert-ed448.pem
new file mode 100644 (file)
index 0000000..1040542
--- /dev/null
@@ -0,0 +1,16 @@
+-----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-----
diff --git a/doc/credentials/x509/clikey-ed448.pem b/doc/credentials/x509/clikey-ed448.pem
new file mode 100644 (file)
index 0000000..3ccb704
--- /dev/null
@@ -0,0 +1,28 @@
+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-----
diff --git a/doc/credentials/x509/key-ed448.pem b/doc/credentials/x509/key-ed448.pem
new file mode 100644 (file)
index 0000000..9f15dbd
--- /dev/null
@@ -0,0 +1,28 @@
+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-----
index fadf2698713267887d87350df0164150a1360c23..c68a266cc99f7a447df1a2dfc110ac1e0d94f1d5 100644 (file)
@@ -44,7 +44,9 @@
                      ((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)
@@ -450,7 +452,8 @@ inline static int _curve_is_eddsa(const gnutls_ecc_curve_entry_st * e)
 {
        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;
 }
index 8b4b78f67d03f138a3537d9947d303a8582e80eb..14351b87add4059e6c472a3be8fc46aa36bcc84f 100644 (file)
@@ -96,6 +96,22 @@ gnutls_ecc_curve_entry_st ecc_curves[] = {
         .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).
index 6e1326666a586a4951587d2b2c6804f5a550fb2e..d4b77beb2a577c3702f390399ed1f47d57b1445a 100644 (file)
@@ -125,6 +125,13 @@ static const gnutls_group_entry_st supported_groups[] = {
         .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",
index 376c76df064cbbb75455e5617bd33f39716028ad..edd6e10acc7db98d335928ff89358467ef71d039 100644 (file)
@@ -183,6 +183,14 @@ mac_entry_st hash_algorithms[] = {
         .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}
index dc535c2f6527f693aea523f3d98380680c065928..c298a38936227d6f638a7d1cd4d832dc9196b53f 100644 (file)
@@ -51,6 +51,7 @@ static const gnutls_pk_map pk_mappings[] = {
        {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},
@@ -141,10 +142,14 @@ static const gnutls_pk_entry pk_algorithms[] = {
           .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}
index 167c5fb51b7a9449cb30301151c7915932e398a7..9c95e388aef98b1882e0f5f381d65cc1bcc465b4 100644 (file)
@@ -125,6 +125,17 @@ gnutls_sign_entry_st sign_algorithms[] = {
         .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
index 8c20d6c1cc164c4d0708788f3fbd7ed08f0c6a71..883f6cd04692dfc50f760183d338549645cb5c4b 100644 (file)
@@ -172,7 +172,8 @@ int _gnutls_proc_ecdh_common_client_kx(gnutls_session_t session,
                        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);
 
@@ -183,7 +184,8 @@ int _gnutls_proc_ecdh_common_client_kx(gnutls_session_t session,
                        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;
                }
@@ -282,7 +284,7 @@ _gnutls_gen_ecdh_common_client_kx_int(gnutls_session_t session,
                        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,
@@ -382,7 +384,8 @@ _gnutls_proc_ecdh_common_server_kx(gnutls_session_t session,
                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);
 
@@ -391,7 +394,8 @@ _gnutls_proc_ecdh_common_server_kx(gnutls_session_t session,
                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;
                }
@@ -462,7 +466,8 @@ int _gnutls_ecdh_common_print_server_kx(gnutls_session_t session,
                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,
index 4ae12c96b567a337aa43f06867e3f47fd1b8b766..41dd1b73261a789cf59abf473b659280d2f6d532 100644 (file)
@@ -75,6 +75,7 @@ static int client_gen_key_share(gnutls_session_t session, const gnutls_group_ent
        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;
@@ -115,7 +116,8 @@ static int client_gen_key_share(gnutls_session_t session, const gnutls_group_ent
 
                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);
 
@@ -195,6 +197,7 @@ static int server_gen_key_share(gnutls_session_t session, const gnutls_group_ent
        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;
@@ -224,7 +227,8 @@ static int server_gen_key_share(gnutls_session_t session, const gnutls_group_ent
 
                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,
@@ -300,7 +304,8 @@ server_use_key_share(gnutls_session_t session, const gnutls_group_entry_st *grou
 
                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);
@@ -438,7 +443,8 @@ client_use_key_share(gnutls_session_t session, const gnutls_group_entry_st *grou
 
                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);
index 1d0f924c2604780b4a41bc16e2a753e96807757a..3f6faa2ec01c20faead8d8569c0bfa9735944f58 100644 (file)
@@ -294,6 +294,8 @@ typedef enum {
  * @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.
@@ -328,6 +330,8 @@ typedef enum {
        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;
 
 /**
@@ -350,6 +354,8 @@ typedef enum {
  * @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.
  */
@@ -371,7 +377,9 @@ typedef enum {
        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;
@@ -833,6 +841,8 @@ typedef enum gnutls_certificate_print_formats {
  * @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.
  */
@@ -848,7 +858,9 @@ typedef enum {
        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;
 
 
@@ -912,6 +924,7 @@ const char *gnutls_pk_algorithm_get_name(gnutls_pk_algorithm_t algorithm);
  * @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.
  */
@@ -968,7 +981,8 @@ typedef enum {
        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;
 
 /**
@@ -993,6 +1007,8 @@ typedef enum {
  * @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.
  */
@@ -1017,7 +1033,9 @@ typedef enum {
        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;
 
 /**
@@ -1041,6 +1059,7 @@ typedef enum {
  * @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
@@ -1054,6 +1073,7 @@ typedef enum {
        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,
index 823c9b98094ec2b1231fae3203d83f4b6fe38c51..4be8dc7edaeb8def7eb787b3746bad61b36eafbf 100644 (file)
 #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
@@ -235,6 +241,22 @@ ecc_shared_secret(struct ecc_scalar *private_key,
  */
 #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
  */
@@ -388,6 +410,7 @@ dh_cleanup:
                        break;
                }
        case GNUTLS_PK_ECDH_X25519:
+       case GNUTLS_PK_ECDH_X448:
                {
                        unsigned size = gnutls_ecc_curve_get_size(priv->curve);
 
@@ -407,7 +430,9 @@ dh_cleanup:
 
                        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);
@@ -739,11 +764,43 @@ _rsa_pss_sign_digest_tr(gnutls_digest_algorithm_t dig,
        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
  */
@@ -774,10 +831,11 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo,
 
        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);
@@ -792,12 +850,18 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo,
 
                        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;
                }
@@ -1130,6 +1194,30 @@ _rsa_pss_verify_digest(gnutls_digest_algorithm_t dig,
        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,
@@ -1149,10 +1237,11 @@ _wrap_nettle_pk_verify(gnutls_pk_algorithm_t algo,
 
        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);
@@ -1165,13 +1254,10 @@ _wrap_nettle_pk_verify(gnutls_pk_algorithm_t algo,
                        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
@@ -1431,6 +1517,8 @@ static int _wrap_nettle_pk_curve_exists(gnutls_ecc_curve_t curve)
        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 ||
@@ -1556,6 +1644,7 @@ wrap_nettle_pk_generate_params(gnutls_pk_algorithm_t algo,
        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:
@@ -1914,6 +2003,7 @@ gnutls_x509_spki_st spki;
                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:
@@ -1934,6 +2024,7 @@ gnutls_x509_spki_st spki;
                break;
        case GNUTLS_PK_DH:
        case GNUTLS_PK_ECDH_X25519:
+       case GNUTLS_PK_ECDH_X448:
                ret = 0;
                goto cleanup;
        default:
@@ -1953,6 +2044,38 @@ cleanup:
 }
 #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.
  */
@@ -2190,13 +2313,14 @@ wrap_nettle_pk_generate_keys(gnutls_pk_algorithm_t algo,
                        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)
@@ -2222,7 +2346,11 @@ wrap_nettle_pk_generate_keys(gnutls_pk_algorithm_t algo,
                        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;
                }
@@ -2335,6 +2463,7 @@ wrap_nettle_pk_generate_keys(gnutls_pk_algorithm_t algo,
                }
 #endif
        case GNUTLS_PK_ECDH_X25519:
+       case GNUTLS_PK_ECDH_X448:
                {
                        unsigned size = gnutls_ecc_curve_get_size(level);
 
@@ -2361,7 +2490,9 @@ wrap_nettle_pk_generate_keys(gnutls_pk_algorithm_t algo,
                        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:
@@ -2595,18 +2726,29 @@ wrap_nettle_pk_verify_priv_params(gnutls_pk_algorithm_t algo,
                        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;
@@ -2707,6 +2849,7 @@ wrap_nettle_pk_verify_pub_params(gnutls_pk_algorithm_t algo,
        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:
                {
@@ -2892,8 +3035,9 @@ wrap_nettle_pk_fixup(gnutls_pk_algorithm_t algo,
                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)
@@ -2906,7 +3050,14 @@ wrap_nettle_pk_fixup(gnutls_pk_algorithm_t algo,
                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)
index debcc2ac09f90d13230c1cfe13ce0c35b5fb802a..24f808000ac388db667ac4963f9675a5b6a0e492 100644 (file)
--- a/lib/pk.c
+++ b/lib/pk.c
@@ -1215,6 +1215,7 @@ pk_prepare_hash(gnutls_pk_algorithm_t pk,
        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:
index bcabee90184b85201cfe49aedaac3210803ee10a..ad99459adba722fa5e41f770f0d8824d5e9da812 100644 (file)
@@ -132,7 +132,8 @@ static const int _supported_groups_ecdh[] = {
        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
 };
 
@@ -153,7 +154,8 @@ static const int _supported_groups_normal[] = {
        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)
@@ -172,7 +174,8 @@ static const int _supported_groups_secure128[] = {
        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,
@@ -419,6 +422,8 @@ static const int _sign_priority_default[] = {
        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,
@@ -455,6 +460,7 @@ static const int _sign_priority_secure128[] = {
        GNUTLS_SIGN_RSA_PSS_RSAE_SHA256,
        GNUTLS_SIGN_ECDSA_SHA256,
        GNUTLS_SIGN_ECDSA_SECP256R1_SHA256,
+
        GNUTLS_SIGN_EDDSA_ED25519,
 
        GNUTLS_SIGN_RSA_SHA384,
@@ -463,6 +469,8 @@ static const int _sign_priority_secure128[] = {
        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,
index 425cc3e7c6869500f22fa21c9d5b06b03244e7c7..4114e2ca182a95e66add61be341fa100ff9f9384 100644 (file)
@@ -205,6 +205,7 @@ privkey_to_pubkey(gnutls_pk_algorithm_t pk,
 
                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);
index 3b4d7f90036bbaa262eb4b72a4ab18e2d8a0fb5f..eb7fdbaa82bf8004536e231018491dbfd1441c35 100644 (file)
@@ -61,6 +61,7 @@ unsigned pubkey_to_bits(const gnutls_pk_params_st * params)
                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:
@@ -314,6 +315,12 @@ gnutls_pubkey_get_preferred_hash_algorithm(gnutls_pubkey_t key,
                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:
@@ -891,7 +898,8 @@ gnutls_pubkey_export_ecc_raw2(gnutls_pubkey_t key,
        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)
@@ -1429,7 +1437,16 @@ gnutls_pubkey_import_ecc_raw(gnutls_pubkey_t key,
                        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);
 
@@ -2232,6 +2249,7 @@ pubkey_verify_data(const gnutls_sign_entry_st *se,
                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;
index d36c263a58aaa930f4a20c04857190bd4b1b3cf1..498ccc4e97090cc6f5214a30465172ef7e577e3a 100644 (file)
@@ -98,6 +98,7 @@
 #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"
index e42f5e09621dbc636c9f74bfd1ba549ab91139fd..c79f6eee37513c5d0aa8c42d97357e12edd2c8b6 100644 (file)
@@ -565,6 +565,9 @@ int _gnutls_x509_read_pubkey(gnutls_pk_algorithm_t algo, uint8_t * der,
        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:
@@ -590,6 +593,7 @@ int _gnutls_x509_read_pubkey_params(gnutls_pk_algorithm_t algo,
        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, &params->spki);
@@ -634,6 +638,7 @@ int _gnutls_x509_check_pubkey_params(gnutls_pk_params_st * params)
        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:
index a589dd4f3300eb0d051c5b0d644d63a5f3119952..b9cbcff7bc3425b91b5fbff1498e336444199dba 100644 (file)
@@ -150,7 +150,8 @@ _gnutls_x509_write_eddsa_pubkey(const gnutls_pk_params_st * params,
        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);
@@ -252,6 +253,7 @@ _gnutls_x509_write_pubkey_params(const gnutls_pk_params_st * params,
        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;
 
@@ -278,6 +280,7 @@ _gnutls_x509_write_pubkey(const gnutls_pk_params_st * params,
        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:
@@ -1031,6 +1034,7 @@ int _gnutls_asn1_encode_privkey(ASN1_TYPE * c2,
                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:
index 1be3da484edbfbf552e9d7ec2ca20ee532dc60bb..a0bdfab9f7aec54b0a0077a112e966ac9fc7c8f3 100644 (file)
@@ -134,7 +134,9 @@ _gnutls_get_asn_mpis(ASN1_TYPE asn, const char *root,
        _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 && 
index da45917753a46f853789ef960eaebc15460340e0..2aa78b478ba0da10fa95321251238de9a1f4a25c 100644 (file)
@@ -1406,6 +1406,7 @@ print_pubkey(gnutls_buffer_st * str, const char *key_name,
                break;
 
        case GNUTLS_PK_EDDSA_ED25519:
+       case GNUTLS_PK_EDDSA_ED448:
        case GNUTLS_PK_ECDSA:
                {
                        gnutls_datum_t x, y;
index a9579914f8c7837ddbd2590b0d8ac5da813248e4..b26295e51be671c3f782e95b4fd7d8cb374c6372 100644 (file)
@@ -1116,7 +1116,17 @@ gnutls_x509_privkey_import_ecc_raw(gnutls_x509_privkey_t key,
 
        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) {
index bcc6dd24ec136f04cc21381f99b9abbebe73534c..f23008fbe5ee3db320f373806838f3fe37bb66f1 100644 (file)
@@ -69,6 +69,7 @@ _encode_privkey(gnutls_x509_privkey_t pkey, gnutls_datum_t * raw)
 
        switch (pkey->params.algo) {
        case GNUTLS_PK_EDDSA_ED25519:
+       case GNUTLS_PK_EDDSA_ED448:
                /* 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,
@@ -1115,7 +1116,16 @@ _decode_pkcs8_eddsa_key(ASN1_TYPE pkcs8_asn, gnutls_x509_privkey_t pkey, const c
                        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;
@@ -1449,6 +1459,7 @@ decode_private_key_info(const gnutls_datum_t * der,
                        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:
index 39a25307a049fb0537d435cb8cb0384010f092d4..050e95059e3b2197fe734cd88693c661ae055c10 100644 (file)
@@ -48,6 +48,8 @@
 #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"
index f10f57bdbbae5dd00b9a127f689ad243ee6d27c4..645dc563cc3b48725103724e5e1793168fa1bd72 100644 (file)
@@ -200,7 +200,7 @@ flag = {
     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.";
 };
index 3fafa5977cba38fdbf4e0073a8afd3e7d86d4d62..c76352c9d8fdf823b1de4a8c63aca035f27e56a6 100644 (file)
@@ -1287,7 +1287,9 @@ static void privkey_info_int(FILE *outfile, common_info_st * cinfo,
                        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;
 
@@ -1641,6 +1643,8 @@ gnutls_pk_algorithm_t figure_key_type(const char *key_type)
                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)
index bfeb66b2da3f6cdef7380b4d75b0c0f0e7986c78..04c7a3e91a9f12d3741e1448982a6ffbd7d0a6d2 100644 (file)
@@ -90,7 +90,7 @@ void switch_to_pkcs8_when_needed(common_info_st *cinfo, gnutls_x509_privkey_t ke
        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)
index 35438daafa853c5a540c25614e7590e86942814d..b65359c27c8fe367e1bf31fe4edd64adfb601cdd 100644 (file)
@@ -168,6 +168,7 @@ generate_private_key_int(common_info_st * cinfo)
 
        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) {
index 0d3f14b6004bb2b73df7f32e18c24e934c81f519..952fc5fbb4281251bb60dcada6575a8599471734 100644 (file)
@@ -129,6 +129,8 @@ void doit(void)
                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));
        }
 
index 7491e3cf330fb3d11c808cd4a396bff7ab73012e..31634bd0958b1e1a46ae3576a0aaf64c36ec6c5d 100644 (file)
@@ -65,36 +65,29 @@ static void sign_verify_data(gnutls_pk_algorithm_t algorithm, gnutls_x509_privke
        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)
@@ -122,7 +115,8 @@ void doit(void)
                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 ||
index c351662319f46c2ae174a49e5ff1031076fcbaab..6ed5dba27f2d6daf2d8c0226d6d432d03b86fd1a 100644 (file)
@@ -43,6 +43,9 @@ RSA_PSS_CLI_KEY="${srcdir}/../../doc/credentials/x509/clikey-rsa-pss.pem"
 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"
 
@@ -52,6 +55,9 @@ RSA_KEY="${srcdir}/../../doc/credentials/x509/key-rsa.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"
 
index 6d17941b8e06e2ca64de89a3ef13f3915e75798f..128873ab231c4f06aeb4d9fb8269918400492738 100755 (executable)
@@ -177,6 +177,18 @@ run_client_suite() {
        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}"
@@ -324,7 +336,8 @@ run_server_suite() {
                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}"
@@ -395,6 +408,10 @@ _EOF_
        ${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
 
@@ -452,6 +469,19 @@ _EOF_
        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}"