Browse Source

Expanded support for Curve25519/Curve448 and TLS v1.3 sniffer (#4335)

* Fixes for building with Ed/Curve25519 only. Fix for IoT safe demo to exit after running once. Added `WOLFSSL_DH_EXTRA` to `--enable-all` and `--enable-sniffer`. Cleanup uses of `==` in configure.ac. Various spelling fixes.

* Fix for sniffer with TLS v1.3 session tickets.

* Fix for ASN Template Ed25519 key export (missing version / not setting OID correctly).

* Add key import/export support for Curve25519/Curve448. Refactor of the 25519/448 ASN code to combine duplicate code.

* Refactor of Curve25519 code. Improved public key export to handle generation when only private is set. Improved private scalar buffer sizing.

* Fix for static ephemeral loading of file buffer.

* Added sniffer Curve25519 support and test case.

* Fix for sniffer to not use ECC for X25519 if both are set.

* Fix Curve448 public export when only private is set.

* Fix for `dh_generate_test` for small stack size.

* Reduce stack size use on new asymmetric DER import/export functions. Cleanup pub length calc.

* Fix invalid comment.
David Garske 2 years ago
parent
commit
9b6cf56a6e

+ 1 - 0
IDE/iotsafe/memory-tls.c

@@ -384,6 +384,7 @@ static int server_loop(void)
             wolfSSL_CTX_free(srv_ctx); srv_ctx = NULL;
 
             server_state = 0;
+            return -1; /* exit test loop, so it doesn't keep running forever */
         }
     }
 

+ 12 - 6
certs/statickeys/gen-static.sh

@@ -3,13 +3,19 @@
 # run from wolfssl root
 
 # SECP256R1
-openssl ecparam -name secp256r1 -genkey -noout -out certs/statickeys/ecc-secp256r1.pem -noout
+openssl ecparam -name prime256v1 -genkey -noout -out certs/statickeys/ecc-secp256r1.pem
 openssl ec -inform pem -in certs/statickeys/ecc-secp256r1.pem -outform der -out certs/statickeys/ecc-secp256r1.der
 
 # DH 2048-bit (keySz = 29)
 # Using one generated and capture with wolfSSL using wc_DhGenerateKeyPair (openssl generates DH keys with 2048-bits... based on the DH "p" prime size)
-#openssl genpkey -paramfile certs/statickeys/dh-ffdhe2048-params.pem -out certs/statickeys/dh-ffdhe2048.der
-openssl pkey -inform der -in certs/statickeys/dh-ffdhe2048.der -outform pem -out certs/statickeys/dh-ffdhe2048.pem
-# Export DH public key as DER and convert to PEM
-openssl pkey -inform der -in certs/statickeys/dh-ffdhe2048.der -outform der -out certs/statickeys/dh-ffdhe2048-pub.der -pubout
-openssl pkey -inform der -in certs/statickeys/dh-ffdhe2048.der -outform pem -out certs/statickeys/dh-ffdhe2048-pub.pem -pubout
+openssl genpkey -paramfile certs/statickeys/dh-ffdhe2048-params.pem -outform -out certs/statickeys/dh-ffdhe2048.pem
+openssl pkey -inform pem -in certs/statickeys/dh-ffdhe2048.pem -outform der -out certs/statickeys/dh-ffdhe2048.der
+# Export DH public key as DER and PEM
+openssl pkey -inform pem -in certs/statickeys/dh-ffdhe2048.pem -outform der -out certs/statickeys/dh-ffdhe2048-pub.der -pubout
+openssl pkey -inform pem -in certs/statickeys/dh-ffdhe2048.pem -outform pem -out certs/statickeys/dh-ffdhe2048-pub.pem -pubout
+
+# X25519 (Curve25519)
+openssl genpkey -algorithm x25519 -outform pem -out certs/statickeys/x25519.pem
+openssl pkey -inform pem -in certs/statickeys/x25519.pem -outform der -out certs/statickeys/x25519.der
+openssl pkey -inform pem -in certs/statickeys/x25519.pem -outform der -out certs/statickeys/x25519-pub.der -pubout
+openssl pkey -inform pem -in certs/statickeys/x25519.pem -outform pem -out certs/statickeys/x25519-pub.pem -pubout

+ 7 - 0
certs/statickeys/include.am

@@ -17,3 +17,10 @@ EXTRA_DIST += \
 		certs/statickeys/dh-ffdhe2048.pem \
 		certs/statickeys/dh-ffdhe2048-pub.der \
 		certs/statickeys/dh-ffdhe2048-pub.pem
+
+# Curve25519 Keys
+EXTRA_DIST += \
+		certs/statickeys/x25519.der \
+		certs/statickeys/x25519.pem \
+		certs/statickeys/x25519-pub.der \
+		certs/statickeys/x25519-pub.pem

BIN
certs/statickeys/x25519-pub.der


+ 3 - 0
certs/statickeys/x25519-pub.pem

@@ -0,0 +1,3 @@
+-----BEGIN PUBLIC KEY-----
+MCowBQYDK2VuAyEACbyMx0UNwcICV5poOv16qKUv8Jk5mOomols4/ZbbKiY=
+-----END PUBLIC KEY-----

BIN
certs/statickeys/x25519.der


+ 3 - 0
certs/statickeys/x25519.pem

@@ -0,0 +1,3 @@
+-----BEGIN PRIVATE KEY-----
+MC4CAQAwBQYDK2VuBCIEIHiOMVwzqRnAXjZwG6To78GJjLMVxnnTrCIArvqztw94
+-----END PRIVATE KEY-----

+ 25 - 12
configure.ac

@@ -491,13 +491,19 @@ then
     DEFAULT_MAX_CLASSIC_ASYM_KEY_BITS=4096
 
     # Enable multiple attribute additions such as DC
-    AM_CFLAGS="-DWOLFSSL_MULTI_ATTRIB $AM_CFLAGS"
+    AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_MULTI_ATTRIB"
 
-    # Enable AES Decrypt, AES ECB, Alt Names, DER Load, Keep Certs, CRL IO with Timeout
-    AM_CFLAGS="$AM_CFLAGS -DHAVE_AES_DECRYPT -DHAVE_AES_ECB -DWOLFSSL_ALT_NAMES -DWOLFSSL_DER_LOAD -DKEEP_OUR_CERT -DKEEP_PEER_CERT"
+    # Enable AES Decrypt, AES ECB
+    AM_CFLAGS="$AM_CFLAGS -DHAVE_AES_DECRYPT -DHAVE_AES_ECB"
+    
+    # Enable Alt Names, DER Load, Keep Certs, CRL IO with Timeout
+    AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ALT_NAMES -DWOLFSSL_DER_LOAD -DKEEP_OUR_CERT -DKEEP_PEER_CERT"
 
     # Enable ECC Key Gen checks
     AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_VALIDATE_ECC_KEYGEN"
+
+    # Enable DH Extra
+    AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DH_EXTRA"
 fi
 
 
@@ -577,7 +583,7 @@ then
         AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_VALIDATE_ECC_IMPORT"
     fi
 
-    if test "$ENABLED_FIPS" == "no"
+    if test "$ENABLED_FIPS" = "no"
     then
         test "$enable_xchacha" = "" && enable_xchacha=yes
         test "$enable_ed25519" = "" && enable_ed25519=yes
@@ -1003,8 +1009,8 @@ AC_ARG_ENABLE([opensslall],
 if test "$ENABLED_LIBWEBSOCKETS" = "yes" || test "$ENABLED_OPENVPN" = "yes" || \
    test "$ENABLED_WPAS_DPP" = "yes" || test "$ENABLED_SMIME" = "yes" || \
    test "$ENABLED_HAPROXY" = "yes" || test "$ENABLED_BIND" = "yes" || \
-   test "$ENABLED_NTP" == "yes" || test "$ENABLED_NETSNMP" = "yes" || \
-   test "$ENABLED_OPENRESTY" = "yes" || test "$ENABLED_RSYSLOG" == "yes"
+   test "$ENABLED_NTP" = "yes" || test "$ENABLED_NETSNMP" = "yes" || \
+   test "$ENABLED_OPENRESTY" = "yes" || test "$ENABLED_RSYSLOG" = "yes"
 then
     ENABLED_OPENSSLALL="yes"
 fi
@@ -1026,7 +1032,7 @@ if test "$ENABLED_OPENSSH" = "yes" || test "$ENABLED_NGINX" = "yes" || \
    test "$ENABLED_SNIFFER" = "yes" || test "$ENABLED_OPENSSLALL" = "yes" || \
    test "$ENABLED_LIBWEBSOCKETS" = "yes" || \
    test "x$ENABLED_LIGHTY" = "xyes" || test "$ENABLED_LIBSSH2" = "yes" || \
-   test "x$ENABLED_NTP" = "xyes" || test "$ENABLED_RSYSLOG" == "yes"
+   test "x$ENABLED_NTP" = "xyes" || test "$ENABLED_RSYSLOG" = "yes"
 then
     ENABLED_OPENSSLEXTRA="yes"
 fi
@@ -2893,6 +2899,11 @@ else
     fi
 fi
 
+if test "x$ENABLED_SNIFFER" = "xyes" && test "x$ENABLED_DH" = "xyes"
+then
+    AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DH_EXTRA"
+fi
+
 
 # Anonymous
 AC_ARG_ENABLE([anon],
@@ -2901,7 +2912,8 @@ AC_ARG_ENABLE([anon],
     [ ENABLED_ANON=no ]
     )
 
-if test "x$ENABLED_WPAS" = "xyes" || test "x$ENABLED_NGINX" = "xyes" || test "x$ENABLED_HAPROXY" = "xyes" || test "$ENABLED_RSYSLOG" == "yes"
+if test "x$ENABLED_WPAS" = "xyes"    || test "x$ENABLED_NGINX" = "xyes" || \
+   test "x$ENABLED_HAPROXY" = "xyes" || test "$ENABLED_RSYSLOG" = "yes"
 then
     ENABLED_ANON=yes
 fi
@@ -3593,7 +3605,7 @@ if test "$ENABLED_CRL" != "no"
 then
     AM_CFLAGS="$AM_CFLAGS -DHAVE_CRL"
 fi
-if test "$ENABLED_CRL" == "io"
+if test "$ENABLED_CRL" = "io"
 then
     AM_CFLAGS="$AM_CFLAGS -DHAVE_CRL_IO"
 fi
@@ -6174,7 +6186,7 @@ then
     AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_TRACK_MEMORY -DWOLFSSL_DEBUG_MEMORY"
 fi
 
-if test "x$ENABLED_MEMTEST" == "xfail"
+if test "x$ENABLED_MEMTEST" = "xfail"
 then
     AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_FORCE_MALLOC_FAIL_TEST"
 fi
@@ -6386,8 +6398,9 @@ AS_IF([test "x$ENABLED_LEANTLS" = "xyes" && \
 
 AS_IF([test "x$ENABLED_SNIFFER" = "xyes" && \
        test "x$ENABLED_RSA" = "xno" && \
-       test "x$ENABLED_ECC" = "xno"],
-      [AC_MSG_ERROR([please enable ecc or rsa if enabling sniffer.])])
+       test "x$ENABLED_ECC" = "xno" && \
+       test "x$ENABLED_CURVE25519" = "xno"],
+      [AC_MSG_ERROR([please enable ecc, rsa or curve25519 if enabling sniffer.])])
 
 # Lean TLS forces off prereqs of SCEP.
 AS_IF([test "x$ENABLED_SCEP" = "xyes" && \

+ 7 - 0
examples/server/server.c

@@ -2191,6 +2191,13 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
         err_sys_ex(runWithErrors, "error loading static DH key");
     }
 #endif
+#ifdef HAVE_CURVE25519
+    ret = wolfSSL_CTX_set_ephemeral_key(ctx, WC_PK_TYPE_CURVE25519,
+        "./certs/statickeys/x25519.pem", 0, WOLFSSL_FILETYPE_PEM);
+    if (ret != 0) {
+        err_sys_ex(runWithErrors, "error loading static X25519 key");
+    }
+#endif
 #endif /* WOLFSSL_SNIFFER && WOLFSSL_STATIC_EPHEMERAL */
 
     if (cipherList && !useDefCipherList) {

+ 1 - 0
scripts/include.am

@@ -91,6 +91,7 @@ EXTRA_DIST +=  scripts/testsuite.pcap \
                scripts/sniffer-ipv6.pcap \
                scripts/sniffer-tls13-dh.pcap \
                scripts/sniffer-tls13-ecc.pcap \
+               scripts/sniffer-tls13-x25519.pcap \
                scripts/sniffer-tls13-gen.sh \
                scripts/sniffer-tls13-hrr.pcap \
                scripts/ping.test \

+ 10 - 0
scripts/sniffer-testsuite.test

@@ -39,6 +39,16 @@ then
     [ $RESULT -ne 0 ] && echo -e "\nsnifftest TLS v1.3 DH\n" && exit 1
 fi
 
+# TLS v1.3 sniffer test X25519 (and resumption)
+if test $# -ne 0
+then
+    ./sslSniffer/sslSnifferTest/snifftest ./scripts/sniffer-tls13-x25519.pcap ./certs/statickeys/x25519.pem 127.0.0.1 11111
+
+    RESULT=$?
+    [ $RESULT -ne 0 ] && echo -e "\nsnifftest TLS v1.3 X25519\n" && exit 1
+fi
+
+
 # TLS v1.3 sniffer test hello_retry_request (HRR) with ECDHE
 if test $# -ne 0
 then

+ 58 - 17
scripts/sniffer-tls13-gen.sh

@@ -7,23 +7,64 @@
 # Script to generate wireshark trace for sniffer-tls13-dh.pcap
 #./configure --enable-sniffer --enable-session-ticket --disable-ecc && make
 
-# TLS v1.3
-./examples/server/server -v 4 -l TLS13-AES128-GCM-SHA256 &
-./examples/client/client -v 4 -l TLS13-AES128-GCM-SHA256
-./examples/server/server -v 4 -l TLS13-AES256-GCM-SHA384 &
-./examples/client/client -v 4 -l TLS13-AES256-GCM-SHA384
-./examples/server/server -v 4 -l TLS13-CHACHA20-POLY1305-SHA256 &
-./examples/client/client -v 4 -l TLS13-CHACHA20-POLY1305-SHA256
-
-# TLS v1.3 Resumption
-./examples/server/server -v 4 -l TLS13-AES128-GCM-SHA256 -r &
-./examples/client/client -v 4 -l TLS13-AES128-GCM-SHA256 -r
-./examples/server/server -v 4 -l TLS13-AES256-GCM-SHA384 -r &
-./examples/client/client -v 4 -l TLS13-AES256-GCM-SHA384 -r
-./examples/server/server -v 4 -l TLS13-CHACHA20-POLY1305-SHA256 -r &
-./examples/client/client -v 4 -l TLS13-CHACHA20-POLY1305-SHA256 -r
+# Run: with dh or ecc
+if [ "$1" == "dh" ] || [ "$1" == "ecc" ]; then
+    # TLS v1.3
+    ./examples/server/server -v 4 -l TLS13-AES128-GCM-SHA256 &
+    ./examples/client/client -v 4 -l TLS13-AES128-GCM-SHA256
+    ./examples/server/server -v 4 -l TLS13-AES256-GCM-SHA384 &
+    ./examples/client/client -v 4 -l TLS13-AES256-GCM-SHA384
+    ./examples/server/server -v 4 -l TLS13-CHACHA20-POLY1305-SHA256 &
+    ./examples/client/client -v 4 -l TLS13-CHACHA20-POLY1305-SHA256
+
+    # TLS v1.3 Resumption
+    ./examples/server/server -v 4 -l TLS13-AES128-GCM-SHA256 -r &
+    ./examples/client/client -v 4 -l TLS13-AES128-GCM-SHA256 -r
+    ./examples/server/server -v 4 -l TLS13-AES256-GCM-SHA384 -r &
+    ./examples/client/client -v 4 -l TLS13-AES256-GCM-SHA384 -r
+    ./examples/server/server -v 4 -l TLS13-CHACHA20-POLY1305-SHA256 -r &
+    ./examples/client/client -v 4 -l TLS13-CHACHA20-POLY1305-SHA256 -r
+fi
+
+# Script to generate wireshark trace for sniffer-tls13-x25519.pcap
+#./configure --enable-sniffer --enable-session-ticket --enable-curve25519 --disable-dh --disable-ecc && make
+# Run: with x25519
+if [ "$1" == "x25519" ]; then
+    # TLS v1.3
+    ./examples/server/server -v 4 -l TLS13-AES128-GCM-SHA256 -c ./certs/ed25519/server-ed25519.pem -k ./certs/ed25519/server-ed25519-priv.pem -A ./certs/ed25519/client-ed25519.pem &
+    sleep 0.1
+    ./examples/client/client -v 4 -l TLS13-AES128-GCM-SHA256 -c ./certs/ed25519/client-ed25519.pem -k ./certs/ed25519/client-ed25519-priv.pem -A ./certs/ed25519/root-ed25519.pem
+
+    ./examples/server/server -v 4 -l TLS13-AES256-GCM-SHA384 -c ./certs/ed25519/server-ed25519.pem -k ./certs/ed25519/server-ed25519-priv.pem -A ./certs/ed25519/client-ed25519.pem &
+    sleep 0.1
+    ./examples/client/client -v 4 -l TLS13-AES256-GCM-SHA384 -c ./certs/ed25519/client-ed25519.pem -k ./certs/ed25519/client-ed25519-priv.pem -A ./certs/ed25519/root-ed25519.pem
+
+    ./examples/server/server -v 4 -l TLS13-CHACHA20-POLY1305-SHA256 -c ./certs/ed25519/server-ed25519.pem -k ./certs/ed25519/server-ed25519-priv.pem -A ./certs/ed25519/client-ed25519.pem &
+    sleep 0.1
+    ./examples/client/client -v 4 -l TLS13-CHACHA20-POLY1305-SHA256 -c ./certs/ed25519/client-ed25519.pem -k ./certs/ed25519/client-ed25519-priv.pem -A ./certs/ed25519/root-ed25519.pem
+
+    # TLS v1.3 Resumption
+    ./examples/server/server -v 4 -l TLS13-AES128-GCM-SHA256 -r -c ./certs/ed25519/server-ed25519.pem -k ./certs/ed25519/server-ed25519-priv.pem -A ./certs/ed25519/client-ed25519.pem &
+    sleep 0.1
+    ./examples/client/client -v 4 -l TLS13-AES128-GCM-SHA256 -r -c ./certs/ed25519/client-ed25519.pem -k ./certs/ed25519/client-ed25519-priv.pem -A ./certs/ed25519/root-ed25519.pem
+
+    ./examples/server/server -v 4 -l TLS13-AES256-GCM-SHA384 -r -c ./certs/ed25519/server-ed25519.pem -k ./certs/ed25519/server-ed25519-priv.pem -A ./certs/ed25519/client-ed25519.pem &
+    sleep 0.1
+    ./examples/client/client -v 4 -l TLS13-AES256-GCM-SHA384 -r -c ./certs/ed25519/client-ed25519.pem -k ./certs/ed25519/client-ed25519-priv.pem -A ./certs/ed25519/root-ed25519.pem
+
+    ./examples/server/server -v 4 -l TLS13-CHACHA20-POLY1305-SHA256 -r -c ./certs/ed25519/server-ed25519.pem -k ./certs/ed25519/server-ed25519-priv.pem -A ./certs/ed25519/client-ed25519.pem &
+    sleep 0.1
+    ./examples/client/client -v 4 -l TLS13-CHACHA20-POLY1305-SHA256 -r -c ./certs/ed25519/client-ed25519.pem -k ./certs/ed25519/client-ed25519-priv.pem -A ./certs/ed25519/root-ed25519.pem
+fi
 
 # TLS v1.3 Hello Retry Request (save this as sniffer-tls13-hrr.pcap)
 # ./configure --enable-sniffer CFLAGS="-DWOLFSSL_SNIFFER_WATCH" --disable-dh && make
-./examples/server/server -v 4 -i -x -g &
-./examples/client/client -v 4 -J
+
+# Run ./scripts/sniffer-tls13-gen.sh hrr
+if [ "$1" == "hrr" ]; then
+    # TLS v1.3 Hello Retry Request 
+    ./examples/server/server -v 4 -i -x -g &
+    sleep 0.1
+
+    ./examples/client/client -v 4 -J
+fi

BIN
scripts/sniffer-tls13-x25519.pcap


+ 13 - 6
src/internal.c

@@ -2273,6 +2273,10 @@ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx)
     if (ctx->staticKE.ecKey && ctx->staticKE.weOwnEC)
         FreeDer(&ctx->staticKE.ecKey);
     #endif
+    #ifdef HAVE_CURVE25519
+    if (ctx->staticKE.x25519Key && ctx->staticKE.weOwnX25519)
+        FreeDer(&ctx->staticKE.x25519Key);
+    #endif
 #endif
 #ifdef WOLFSSL_STATIC_MEMORY
     if (ctx->heap != NULL) {
@@ -6213,6 +6217,9 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
     #ifndef NO_DH
     ssl->staticKE.weOwnDH = 0;
     #endif
+    #ifdef HAVE_CURVE25519
+    ssl->staticKE.weOwnX25519 = 0;
+    #endif
 #endif
 
 #ifdef WOLFSSL_TLS13
@@ -6987,6 +6994,10 @@ void SSL_ResourceFree(WOLFSSL* ssl)
     if (ssl->staticKE.ecKey && ssl->staticKE.weOwnEC)
         FreeDer(&ssl->staticKE.ecKey);
     #endif
+    #ifdef HAVE_CURVE25519
+    if (ssl->staticKE.x25519Key && ssl->staticKE.weOwnX25519)
+        FreeDer(&ssl->staticKE.x25519Key);
+    #endif
 #endif
 
 #ifdef WOLFSSL_STATIC_MEMORY
@@ -27404,12 +27415,6 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
 
             case TLS_ASYNC_BUILD:
             {
-            #if (!defined(NO_DH) && !defined(NO_RSA)) || (defined(HAVE_ECC) || \
-                    (defined(HAVE_CURVE25519) && defined(HAVE_ED25519)) || \
-                    (defined(HAVE_CURVE448) && defined(HAVE_ED448)))
-                word32 preSigSz, preSigIdx;
-            #endif
-
                 switch(ssl->specs.kea)
                 {
                 #ifndef NO_PSK
@@ -27670,6 +27675,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
                     case ecc_diffie_hellman_kea:
                     {
                         enum wc_HashType hashType;
+                        word32 preSigSz, preSigIdx;
 
                         /* curve type, named curve, length(1) */
                         args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
@@ -28003,6 +28009,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
                     case diffie_hellman_kea:
                     {
                         enum wc_HashType hashType;
+                        word32 preSigSz, preSigIdx;
 
                         args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
                         args->length = LENGTH_SZ * 3;  /* p, g, pub */

+ 1 - 1
src/ocsp.c

@@ -858,7 +858,7 @@ const char *wolfSSL_OCSP_response_status_str(long s)
             return "trylater";
         case OCSP_SIG_REQUIRED:
             return "sigrequired";
-        case OCSP_UNAUTHROIZED:
+        case OCSP_UNAUTHORIZED:
             return "unauthorized";
         default:
             return "(UNKNOWN)";

+ 133 - 21
src/sniffer.c

@@ -91,6 +91,20 @@
 #include <wolfssl/error-ssl.h>
 #include <wolfssl/sniffer.h>
 #include <wolfssl/sniffer_error.h>
+
+#ifndef NO_RSA
+    #include <wolfssl/wolfcrypt/rsa.h>
+#endif
+#ifndef NO_DH
+    #include <wolfssl/wolfcrypt/dh.h>
+#endif
+#ifdef HAVE_ECC
+    #include <wolfssl/wolfcrypt/ecc.h>
+#endif
+#ifdef HAVE_CURVE25519
+    #include <wolfssl/wolfcrypt/curve25519.h>
+#endif
+
 #ifdef NO_INLINE
     #include <wolfssl/wolfcrypt/misc.h>
 #else
@@ -2146,6 +2160,9 @@ typedef struct {
 #ifdef HAVE_ECC
     DerBuffer* ecKey;
 #endif
+#ifdef HAVE_CURVE25519
+    DerBuffer* x25519Key;
+#endif
 #if !defined(NO_RSA) && defined(WOLFSSL_STATIC_RSA)
     DerBuffer* rsaKey;
 #endif
@@ -2157,14 +2174,14 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
     word32 idx = 0;
     int ret;
     DerBuffer* keyBuf;
-#ifdef HAVE_ECC
-    int useEccCurveId = ECC_CURVE_DEF;
+#if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
+    int useCurveId = 0;
 #endif
     int devId = INVALID_DEVID;
 
-#ifdef HAVE_ECC
+#if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
     if (ksInfo && ksInfo->curve_id != 0)
-        useEccCurveId = ksInfo->curve_id;
+        useCurveId = ksInfo->curve_id;
 #endif
 #ifdef WOLF_CRYPTO_CB
     devId = CryptoDeviceId;
@@ -2201,9 +2218,9 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
                     keys->ecKey = session->sslServer->buffers.key; /* try ECC */
             #endif
             }
-        #ifdef HAVE_ECC
+        #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
             else {
-                useEccCurveId = -1; /* don't try loading ECC */
+                useCurveId = -1; /* don't try loading further */
             }
         #endif
         }
@@ -2365,7 +2382,11 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
 
 #ifdef HAVE_ECC
     /* Static ECC Key */
-    if (useEccCurveId >= ECC_CURVE_DEF && keys->ecKey) {
+    if (useCurveId >= 0 && keys->ecKey
+    #ifdef HAVE_CURVE25519
+        && useCurveId != ECC_X25519 
+    #endif
+    ) {
         ecc_key key;
         ecc_key pubKey;
         int length, keyInit = 0, pubKeyInit = 0;
@@ -2422,13 +2443,13 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
             }
 
             /* if curve not provided in key share data, then use private key curve */
-            if (useEccCurveId == ECC_CURVE_DEF && key.dp) {
-                useEccCurveId = key.dp->id;
+            if (useCurveId == 0 && key.dp) {
+                useCurveId = key.dp->id;
             }
         }
 
         if (ret == 0) {
-            ret = wc_ecc_import_x963_ex(input, length, &pubKey, useEccCurveId);
+            ret = wc_ecc_import_x963_ex(input, length, &pubKey, useCurveId);
             if (ret != 0) {
                 SetError(ECC_PUB_DECODE_STR, error, session, FATAL_ERROR_STATE);
             }
@@ -2466,6 +2487,82 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
     }
 #endif /* HAVE_ECC */
 
+#ifdef HAVE_CURVE25519
+    /* Static Curve25519 Key */
+    if (useCurveId == ECC_X25519 && keys->x25519Key) {
+        curve25519_key key;
+        curve25519_key pubKey;
+        int length, keyInit = 0, pubKeyInit = 0;
+
+        keyBuf = keys->x25519Key;
+
+#ifdef WOLFSSL_SNIFFER_KEY_CALLBACK
+        if (KeyCb != NULL && ksInfo) {
+            ret = KeyCb(session, ksInfo->named_group,
+                session->srvKs.key, session->srvKs.key_len,
+                session->cliKs.key, session->cliKs.key_len,
+                keyBuf, KeyCbCtx, error);
+            if (ret != 0) {
+                SetError(-1, error, session, FATAL_ERROR_STATE);
+                return ret;
+            }
+        }
+#endif
+
+        idx = 0;
+        ret = wc_curve25519_init_ex(&key, NULL, devId);
+        if (ret == 0) {
+            keyInit = 1;
+            ret = wc_curve25519_init(&pubKey);
+        }
+
+        if (ret == 0) {
+            pubKeyInit = 1;
+            ret = wc_Curve25519PrivateKeyDecode(keyBuf->buffer, &idx, &key,
+                keyBuf->length);
+            if (ret != 0) {
+                SetError(ECC_DECODE_STR, error, session, FATAL_ERROR_STATE);
+            }
+        }
+
+        if (ret == 0) {
+            length = CURVE25519_KEYSIZE;
+            if (length > *sslBytes) {
+                SetError(PARTIAL_INPUT_STR, error, session, FATAL_ERROR_STATE);
+                ret = -1;
+            }
+        }
+
+        if (ret == 0) {
+            ret = wc_curve25519_import_public_ex(input, length, &pubKey,
+                EC25519_LITTLE_ENDIAN);
+            if (ret != 0) {
+                SetError(ECC_PUB_DECODE_STR, error, session, FATAL_ERROR_STATE);
+            }
+        }
+
+        if (ret == 0) {
+            /* For Curve25519 length is always 32 */
+            session->keySz = CURVE25519_KEYSIZE;
+            session->sslServer->arrays->preMasterSz = ENCRYPT_LEN;
+
+            ret = wc_curve25519_shared_secret_ex(&key, &pubKey,
+                session->sslServer->arrays->preMasterSecret,
+                &session->sslServer->arrays->preMasterSz, EC25519_LITTLE_ENDIAN);
+        }
+
+#ifdef WOLFSSL_SNIFFER_STATS
+        if (ret != 0)
+            INC_STAT(SnifferStats.sslKeyFails);
+#endif
+
+        if (keyInit)
+            wc_curve25519_free(&key);
+        if (pubKeyInit)
+            wc_curve25519_free(&pubKey);
+    }
+#endif /* HAVE_CURVE25519 */
+
     /* store for client side as well */
     XMEMCPY(session->sslClient->arrays->preMasterSecret,
            session->sslServer->arrays->preMasterSecret,
@@ -2553,6 +2650,9 @@ static int ProcessClientKeyExchange(const byte* input, int* sslBytes,
     #ifdef HAVE_ECC
     keys.ecKey = session->sslServer->staticKE.ecKey;
     #endif
+    #ifdef HAVE_CURVE25519
+    keys.x25519Key = session->sslServer->staticKE.x25519Key;
+    #endif
 #endif
     keys.rsaKey = session->sslServer->buffers.key;
     return SetupKeys(input, sslBytes, session, error, NULL, &keys);
@@ -2612,7 +2712,7 @@ static int ProcessKeyShare(KeyShareInfo* info, const byte* input, int len,
         #endif
     #endif /* !NO_DH */
     #ifdef HAVE_ECC
-        #if !defined(NO_ECC256)  || defined(HAVE_ALL_CURVES)
+        #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES)
             #ifndef NO_ECC_SECP
             case WOLFSSL_ECC_SECP256R1:
                 info->curve_id = ECC_SECP256R1;
@@ -2755,19 +2855,21 @@ static int ProcessSessionTicket(const byte* input, int* sslBytes,
 #ifdef WOLFSSL_TLS13
     /* TLS v1.3 has hint age and nonce */
     if (IsAtLeastTLSv1_3(ssl->version)) {
+        /* Note: Must use server session for sessions */
     #ifdef HAVE_SESSION_TICKET
-        if (SetTicket(ssl, input, len) != 0) {
+        if (SetTicket(session->sslServer, input, len) != 0) {
             SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
             return -1;
         }
+
         /* set haveSessionId to use the wolfSession cache */
-        ssl->options.haveSessionId = 1;
+        session->sslServer->options.haveSessionId = 1;
 
         /* Use the wolf Session cache to retain resumption secret */
         if (session->flags.cached == 0) {
-            WOLFSSL_SESSION* sess = GetSession(ssl, NULL, 0);
+            WOLFSSL_SESSION* sess = GetSession(session->sslServer, NULL, 0);
             if (sess == NULL) {
-                AddSession(ssl); /* don't re add */
+                AddSession(session->sslServer); /* don't re add */
             #ifdef WOLFSSL_SNIFFER_STATS
                 INC_STAT(SnifferStats.sslResumptionInserts);
             #endif
@@ -2858,8 +2960,10 @@ static int DoResume(SnifferSession* session, char* error)
         /* Resumption PSK is resumption master secret. */
         session->sslServer->arrays->psk_keySz = session->sslServer->specs.hash_size;
         session->sslClient->arrays->psk_keySz = session->sslClient->specs.hash_size;
-        ret  = DeriveResumptionPSK(session->sslServer, session->sslServer->session.ticketNonce.data, 
-            session->sslServer->session.ticketNonce.len, session->sslServer->arrays->psk_key);
+        ret  = DeriveResumptionPSK(session->sslServer,
+            session->sslServer->session.ticketNonce.data, 
+            session->sslServer->session.ticketNonce.len,
+            session->sslServer->arrays->psk_key);
         /* Copy resumption PSK to client */
         XMEMCPY(session->sslClient->arrays->psk_key, 
             session->sslServer->arrays->psk_key,
@@ -3181,6 +3285,9 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
         #ifdef HAVE_ECC
         keys.ecKey = session->sslServer->staticKE.ecKey;
         #endif
+        #ifdef HAVE_CURVE25519
+        keys.x25519Key = session->sslServer->staticKE.x25519Key;
+        #endif
     #endif
 
         ret = SetupKeys(session->cliKs.key, &session->cliKs.key_len, 
@@ -3505,6 +3612,9 @@ static int ProcessClientHello(const byte* input, int* sslBytes,
                         return -1;
                     }
                 }
+            #ifdef HAVE_SESSION_TICKET
+                ssl->options.useTicket = 1;
+            #endif
                 XMEMCPY(session->ticketID, input + extLen - ID_LEN, ID_LEN);
             }
             break;
@@ -3657,7 +3767,7 @@ static int ProcessFinished(const byte* input, int size, int* sslBytes,
         #ifndef NO_SESSION_CACHE
             WOLFSSL_SESSION* sess = GetSession(session->sslServer, NULL, 0);
             if (sess == NULL) {
-                AddSession(session->sslServer);  /* don't re add */
+                AddSession(session->sslServer); /* don't re add */
             #ifdef WOLFSSL_SNIFFER_STATS
                 INC_STAT(SnifferStats.sslResumptionInserts);
             #endif
@@ -3700,13 +3810,15 @@ static int ProcessFinished(const byte* input, int size, int* sslBytes,
 
         #ifdef HAVE_SESSION_TICKET
             /* derive resumption secret for next session - on finished (from client) */
-            ret += DeriveResumptionSecret(session->sslClient, session->sslClient->session.masterSecret);
+            ret += DeriveResumptionSecret(session->sslClient,
+                session->sslClient->session.masterSecret);
 
             /* copy resumption secret to server */
             XMEMCPY(session->sslServer->session.masterSecret,
-                session->sslClient->session.masterSecret, SECRET_LEN);
+                    session->sslClient->session.masterSecret, SECRET_LEN);
             #ifdef SHOW_SECRETS
-            PrintSecret("resumption secret", session->sslClient->session.masterSecret, SECRET_LEN);
+            PrintSecret("resumption secret",
+                session->sslClient->session.masterSecret, SECRET_LEN);
             #endif
         #endif
         }

+ 46 - 8
src/ssl.c

@@ -38619,7 +38619,7 @@ WOLFSSL_EVP_PKEY* wolfSSL_PEM_read_bio_PrivateKey(WOLFSSL_BIO* bio,
             if (keyFormat == RSAk)
                 type = EVP_PKEY_RSA;
             else if (keyFormat == ECDSAk)
-                type =  EVP_PKEY_EC;
+                type = EVP_PKEY_EC;
             else if (keyFormat == DSAk)
                 type = EVP_PKEY_DSA;
             else if (keyFormat == DHk)
@@ -54025,10 +54025,10 @@ static int SetStaticEphemeralKey(StaticKeyExchangeInfo_t* staticKE, int keyAlgo,
     WOLFSSL_ENTER("SetStaticEphemeralKey");
 
     /* if just free'ing key then skip loading */
-    if (key != NULL && keySz > 0) {
+    if (key != NULL) {
     #ifndef NO_FILESYSTEM
         /* load file from filesystem */
-        if (key && keySz == 0) {
+        if (key != NULL && keySz == 0) {
             size_t keyBufSz = 0;
             keyFile = (const char*)key;
             ret = wc_FileLoad(keyFile, &keyBuf, &keyBufSz, heap);
@@ -54053,6 +54053,8 @@ static int SetStaticEphemeralKey(StaticKeyExchangeInfo_t* staticKE, int keyAlgo,
             if (ret == 0 && keyAlgo == WC_PK_TYPE_NONE) {
                 if (keyFormat == ECDSAk)
                     keyAlgo = WC_PK_TYPE_ECDH;
+                else if (keyFormat == X25519k)
+                    keyAlgo = WC_PK_TYPE_CURVE25519;
                 else
                     keyAlgo = WC_PK_TYPE_DH;
             }
@@ -54088,6 +54090,20 @@ static int SetStaticEphemeralKey(StaticKeyExchangeInfo_t* staticKE, int keyAlgo,
                 }
             }
         #endif
+        #ifdef HAVE_CURVE25519
+            if (keyAlgo == WC_PK_TYPE_NONE) {
+                word32 idx = 0;
+                curve25519_key x25519Key;
+                ret = wc_curve25519_init_ex(&x25519Key, heap, INVALID_DEVID);
+                if (ret == 0) {
+                    ret = wc_Curve25519PrivateKeyDecode(keyBuf, &idx, &x25519Key,
+                        keySz);
+                    if (ret == 0)
+                        keyAlgo = WC_PK_TYPE_CURVE25519;
+                    wc_curve25519_free(&x25519Key);
+                }
+            }
+        #endif
 
             if (keyAlgo != WC_PK_TYPE_NONE) {
                 ret = AllocDer(&der, keySz, PRIVATEKEY_TYPE, heap);
@@ -54107,34 +54123,51 @@ static int SetStaticEphemeralKey(StaticKeyExchangeInfo_t* staticKE, int keyAlgo,
 
     /* if key is already allocated then set free it */
 #ifndef NO_DH
-    if (keyAlgo == WC_PK_TYPE_DH && staticKE->dhKey && staticKE->weOwnDH)
+    if (keyAlgo == WC_PK_TYPE_DH && staticKE->dhKey && staticKE->weOwnDH) {
         FreeDer(&staticKE->dhKey);
+    }
 #endif
 #ifdef HAVE_ECC
-    if (keyAlgo == WC_PK_TYPE_ECDH && staticKE->ecKey && staticKE->weOwnEC)
+    if (keyAlgo == WC_PK_TYPE_ECDH && staticKE->ecKey && staticKE->weOwnEC) {
         FreeDer(&staticKE->ecKey);
+    }
+#endif
+#ifdef HAVE_CURVE25519
+    if (keyAlgo == WC_PK_TYPE_CURVE25519 && staticKE->x25519Key && 
+                                                        staticKE->weOwnX25519) {
+        FreeDer(&staticKE->x25519Key);
+    }
 #endif
 
     switch (keyAlgo) {
     #ifndef NO_DH
         case WC_PK_TYPE_DH:
-            staticKE->dhKey = der;
+            staticKE->dhKey = der; der = NULL;
             staticKE->weOwnDH = 1;
             break;
     #endif
     #ifdef HAVE_ECC
         case WC_PK_TYPE_ECDH:
-            staticKE->ecKey = der;
+            staticKE->ecKey = der; der = NULL;
             staticKE->weOwnEC = 1;
             break;
+    #endif
+    #ifdef HAVE_CURVE25519
+        case WC_PK_TYPE_CURVE25519:
+            staticKE->x25519Key = der; der = NULL;
+            staticKE->weOwnX25519 = 1;
+            break;
     #endif
         default:
             /* not supported */
             ret = NOT_COMPILED_IN;
-            FreeDer(&der);
             break;
     }
 
+    if (ret != 0) {
+        FreeDer(&der);
+    }
+
     WOLFSSL_LEAVE("SetStaticEphemeralKey", ret);
 
     return ret;
@@ -54184,6 +54217,11 @@ static int GetStaticEphemeralKey(StaticKeyExchangeInfo_t* staticKE, int keyAlgo,
         case WC_PK_TYPE_ECDH:
             der = staticKE->ecKey;
             break;
+    #endif
+    #ifdef HAVE_CURVE25519
+        case WC_PK_TYPE_CURVE25519:
+            der = staticKE->x25519Key;
+            break;
     #endif
         default:
             /* not supported */

+ 17 - 4
src/tls.c

@@ -4611,7 +4611,7 @@ int TLSX_ValidateSupportedCurves(WOLFSSL* ssl, byte first, byte second) {
                     ephmSuite = 1;
                 break;
 
-    #ifdef WOLFSSL_STATIC_DH
+    #if defined(HAVE_ECC) && defined(WOLFSSL_STATIC_DH)
                 /* ECDH_RSA */
                 case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
                 case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
@@ -4632,7 +4632,7 @@ int TLSX_ValidateSupportedCurves(WOLFSSL* ssl, byte first, byte second) {
                     sig = 1;
                     key |= ssl->pkCurveOID == pkOid;
                 break;
-    #endif /* WOLFSSL_STATIC_DH */
+    #endif /* HAVE_ECC && WOLFSSL_STATIC_DH */
 #endif
                 default:
                     if (oid == ECC_X25519_OID && defOid == oid) {
@@ -6858,10 +6858,23 @@ static int TLSX_KeyShare_GenX25519Key(WOLFSSL *ssl, KeyShareEntry* kse)
         }
 
         /* Make an Curve25519 key. */
-        ret = wc_curve25519_init((curve25519_key*)kse->key);
+        ret = wc_curve25519_init_ex((curve25519_key*)kse->key, ssl->heap,
+            INVALID_DEVID);
         if (ret == 0) {
             key = (curve25519_key*)kse->key;
-            ret = wc_curve25519_make_key(ssl->rng, CURVE25519_KEYSIZE, key);
+        #ifdef WOLFSSL_STATIC_EPHEMERAL
+            if (ssl->staticKE.x25519Key) {
+                DerBuffer* keyDer = ssl->staticKE.x25519Key;
+                word32 idx = 0;
+                WOLFSSL_MSG("Using static X25519 key");
+                ret = wc_Curve25519PrivateKeyDecode(keyDer->buffer, &idx, key,
+                    keyDer->length);
+            }
+            else
+        #endif
+            {
+                ret = wc_curve25519_make_key(ssl->rng, CURVE25519_KEYSIZE, key);
+            }
         }
     }
 

+ 1 - 1
src/tls13.c

@@ -6547,7 +6547,7 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input,
         #ifdef HAVE_ED25519
             if (args->sigAlgo == ed25519_sa_algo &&
                                                   !ssl->peerEd25519KeyPresent) {
-                WOLFSSL_MSG("Peer sent ED22519 sig but not ED22519 cert");
+                WOLFSSL_MSG("Peer sent ED25519 sig but not ED25519 cert");
                 ret = SIG_VERIFY_E;
                 goto exit_dcv;
             }

+ 19 - 12
sslSniffer/sslSnifferTest/snifftest.c

@@ -97,20 +97,27 @@ enum {
     #define STORE_DATA_BLOCK_SZ 1024
 #endif
 
+#if defined(HAVE_ECC) && !defined(NO_ECC_SECP) && (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES))
+    #define DEFAULT_SERVER_EPH_KEY_ECC "../../certs/statickeys/ecc-secp256r1.pem"
+#else
+    #define DEFAULT_SERVER_EPH_KEY_ECC ""
+#endif
+#ifndef NO_DH
+    #define DEFAULT_SERVER_EPH_KEY_DH "../../certs/statickeys/dh-ffdhe2048.pem"
+#else
+    #define DEFAULT_SERVER_EPH_KEY_DH ""
+#endif
+#ifdef HAVE_CURVE25519
+    #define DEFAULT_SERVER_EPH_KEY_X25519 "../../certs/statickeys/x25519.pem"
+#else
+    #define DEFAULT_SERVER_EPH_KEY_X25519 ""
+#endif
 
-#define DEFAULT_SERVER_EPH_KEY_ECC "../../certs/statickeys/ecc-secp256r1.pem"
-#define DEFAULT_SERVER_EPH_KEY_DH  "../../certs/statickeys/dh-ffdhe2048.pem"
 #ifndef DEFAULT_SERVER_EPH_KEY
-    #if defined(HAVE_ECC) && !defined(NO_ECC_SECP) && \
-        (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES))
-        #if !defined(NO_DH)
-            #define DEFAULT_SERVER_EPH_KEY DEFAULT_SERVER_EPH_KEY_ECC "," DEFAULT_SERVER_EPH_KEY_DH
-        #else
-            #define DEFAULT_SERVER_EPH_KEY DEFAULT_SERVER_EPH_KEY_ECC
-        #endif
-    #elif !defined(NO_DH)
-        #define DEFAULT_SERVER_EPH_KEY DEFAULT_SERVER_EPH_KEY_DH
-    #endif
+    #define DEFAULT_SERVER_EPH_KEY \
+                DEFAULT_SERVER_EPH_KEY_ECC "," \
+                DEFAULT_SERVER_EPH_KEY_DH "," \
+                DEFAULT_SERVER_EPH_KEY_X25519
 #endif
 
 #define DEFAULT_SERVER_KEY_RSA "../../certs/server-key.pem"

+ 11 - 11
tests/api.c

@@ -20230,10 +20230,10 @@ static int test_wc_curve25519_shared_secret_ex(void)
 /*
  * Testing wc_curve25519_make_pub
  */
-static int test_wc_curve25519_make_pub (void)
+static int test_wc_curve25519_make_pub(void)
 {
     int ret = 0;
-#if defined(HAVE_CURVE25519)
+#ifdef HAVE_CURVE25519
     WC_RNG          rng;
     curve25519_key  key;
     byte            out[CURVE25519_KEYSIZE];
@@ -20248,45 +20248,45 @@ static int test_wc_curve25519_make_pub (void)
         }
     }
     if (ret == 0) {
-      ret = wc_curve25519_make_pub((int)sizeof out, out, (int)sizeof key.k.point, key.k.point);
+      ret = wc_curve25519_make_pub((int)sizeof(out), out, (int)sizeof(key.k), key.k);
     }
     /*test bad cases*/
     if (ret == 0) {
-        ret = wc_curve25519_make_pub((int)sizeof key.k.point - 1, key.k.point, (int)sizeof out, out);
+        ret = wc_curve25519_make_pub((int)sizeof(key.k) - 1, key.k, (int)sizeof out, out);
         if (ret == ECC_BAD_ARG_E) {
             ret = 0;
         }
     }
     if (ret == 0) {
-        ret = wc_curve25519_make_pub((int)sizeof out, out, (int)sizeof key.k.point, NULL);
+        ret = wc_curve25519_make_pub((int)sizeof out, out, (int)sizeof(key.k), NULL);
         if (ret == ECC_BAD_ARG_E) {
             ret = 0;
         }
     }
     if (ret == 0) {
-        ret = wc_curve25519_make_pub((int)sizeof out - 1, out, (int)sizeof key.k.point, key.k.point);
+        ret = wc_curve25519_make_pub((int)sizeof out - 1, out, (int)sizeof(key.k), key.k);
         if (ret == ECC_BAD_ARG_E) {
             ret = 0;
         }
     }
     if (ret == 0) {
-        ret = wc_curve25519_make_pub((int)sizeof out, NULL, (int)sizeof key.k.point, key.k.point);
+        ret = wc_curve25519_make_pub((int)sizeof out, NULL, (int)sizeof(key.k), key.k);
         if (ret == ECC_BAD_ARG_E) {
             ret = 0;
         }
     }
     if (ret == 0) {
         /* verify clamping test */
-        key.k.point[0] |= ~248;
-        ret = wc_curve25519_make_pub((int)sizeof out, out, (int)sizeof key.k.point, key.k.point);
+        key.k[0] |= ~248;
+        ret = wc_curve25519_make_pub((int)sizeof out, out, (int)sizeof(key.k), key.k);
         if (ret == ECC_BAD_ARG_E) {
             ret = 0;
         }
-        key.k.point[0] &= 248;
+        key.k[0] &= 248;
     }
     /* repeat the expected-to-succeed test. */
     if (ret == 0) {
-      ret = wc_curve25519_make_pub((int)sizeof out, out, (int)sizeof key.k.point, key.k.point);
+      ret = wc_curve25519_make_pub((int)sizeof out, out, (int)sizeof(key.k), key.k);
     }
 
     printf(resultFmt, ret == 0 ? passed : failed);

File diff suppressed because it is too large
+ 380 - 406
wolfcrypt/src/asn.c


+ 127 - 133
wolfcrypt/src/curve25519.c

@@ -57,6 +57,41 @@ const curve25519_set_type curve25519_sets[] = {
 
 static const unsigned char kCurve25519BasePoint[CURVE25519_KEYSIZE] = {9};
 
+/* Curve25519 private key must be less than order */
+/* These functions clamp private k and check it */
+static WC_INLINE int curve25519_priv_clamp(byte* priv)
+{
+    priv[0]  &= 248;
+    priv[CURVE25519_KEYSIZE-1] &= 127;
+    priv[CURVE25519_KEYSIZE-1] |= 64;
+    return 0;
+}
+static WC_INLINE int curve25519_priv_clamp_check(const byte* priv)
+{
+    /* check that private part of key has been clamped */
+    int ret = 0;
+    if ((priv[0] & ~248) ||
+        (priv[CURVE25519_KEYSIZE-1] & 128)) {
+        ret = ECC_BAD_ARG_E;
+    }
+    return ret;
+}
+
+static WC_INLINE void curve25519_copy_point(byte* out, const byte* point,
+    int endian)
+{
+    int i;
+    if (endian == EC25519_BIG_ENDIAN) {
+        /* put shared secret key in Big Endian format */
+        for (i = 0; i < CURVE25519_KEYSIZE; i++) {
+            out[i] = point[CURVE25519_KEYSIZE - i -1];
+        }
+    }
+    else { /* put shared secret key in Little Endian format */
+        XMEMCPY(out, point, CURVE25519_KEYSIZE);
+    }
+}
+
 /* compute the public key from an existing private key, using bare vectors.
  *
  * return value is propagated from curve25519() (0 on success), or
@@ -66,28 +101,29 @@ int wc_curve25519_make_pub(int public_size, byte* pub, int private_size,
                            const byte* priv)
 {
     int ret;
+#ifdef FREESCALE_LTC_ECC
+    const ECPoint* basepoint = nxp_ltc_curve25519_GetBasePoint();
+    ECPoint wc_pub;
+#endif
 
-    if ((public_size != CURVE25519_KEYSIZE) ||
+    if ( (public_size != CURVE25519_KEYSIZE) ||
         (private_size != CURVE25519_KEYSIZE)) {
         return ECC_BAD_ARG_E;
     }
-    if ((pub == NULL) || (priv == NULL))
+    if ((pub == NULL) || (priv == NULL)) {
         return ECC_BAD_ARG_E;
+    }
 
     /* check clamping */
-    if ((priv[0] & ~248) ||
-        (priv[CURVE25519_KEYSIZE-1] & 128)) {
-        return ECC_BAD_ARG_E;
-    }
+    ret = curve25519_priv_clamp_check(priv);
+    if (ret != 0)
+        return ret;
 
 #ifdef FREESCALE_LTC_ECC
-    {
-        const ECPoint* basepoint = nxp_ltc_curve25519_GetBasePoint();
-        ECPoint wc_pub;
-        /* input basepoint on Weierstrass curve */
-        ret = nxp_ltc_curve25519(&wc_pub, priv, basepoint, kLTC_Weierstrass);
-        if (ret == 0)
-            XMEMCPY(pub, wc_pub.point, CURVE25519_KEYSIZE);
+    /* input basepoint on Weierstrass curve */
+    ret = nxp_ltc_curve25519(&wc_pub, priv, basepoint, kLTC_Weierstrass);
+    if (ret == 0) {
+        XMEMCPY(pub, wc_pub.point, CURVE25519_KEYSIZE);
     }
 #else
     fe_init();
@@ -117,7 +153,7 @@ int wc_curve25519_generic(int public_size, byte* pub,
                           int basepoint_size, const byte* basepoint)
 {
 #ifdef FREESCALE_LTC_ECC
-    /* unsupported with NXP LTC, onlly supports single basepoint with
+    /* unsupported with NXP LTC, only supports single basepoint with
      * nxp_ltc_curve25519_GetBasePoint() */
     return WC_HW_E;
 #else
@@ -132,10 +168,9 @@ int wc_curve25519_generic(int public_size, byte* pub,
         return ECC_BAD_ARG_E;
 
     /* check clamping */
-    if ((priv[0] & ~248) ||
-        (priv[CURVE25519_KEYSIZE-1] & 128)) {
-        return ECC_BAD_ARG_E;
-    }
+    ret = curve25519_priv_clamp_check(priv);
+    if (ret != 0)
+        return ret;
 
     fe_init();
 
@@ -171,15 +206,12 @@ int wc_curve25519_make_priv(WC_RNG* rng, int keysize, byte* key)
 
     /* random number for private key */
     ret = wc_RNG_GenerateBlock(rng, key, keysize);
-    if (ret != 0)
-        return ret;
-
-    /* Clamp the private key */
-    key[0] &= 248;
-    key[CURVE25519_KEYSIZE-1] &= 63; /* same &=127 because |=64 after */
-    key[CURVE25519_KEYSIZE-1] |= 64;
+    if (ret == 0) {
+        /* Clamp the private key */
+        ret = curve25519_priv_clamp(key);
+    }
 
-    return 0;
+    return ret;
 }
 
 /* generate a new keypair.
@@ -203,11 +235,14 @@ int wc_curve25519_make_key(WC_RNG* rng, int keysize, curve25519_key* key)
     }
 #endif
 
-    ret = wc_curve25519_make_priv(rng, keysize, key->k.point);
-    if (ret < 0)
-        return ret;
-    return wc_curve25519_make_pub((int)sizeof(key->p.point), key->p.point,
-                                  (int)sizeof(key->k.point), key->k.point);
+    ret = wc_curve25519_make_priv(rng, keysize, key->k);
+    if (ret == 0) {
+        key->privSet = 1;
+        ret = wc_curve25519_make_pub((int)sizeof(key->p.point), key->p.point,
+                                     (int)sizeof(key->k), key->k);
+        key->pubSet = (ret == 0);
+    }
+    return ret;
 }
 
 #ifdef HAVE_CURVE25519_SHARED_SECRET
@@ -224,11 +259,7 @@ int wc_curve25519_shared_secret_ex(curve25519_key* private_key,
                                    curve25519_key* public_key,
                                    byte* out, word32* outlen, int endian)
 {
-#ifdef FREESCALE_LTC_ECC
-    ECPoint o = {{0}};
-#else
-    unsigned char o[CURVE25519_KEYSIZE];
-#endif
+    ECPoint o;
     int ret = 0;
 
     /* sanity check */
@@ -237,10 +268,17 @@ int wc_curve25519_shared_secret_ex(curve25519_key* private_key,
         return BAD_FUNC_ARG;
     }
 
-    /* avoid implementation fingerprinting */
-    if (public_key->p.point[CURVE25519_KEYSIZE-1] > 0x7F)
+    /* make sure we have a populated private and public key */
+    if (!private_key->privSet || !public_key->pubSet) {
+        return ECC_BAD_ARG_E;
+    }
+
+    /* avoid implementation fingerprinting - make sure signed bit is not set */
+    if (public_key->p.point[CURVE25519_KEYSIZE-1] & 0x80) {
         return ECC_BAD_ARG_E;
+    }
 
+    XMEMSET(&o, 0, sizeof(o));
 
 #ifdef WOLF_CRYPTO_CB
     if (private_key->devId != INVALID_DEVID) {
@@ -254,54 +292,28 @@ int wc_curve25519_shared_secret_ex(curve25519_key* private_key,
 
     #ifdef FREESCALE_LTC_ECC
         /* input point P on Curve25519 */
-        ret = nxp_ltc_curve25519(&o, private_key->k.point, &public_key->p,
+        ret = nxp_ltc_curve25519(&o, private_key->k, &public_key->p,
                                  kLTC_Curve25519);
     #else
         #if defined(USE_INTEL_SPEEDUP) || defined(WOLFSSL_ARMASM)
             SAVE_VECTOR_REGISTERS();
         #endif
 
-        ret = curve25519(o, private_key->k.point, public_key->p.point);
+        ret = curve25519(o.point, private_key->k, public_key->p.point);
 
         #if defined(USE_INTEL_SPEEDUP) || defined(WOLFSSL_ARMASM)
             RESTORE_VECTOR_REGISTERS();
         #endif
     #endif
     if (ret != 0) {
-        #ifdef FREESCALE_LTC_ECC
-            ForceZero(o.point, CURVE25519_KEYSIZE);
-            ForceZero(o.pointY, CURVE25519_KEYSIZE);
-        #else
-            ForceZero(o, CURVE25519_KEYSIZE);
-        #endif
+        ForceZero(&o, sizeof(o));
         return ret;
     }
 
-    if (endian == EC25519_BIG_ENDIAN) {
-        int i;
-        /* put shared secret key in Big Endian format */
-        for (i = 0; i < CURVE25519_KEYSIZE; i++)
-            #ifdef FREESCALE_LTC_ECC
-                out[i] = o.point[CURVE25519_KEYSIZE - i -1];
-            #else
-                out[i] = o[CURVE25519_KEYSIZE - i -1];
-            #endif
-    }
-    else /* put shared secret key in Little Endian format */
-        #ifdef FREESCALE_LTC_ECC
-            XMEMCPY(out, o.point, CURVE25519_KEYSIZE);
-        #else
-            XMEMCPY(out, o, CURVE25519_KEYSIZE);
-        #endif
-
+    curve25519_copy_point(out, o.point, endian);
     *outlen = CURVE25519_KEYSIZE;
 
-    #ifdef FREESCALE_LTC_ECC
-        ForceZero(o.point, CURVE25519_KEYSIZE);
-        ForceZero(o.pointY, CURVE25519_KEYSIZE);
-    #else
-        ForceZero(o, CURVE25519_KEYSIZE);
-    #endif
+    ForceZero(&o, sizeof(o));
 
     return ret;
 }
@@ -322,27 +334,29 @@ int wc_curve25519_export_public(curve25519_key* key, byte* out, word32* outLen)
 int wc_curve25519_export_public_ex(curve25519_key* key, byte* out,
                                    word32* outLen, int endian)
 {
-    if (key == NULL || out == NULL || outLen == NULL)
+    int ret = 0;
+
+    if (key == NULL || out == NULL || outLen == NULL) {
         return BAD_FUNC_ARG;
+    }
 
     /* check and set outgoing key size */
     if (*outLen < CURVE25519_KEYSIZE) {
         *outLen = CURVE25519_KEYSIZE;
         return ECC_BAD_ARG_E;
     }
-    *outLen = CURVE25519_KEYSIZE;
-
-    if (endian == EC25519_BIG_ENDIAN) {
-        int i;
 
-        /* read keys in Big Endian format */
-        for (i = 0; i < CURVE25519_KEYSIZE; i++)
-            out[i] = key->p.point[CURVE25519_KEYSIZE - i - 1];
+    /* calculate public if missing */
+    if (!key->pubSet) {
+        ret = wc_curve25519_make_pub((int)sizeof(key->p.point), key->p.point,
+                                     (int)sizeof(key->k), key->k);
+        key->pubSet = (ret == 0);
     }
-    else
-        XMEMCPY(out, key->p.point, CURVE25519_KEYSIZE);
+    /* export public point with endianess */
+    curve25519_copy_point(out, key->p.point, endian);
+    *outLen = CURVE25519_KEYSIZE;
 
-    return 0;
+    return ret;
 }
 
 #endif /* HAVE_CURVE25519_KEY_EXPORT */
@@ -362,33 +376,32 @@ int wc_curve25519_import_public(const byte* in, word32 inLen,
 int wc_curve25519_import_public_ex(const byte* in, word32 inLen,
                                 curve25519_key* key, int endian)
 {
+#ifdef FREESCALE_LTC_ECC
+    ltc_pkha_ecc_point_t ltcPoint;
+#endif
+
     /* sanity check */
-    if (key == NULL || in == NULL)
+    if (key == NULL || in == NULL) {
         return BAD_FUNC_ARG;
+    }
 
     /* check size of incoming keys */
-    if (inLen != CURVE25519_KEYSIZE)
+    if (inLen != CURVE25519_KEYSIZE) {
        return ECC_BAD_ARG_E;
-
-    if (endian == EC25519_BIG_ENDIAN) {
-        int i;
-
-        /* read keys in Big Endian format */
-        for (i = 0; i < CURVE25519_KEYSIZE; i++)
-            key->p.point[i] = in[CURVE25519_KEYSIZE - i - 1];
     }
-    else
-        XMEMCPY(key->p.point, in, inLen);
+
+    /* import public point with endianess */
+    curve25519_copy_point(key->p.point, in, endian);
+    key->pubSet = 1;
 
     key->dp = &curve25519_sets[0];
 
     /* LTC needs also Y coordinate - let's compute it */
-    #ifdef FREESCALE_LTC_ECC
-        ltc_pkha_ecc_point_t ltcPoint;
-        ltcPoint.X = &key->p.point[0];
-        ltcPoint.Y = &key->p.pointY[0];
-        LTC_PKHA_Curve25519ComputeY(&ltcPoint);
-    #endif
+#ifdef FREESCALE_LTC_ECC
+    ltcPoint.X = &key->p.point[0];
+    ltcPoint.Y = &key->p.pointY[0];
+    LTC_PKHA_Curve25519ComputeY(&ltcPoint);
+#endif
 
     return 0;
 }
@@ -481,17 +494,10 @@ int wc_curve25519_export_private_raw_ex(curve25519_key* key, byte* out,
         *outLen = CURVE25519_KEYSIZE;
         return ECC_BAD_ARG_E;
     }
-    *outLen = CURVE25519_KEYSIZE;
-
-    if (endian == EC25519_BIG_ENDIAN) {
-        int i;
 
-        /* put the key in Big Endian format */
-        for (i = 0; i < CURVE25519_KEYSIZE; i++)
-            out[i] = key->k.point[CURVE25519_KEYSIZE - i - 1];
-    }
-    else
-        XMEMCPY(out, key->k.point, CURVE25519_KEYSIZE);
+    /* export private scalar with endianess */
+    curve25519_copy_point(out, key->k, endian);
+    *outLen = CURVE25519_KEYSIZE;
 
     return 0;
 }
@@ -572,31 +578,23 @@ int wc_curve25519_import_private_ex(const byte* priv, word32 privSz,
                                     curve25519_key* key, int endian)
 {
     /* sanity check */
-    if (key == NULL || priv == NULL)
+    if (key == NULL || priv == NULL) {
         return BAD_FUNC_ARG;
+    }
 
     /* check size of incoming keys */
-    if ((int)privSz != CURVE25519_KEYSIZE)
+    if ((int)privSz != CURVE25519_KEYSIZE) {
         return ECC_BAD_ARG_E;
-
-    if (endian == EC25519_BIG_ENDIAN) {
-        int i;
-
-        /* read the key in Big Endian format */
-        for (i = 0; i < CURVE25519_KEYSIZE; i++)
-            key->k.point[i] = priv[CURVE25519_KEYSIZE - i - 1];
     }
-    else
-        XMEMCPY(key->k.point, priv, CURVE25519_KEYSIZE);
+
+    /* import private scalar with endianess */
+    curve25519_copy_point(key->k, priv, endian);
+    key->privSet = 1;
 
     key->dp = &curve25519_sets[0];
 
     /* Clamp the key */
-    key->k.point[0] &= 248;
-    key->k.point[privSz-1] &= 63; /* same &=127 because |=64 after */
-    key->k.point[privSz-1] |= 64;
-
-    return 0;
+    return curve25519_priv_clamp(key->k);
 }
 
 #endif /* HAVE_CURVE25519_KEY_IMPORT */
@@ -633,19 +631,16 @@ int wc_curve25519_init(curve25519_key* key)
 /* Clean the memory of a key */
 void wc_curve25519_free(curve25519_key* key)
 {
-   if (key == NULL)
+    if (key == NULL)
        return;
 
-   key->dp = NULL;
-   ForceZero(key->p.point, sizeof(key->p.point));
-   ForceZero(key->k.point, sizeof(key->k.point));
-   #ifdef FREESCALE_LTC_ECC
-       ForceZero(key->p.point, sizeof(key->p.pointY));
-       ForceZero(key->k.point, sizeof(key->k.pointY));
-   #endif
+    key->dp = NULL;
+    ForceZero(key->k, sizeof(key->k));
+    XMEMSET(&key->p, 0, sizeof(key->p));
+    key->pubSet = 0;
+    key->privSet = 0;
 }
 
-
 /* get key size */
 int wc_curve25519_size(curve25519_key* key)
 {
@@ -656,4 +651,3 @@ int wc_curve25519_size(curve25519_key* key)
 }
 
 #endif /*HAVE_CURVE25519*/
-

+ 56 - 15
wolfcrypt/src/curve448.c

@@ -42,6 +42,28 @@
     #include <wolfcrypt/src/misc.c>
 #endif
 
+int wc_curve448_make_pub(int public_size, byte* pub, int private_size,
+    const byte* priv)
+{
+    int ret;
+    unsigned char basepoint[CURVE448_KEY_SIZE] = {5};
+
+    if ((pub == NULL) || (priv == NULL)) {
+        return ECC_BAD_ARG_E;
+    }
+    if ((public_size  != CURVE448_PUB_KEY_SIZE) ||
+        (private_size != CURVE448_KEY_SIZE)) {
+        return ECC_BAD_ARG_E;
+    }
+
+    fe448_init();
+
+    /* compute public key */
+    ret = curve448(pub, priv, basepoint);
+
+    return ret;
+}
+
 
 /* Make a new curve448 private/public key.
  *
@@ -54,7 +76,6 @@
  */
 int wc_curve448_make_key(WC_RNG* rng, int keysize, curve448_key* key)
 {
-    unsigned char basepoint[CURVE448_KEY_SIZE] = {5};
     int  ret = 0;
 
     if ((key == NULL) || (rng == NULL)) {
@@ -67,21 +88,25 @@ int wc_curve448_make_key(WC_RNG* rng, int keysize, curve448_key* key)
     }
 
     if (ret == 0) {
-        fe448_init();
-
         /* random number for private key */
         ret = wc_RNG_GenerateBlock(rng, key->k, keysize);
     }
     if (ret == 0) {
-        /* Clamp the private key */
+        key->privSet = 1;
+
+        /* clamp private */
         key->k[0] &= 0xfc;
         key->k[CURVE448_KEY_SIZE-1] |= 0x80;
-
-        /* compute public key */
-        ret = curve448(key->p, key->k, basepoint);
-        if (ret != 0) {
-            ForceZero(key->k, keysize);
-            ForceZero(key->p, keysize);
+        
+        /* compute public */
+        ret = wc_curve448_make_pub((int)sizeof(key->p), key->p,
+                                   (int)sizeof(key->k), key->k);
+        if (ret == 0) {
+            key->pubSet = 1;
+        }
+        else {
+            ForceZero(key->k, sizeof(key->k));
+            XMEMSET(key->p, 0, sizeof(key->p));
         }
     }
 
@@ -137,6 +162,10 @@ int wc_curve448_shared_secret_ex(curve448_key* private_key,
                         (outLen == NULL) || (*outLen < CURVE448_PUB_KEY_SIZE)) {
         ret = BAD_FUNC_ARG;
     }
+    /* make sure we have a populated private and public key */
+    if (ret == 0 && (!private_key->privSet || !public_key->pubSet)) {
+        ret = ECC_BAD_ARG_E;
+    }
 
     if (ret == 0) {
         ret = curve448(o, private_key->k, public_key->p);
@@ -207,9 +236,16 @@ int wc_curve448_export_public_ex(curve448_key* key, byte* out, word32* outLen,
         *outLen = CURVE448_PUB_KEY_SIZE;
         ret = ECC_BAD_ARG_E;
     }
+    if (ret == 0) {
+        /* calculate public if missing */
+        if (!key->pubSet) {
+            ret = wc_curve448_make_pub((int)sizeof(key->p), key->p,
+                                       (int)sizeof(key->k), key->k);
+            key->pubSet = (ret == 0);
+        }
+    }
     if (ret == 0) {
         *outLen = CURVE448_PUB_KEY_SIZE;
-
         if (endian == EC448_BIG_ENDIAN) {
             /* read keys in Big Endian format */
             for (i = 0; i < CURVE448_PUB_KEY_SIZE; i++) {
@@ -278,6 +314,7 @@ int wc_curve448_import_public_ex(const byte* in, word32 inLen,
         }
         else
             XMEMCPY(key->p, in, inLen);
+        key->pubSet = 1;
     }
 
     return ret;
@@ -569,6 +606,8 @@ int wc_curve448_import_private_ex(const byte* priv, word32 privSz,
         /* Clamp the key */
         key->k[0] &= 0xfc;
         key->k[CURVE448_KEY_SIZE-1] |= 0x80;
+
+        key->privSet = 1;
     }
 
     return ret;
@@ -607,10 +646,12 @@ int wc_curve448_init(curve448_key* key)
  */
 void wc_curve448_free(curve448_key* key)
 {
-   if (key != NULL) {
-       ForceZero(key->p, sizeof(key->p));
-       ForceZero(key->k, sizeof(key->k));
-   }
+    if (key != NULL) {
+        ForceZero(key->k, sizeof(key->k));
+        XMEMSET(key->p, 0, sizeof(key->p));
+        key->pubSet = 0;
+        key->privSet = 0;
+    }
 }
 
 

+ 108 - 10
wolfcrypt/test/test.c

@@ -16278,7 +16278,11 @@ exit_gen_test:
 static int dh_generate_test(WC_RNG *rng)
 {
     int    ret = 0;
-    DhKey  smallKey;
+#ifdef WOLFSSL_SMALL_STACK
+    DhKey  *smallKey = (DhKey*)XMALLOC(sizeof(DhKey), HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
+#else
+    DhKey  smallKey[1];
+#endif
     byte   p[2] = { 0, 5 };
     byte   g[2] = { 0, 2 };
 #if !defined(WOLFSSL_SP_MATH)
@@ -16294,7 +16298,13 @@ static int dh_generate_test(WC_RNG *rng)
     word32 pubSz = sizeof(pub);
 #endif
 
-    ret = wc_InitDhKey_ex(&smallKey, HEAP_HINT, devId);
+#ifdef WOLFSSL_SMALL_STACK
+    if (smallKey == NULL) {
+        ERROR_OUT(-8010, exit_gen_test);
+    }
+#endif
+
+    ret = wc_InitDhKey_ex(smallKey, HEAP_HINT, devId);
     if (ret != 0)
         return -8010;
 
@@ -16308,32 +16318,32 @@ static int dh_generate_test(WC_RNG *rng)
     if (ret != BAD_FUNC_ARG) {
         ERROR_OUT(-8012, exit_gen_test);
     }
-    ret = wc_DhSetKey(&smallKey, NULL, sizeof(p), g, sizeof(g));
+    ret = wc_DhSetKey(smallKey, NULL, sizeof(p), g, sizeof(g));
     if (ret != BAD_FUNC_ARG) {
         ERROR_OUT(-8013, exit_gen_test);
     }
-    ret = wc_DhSetKey(&smallKey, p, 0, g, sizeof(g));
+    ret = wc_DhSetKey(smallKey, p, 0, g, sizeof(g));
     if (ret != BAD_FUNC_ARG) {
         ERROR_OUT(-8014, exit_gen_test);
     }
-    ret = wc_DhSetKey(&smallKey, p, sizeof(p), NULL, sizeof(g));
+    ret = wc_DhSetKey(smallKey, p, sizeof(p), NULL, sizeof(g));
     if (ret != BAD_FUNC_ARG) {
         ERROR_OUT(-8015, exit_gen_test);
     }
-    ret = wc_DhSetKey(&smallKey, p, sizeof(p), g, 0);
+    ret = wc_DhSetKey(smallKey, p, sizeof(p), g, 0);
     if (ret != BAD_FUNC_ARG) {
         ERROR_OUT(-8016, exit_gen_test);
     }
-    ret = wc_DhSetKey(&smallKey, p, sizeof(p), g, sizeof(g));
+    ret = wc_DhSetKey(smallKey, p, sizeof(p), g, sizeof(g));
     if (ret != 0) {
         ERROR_OUT(-8017, exit_gen_test);
     }
 
 #if !defined(WOLFSSL_SP_MATH)
     /* Use API. */
-    ret = wc_DhGenerateKeyPair(&smallKey, rng, priv, &privSz, pub, &pubSz);
+    ret = wc_DhGenerateKeyPair(smallKey, rng, priv, &privSz, pub, &pubSz);
 #if defined(WOLFSSL_ASYNC_CRYPT)
-    ret = wc_AsyncWait(ret, &smallKey.asyncDev, WC_ASYNC_FLAG_NONE);
+    ret = wc_AsyncWait(ret, &smallKey->asyncDev, WC_ASYNC_FLAG_NONE);
 #endif
     if (ret != 0) {
         ret = -8018;
@@ -16344,7 +16354,12 @@ static int dh_generate_test(WC_RNG *rng)
 #endif
 
 exit_gen_test:
-    wc_FreeDhKey(&smallKey);
+    wc_FreeDhKey(smallKey);
+#ifdef WOLFSSL_SMALL_STACK
+    if (smallKey != NULL) {
+        XFREE(smallKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
+    }
+#endif
 
     return ret;
 }
@@ -24900,6 +24915,83 @@ static int curve25519_check_public_test(void)
 
 #endif /* HAVE_CURVE25519_SHARED_SECRET && HAVE_CURVE25519_KEY_IMPORT */
 
+#if defined(HAVE_CURVE25519_KEY_EXPORT) && defined(HAVE_CURVE25519_KEY_IMPORT)
+static int curve255519_der_test(void)
+{
+    int ret = 0;
+    /* certs/statickeys/x25519.der */
+    const byte kCurve25519PrivDer[] = {
+        0x30, 0x2E, 0x02, 0x01, 0x00, 0x30, 0x05, 0x06, 0x03, 0x2B, 0x65, 0x6E,
+        0x04, 0x22, 0x04, 0x20, 0x78, 0x8E, 0x31, 0x5C, 0x33, 0xA9, 0x19, 0xC0,
+        0x5E, 0x36, 0x70, 0x1B, 0xA4, 0xE8, 0xEF, 0xC1, 0x89, 0x8C, 0xB3, 0x15,
+        0xC6, 0x79, 0xD3, 0xAC, 0x22, 0x00, 0xAE, 0xFA, 0xB3, 0xB7, 0x0F, 0x78
+    };
+    /* certs/statickeys/x25519-pub.der */
+    const byte kCurve25519PubDer[] = {
+        0x30, 0x2A, 0x30, 0x05, 0x06, 0x03, 0x2B, 0x65, 0x6E, 0x03, 0x21, 0x00,
+        0x09, 0xBC, 0x8C, 0xC7, 0x45, 0x0D, 0xC1, 0xC2, 0x02, 0x57, 0x9A, 0x68,
+        0x3A, 0xFD, 0x7A, 0xA8, 0xA5, 0x2F, 0xF0, 0x99, 0x39, 0x98, 0xEA, 0x26,
+        0xA2, 0x5B, 0x38, 0xFD, 0x96, 0xDB, 0x2A, 0x26
+    };
+    curve25519_key key;
+    byte output[128];
+    word32 outputSz = 128;
+    word32 idx;
+
+    if (wc_curve25519_init_ex(&key, HEAP_HINT, devId) != 0) {
+        return -10723;
+    }
+
+    /* Test decode / encode of Curve25519 private key only */
+    if (ret == 0) {
+        idx = 0;
+        ret = wc_Curve25519PrivateKeyDecode(kCurve25519PrivDer, &idx, &key,
+            (word32)sizeof(kCurve25519PrivDer));
+    }
+    if (ret == 0) {
+        outputSz = (word32)sizeof(output);
+        ret = wc_Curve25519PrivateKeyToDer(&key, output, outputSz);
+        if (ret >= 0) {
+            outputSz = ret;
+            ret = 0;
+        }
+        else {
+            ret = -10724;
+        }
+    }
+    if (ret == 0 && (outputSz != (word32)sizeof(kCurve25519PrivDer) ||
+                     XMEMCMP(output, kCurve25519PrivDer, outputSz) != 0)) {
+        ret = -10725;
+    }
+
+    /* Test decode / encode of Curve25519 public key only */
+    if (ret == 0) {
+        idx = 0;
+        ret = wc_Curve25519PublicKeyDecode(kCurve25519PubDer, &idx, &key,
+            (word32)sizeof(kCurve25519PubDer));
+    }
+    if (ret == 0) {
+        outputSz = (word32)sizeof(output);
+        ret = wc_Curve25519PublicKeyToDer(&key, output, outputSz, 1);
+        if (ret >= 0) {
+            outputSz = ret;
+            ret = 0;
+        }
+        else {
+            ret = -10726;
+        }
+    }
+    if (ret == 0 && (outputSz != (word32)sizeof(kCurve25519PubDer) ||
+                     XMEMCMP(output, kCurve25519PubDer, outputSz) != 0)) {
+        ret = -10727;
+    }
+
+    wc_curve25519_free(&key);
+
+    return ret;
+}
+#endif /* HAVE_CURVE25519_KEY_EXPORT && HAVE_CURVE25519_KEY_IMPORT */
+
 WOLFSSL_TEST_SUBROUTINE int curve25519_test(void)
 {
     WC_RNG  rng;
@@ -25082,6 +25174,12 @@ WOLFSSL_TEST_SUBROUTINE int curve25519_test(void)
         return ret;
 #endif /* HAVE_CURVE25519_SHARED_SECRET && HAVE_CURVE25519_KEY_IMPORT */
 
+#if defined(HAVE_CURVE25519_KEY_IMPORT) && defined(HAVE_CURVE25519_KEY_IMPORT)
+    ret = curve255519_der_test();
+    if (ret != 0)
+        return ret;
+#endif
+
     /* clean up keys when done */
     wc_curve25519_free(&pubKey);
     wc_curve25519_free(&userB);

+ 7 - 0
wolfssl/internal.h

@@ -2763,6 +2763,10 @@ typedef struct {
 #ifdef HAVE_ECC
     DerBuffer* ecKey;
 #endif
+#ifdef HAVE_CURVE25519
+    DerBuffer* x25519Key;
+#endif
+
     /* bits */
 #ifndef NO_DH
     byte weOwnDH:1;
@@ -2770,6 +2774,9 @@ typedef struct {
 #ifdef HAVE_ECC
     byte weOwnEC:1;
 #endif
+#ifdef HAVE_CURVE25519
+    byte weOwnX25519:1;
+#endif
 } StaticKeyExchangeInfo_t;
 #endif
 

+ 16 - 10
wolfssl/wolfcrypt/asn.h

@@ -47,7 +47,7 @@ that can be serialized and deserialized in a cross-platform way.
 
 /* fips declare of RsaPrivateKeyDecode @wc_fips */
 #if defined(HAVE_FIPS) && !defined(NO_RSA) && \
-	(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
+    (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
     #include <cyassl/ctaocrypt/rsa.h>
 #endif
 
@@ -160,7 +160,7 @@ enum ASNItem_DataType {
 
 /* A template entry describing an ASN.1 item. */
 typedef struct ASNItem {
-    /* Depth of ASN.1 item - how many consturcted ASN.1 items above. */
+    /* Depth of ASN.1 item - how many constructed ASN.1 items above. */
     byte depth;
     /* BER/DER tag to expect. */
     byte tag;
@@ -232,7 +232,7 @@ typedef struct ASNGetData {
         struct {
             /* Buffer to hold ASN.1 data. */
             byte*   data;
-            /* Maxumum length of buffer. */
+            /* Maximum length of buffer. */
             word32* length;
         } buffer;
         /* Refernce to ASN.1 item's data. */
@@ -366,7 +366,7 @@ WOLFSSL_LOCAL void SetASN_OID(ASNSetData *dataASN, int oid, int oidType);
         (dataASN)->data.mp  = num;                                     \
     } while (0)
 
-/* Setup ASN data item to get a positve or negative number into an mp_int.
+/* Setup ASN data item to get a positive or negative number into an mp_int.
  *
  * @param [in] dataASN  Dynamic ASN data item.
  * @param [in] num      Multi-precision number object.
@@ -572,7 +572,7 @@ WOLFSSL_LOCAL void SetASN_OID(ASNSetData *dataASN, int oid, int oidType);
 #define GetASNItem_UnusedBits(dataASN)                                 \
     (*(dataASN.data.ref.data - 1))
 
-/* Set the data items at indeces start to end inclusive to not be encoded.
+/* Set the data items at indices start to end inclusive to not be encoded.
  *
  * @param [in] dataASN  Dynamic ASN data item.
  * @param [in] start    First item not to be encoded.
@@ -962,8 +962,10 @@ enum Key_Sum {
     RSAk     = 645,
     NTRUk    = 274,
     ECDSAk   = 518,
-    ED25519k = 256,
-    ED448k   = 257,
+    ED25519k = 256, /* 1.3.101.112 */
+    X25519k  = 254, /* 1.3.101.110 */
+    ED448k   = 257, /* 1.3.101.113 */
+    X448k    = 255, /* 1.3.101.111 */
     DHk      = 647, /* dhKeyAgreement OID: 1.2.840.113549.1.3.1 */
 };
 
@@ -1031,8 +1033,11 @@ enum Extensions_Sum {
     ISSUE_ALT_NAMES_OID       = 132, /* 2.5.29.18 */
     TLS_FEATURE_OID           = 92,  /* 1.3.6.1.5.5.7.1.24 */
     NETSCAPE_CT_OID           = 753, /* 2.16.840.1.113730.1.1 */
-    OCSP_NOCHECK_OID          = 121  /* 1.3.6.1.5.5.7.48.1.5
+    OCSP_NOCHECK_OID          = 121, /* 1.3.6.1.5.5.7.48.1.5
                                          id-pkix-ocsp-nocheck */
+
+    AKEY_PACKAGE_OID          = 1048 /* 2.16.840.1.101.2.1.2.78.5
+                                        RFC 5958  - Asymmetric Key Packages */
 };
 
 enum CertificatePolicy_Sum {
@@ -1886,7 +1891,7 @@ enum Ocsp_Response_Status {
     OCSP_INTERNAL_ERROR    = 2, /* Internal error in issuer */
     OCSP_TRY_LATER         = 3, /* Try again later */
     OCSP_SIG_REQUIRED      = 5, /* Must sign the request (4 is skipped) */
-    OCSP_UNAUTHROIZED      = 6  /* Request unauthorized */
+    OCSP_UNAUTHORIZED      = 6  /* Request unauthorized */
 };
 
 
@@ -1929,7 +1934,8 @@ struct CertStatus {
     byte nextDate[MAX_DATE_SIZE];
     byte thisDateFormat;
     byte nextDateFormat;
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || defined(HAVE_LIGHTY)
+#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || \
+    defined(WOLFSSL_HAPROXY) || defined(HAVE_LIGHTY)
     WOLFSSL_ASN1_TIME thisDateParsed;
     WOLFSSL_ASN1_TIME nextDateParsed;
     byte* thisDateAsn;

+ 56 - 33
wolfssl/wolfcrypt/asn_public.h

@@ -47,10 +47,18 @@ This library defines the interface APIs for X509 certificates.
     typedef struct ed25519_key ed25519_key;
     #define WC_ED25519KEY_TYPE_DEFINED
 #endif
+#ifndef WC_CURVE25519KEY_TYPE_DEFINED
+    typedef struct curve25519_key curve25519_key;
+    #define WC_CURVE25519KEY_TYPE_DEFINED
+#endif
 #ifndef WC_ED448KEY_TYPE_DEFINED
     typedef struct ed448_key ed448_key;
     #define WC_ED448KEY_TYPE_DEFINED
 #endif
+#ifndef WC_CURVE448KEY_TYPE_DEFINED
+    typedef struct curve448_key curve448_key;
+    #define WC_CURVE448KEY_TYPE_DEFINED
+#endif
 #ifndef WC_RSAKEY_TYPE_DEFINED
     typedef struct RsaKey RsaKey;
     #define WC_RSAKEY_TYPE_DEFINED
@@ -571,54 +579,69 @@ WOLFSSL_API int wc_DhPrivKeyToDer(DhKey* key, byte* out, word32* outSz);
     WOLFSSL_API int wc_EccPublicKeyDerSize(ecc_key*, int with_AlgCurve);
 #endif
 
+/* RFC 5958 (Asymmetric Key Packages) */
+#if !defined(WC_ENABLE_ASYM_KEY_EXPORT) && \
+    ((defined(HAVE_ED25519)    && defined(HAVE_ED25519_KEY_EXPORT)) || \
+     (defined(HAVE_CURVE25519) && defined(HAVE_CURVE25519_KEY_EXPORT)) || \
+     (defined(HAVE_ED448)      && defined(HAVE_ED448_KEY_EXPORT)) || \
+     (defined(HAVE_CURVE448)   && defined(HAVE_CURVE448_KEY_EXPORT)))
+    #define WC_ENABLE_ASYM_KEY_EXPORT
+#endif
+
+#if !defined(WC_ENABLE_ASYM_KEY_IMPORT) && \
+    ((defined(HAVE_ED25519)    && defined(HAVE_ED25519_KEY_IMPORT)) || \
+     (defined(HAVE_CURVE25519) && defined(HAVE_CURVE25519_KEY_IMPORT)) || \
+     (defined(HAVE_ED448)      && defined(HAVE_ED448_KEY_IMPORT)) || \
+     (defined(HAVE_CURVE448)   && defined(HAVE_CURVE448_KEY_IMPORT)))
+    #define WC_ENABLE_ASYM_KEY_IMPORT
+#endif
+
 #ifdef HAVE_ED25519
-    /* private key helpers */
 #ifdef HAVE_ED25519_KEY_IMPORT
-    WOLFSSL_API int wc_Ed25519PrivateKeyDecode(const byte*, word32*,
-                                               ed25519_key*, word32);
+WOLFSSL_API int wc_Ed25519PrivateKeyDecode(const byte*, word32*, ed25519_key*, word32);
+WOLFSSL_API int wc_Ed25519PublicKeyDecode(const byte*, word32*, ed25519_key*, word32);
 #endif
-
 #ifdef HAVE_ED25519_KEY_EXPORT
-    WOLFSSL_API int wc_Ed25519KeyToDer(ed25519_key* key, byte* output,
-                                       word32 inLen);
-    WOLFSSL_API int wc_Ed25519PrivateKeyToDer(ed25519_key* key, byte* output,
-                                              word32 inLen);
+WOLFSSL_API int wc_Ed25519KeyToDer(ed25519_key*, byte*, word32);
+WOLFSSL_API int wc_Ed25519PrivateKeyToDer(ed25519_key*, byte*, word32);
+WOLFSSL_API int wc_Ed25519PublicKeyToDer(ed25519_key*, byte*, word32, int);
 #endif
+#endif /* HAVE_ED25519 */
 
-    /* public key helper */
-    WOLFSSL_API int wc_Ed25519PublicKeyDecode(const byte*, word32*,
-                                              ed25519_key*, word32);
-    #if (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN)) && \
-        defined(HAVE_ED25519_KEY_EXPORT)
-
-        WOLFSSL_API int wc_Ed25519PublicKeyToDer(ed25519_key*, byte* output,
-                                               word32 inLen, int with_AlgCurve);
-    #endif
+#ifdef HAVE_CURVE25519
+#ifdef HAVE_CURVE25519_KEY_IMPORT
+WOLFSSL_API int wc_Curve25519PrivateKeyDecode(const byte*, word32*, curve25519_key*, word32);
+WOLFSSL_API int wc_Curve25519PublicKeyDecode(const byte*, word32*, curve25519_key*, word32);
+#endif
+#ifdef HAVE_CURVE25519_KEY_EXPORT
+WOLFSSL_API int wc_Curve25519PrivateKeyToDer(curve25519_key*, byte*, word32);
+WOLFSSL_API int wc_Curve25519PublicKeyToDer(curve25519_key*, byte*, word32, int);
 #endif
+#endif /* HAVE_CURVE25519 */
 
 #ifdef HAVE_ED448
-    /* private key helpers */
 #ifdef HAVE_ED448_KEY_IMPORT
-    WOLFSSL_API int wc_Ed448PrivateKeyDecode(const byte*, word32*,
-                                             ed448_key*, word32);
+WOLFSSL_API int wc_Ed448PrivateKeyDecode(const byte*, word32*, ed448_key*, word32);
+WOLFSSL_API int wc_Ed448PublicKeyDecode(const byte*, word32*, ed448_key*, word32);
 #endif
-
 #ifdef HAVE_ED448_KEY_EXPORT
-    WOLFSSL_API int wc_Ed448KeyToDer(ed448_key* key, byte* output,
-                                     word32 inLen);
-    WOLFSSL_API int wc_Ed448PrivateKeyToDer(ed448_key* key, byte* output,
-                                            word32 inLen);
+WOLFSSL_API int wc_Ed448KeyToDer(ed448_key*, byte*, word32);
+WOLFSSL_API int wc_Ed448PrivateKeyToDer(ed448_key*, byte*, word32);
+WOLFSSL_API int wc_Ed448PublicKeyToDer(ed448_key*, byte*, word32, int);
 #endif
+#endif /* HAVE_ED448 */
 
-    /* public key helper */
-    WOLFSSL_API int wc_Ed448PublicKeyDecode(const byte*, word32*,
-                                            ed448_key*, word32);
-    #if (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN)) && \
-        defined(HAVE_ED448_KEY_EXPORT)
-        WOLFSSL_API int wc_Ed448PublicKeyToDer(ed448_key*, byte* output,
-                                               word32 inLen, int with_AlgCurve);
-    #endif
+#ifdef HAVE_CURVE448
+#ifdef HAVE_CURVE448_KEY_IMPORT
+WOLFSSL_API int wc_Curve448PrivateKeyDecode(const byte*, word32*, curve448_key*, word32);
+WOLFSSL_API int wc_Curve448PublicKeyDecode(const byte*, word32*, curve448_key*, word32);
 #endif
+#ifdef HAVE_CURVE448_KEY_EXPORT
+WOLFSSL_API int wc_Curve448PrivateKeyToDer(curve448_key*, byte*, word32);
+WOLFSSL_API int wc_Curve448PublicKeyToDer(curve448_key*, byte*, word32, int);
+#endif
+#endif /* HAVE_CURVE448 */
+
 
 /* DER encode signature */
 WOLFSSL_API word32 wc_EncodeSignature(byte* out, const byte* digest,

+ 15 - 5
wolfssl/wolfcrypt/curve25519.h

@@ -61,11 +61,17 @@ typedef struct {
  * the mathematical functions used the endianness */
 typedef struct {
     byte point[CURVE25519_KEYSIZE];
-    #ifdef FREESCALE_LTC_ECC
-        byte pointY[CURVE25519_KEYSIZE];
-    #endif
+#ifdef FREESCALE_LTC_ECC
+    byte pointY[CURVE25519_KEYSIZE];
+#endif
+    byte pointSz;
 } ECPoint;
 
+#ifndef WC_CURVE25519KEY_TYPE_DEFINED
+    typedef struct curve25519_key curve25519_key;
+    #define WC_CURVE25519KEY_TYPE_DEFINED
+#endif
+
 /* A CURVE25519 Key */
 typedef struct curve25519_key {
     int idx;            /* Index into the ecc_sets[] for the parameters of
@@ -73,8 +79,8 @@ typedef struct curve25519_key {
                            curve in dp */
     const curve25519_set_type* dp;   /* domain parameters, either points to
                                    curves (idx >= 0) or user supplied */
-    ECPoint   p;        /* public key  */
-    ECPoint   k;        /* private key */
+    ECPoint   p;                     /* public point for key  */
+    byte      k[CURVE25519_KEYSIZE]; /* private scaler for key */
 
 #ifdef WOLFSSL_ASYNC_CRYPT
     WC_ASYNC_DEV asyncDev;
@@ -82,6 +88,10 @@ typedef struct curve25519_key {
 #if defined(WOLF_CRYPTO_CB)
     int devId;
 #endif
+
+    /* bit fields */
+    byte pubSet:1;
+    byte privSet:1;
 } curve25519_key;
 
 enum {

+ 12 - 0
wolfssl/wolfcrypt/curve448.h

@@ -43,6 +43,10 @@
 #define CURVE448_KEY_SIZE        56
 #define CURVE448_PUB_KEY_SIZE    56
 
+#ifndef WC_CURVE448KEY_TYPE_DEFINED
+    typedef struct curve448_key curve448_key;
+    #define WC_CURVE448KEY_TYPE_DEFINED
+#endif
 
 /* A CURVE448 Key */
 typedef struct curve448_key {
@@ -52,6 +56,10 @@ typedef struct curve448_key {
 #ifdef WOLFSSL_ASYNC_CRYPT
     WC_ASYNC_DEV asyncDev;
 #endif
+
+    /* bit fields */
+    byte pubSet:1;
+    byte privSet:1;
 } curve448_key;
 
 enum {
@@ -62,6 +70,10 @@ enum {
 WOLFSSL_API
 int wc_curve448_make_key(WC_RNG* rng, int keysize, curve448_key* key);
 
+WOLFSSL_API
+int wc_curve448_make_pub(int public_size, byte* pub, int private_size,
+                           const byte* priv);
+
 WOLFSSL_API
 int wc_curve448_shared_secret(curve448_key* private_key,
                               curve448_key* public_key,

+ 7 - 1
wolfssl/wolfcrypt/ecc.h

@@ -180,6 +180,10 @@ enum {
 #endif
 };
 
+#endif /* HAVE_ECC */
+
+#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
+    defined(HAVE_CURVE448) || defined(WOLFCRYPT_HAVE_SAKKE)
 /* Curve Types */
 typedef enum ecc_curve_id {
     ECC_CURVE_INVALID = -1,
@@ -227,7 +231,6 @@ typedef enum ecc_curve_id {
 #ifdef HAVE_CURVE448
     ECC_X448,
 #endif
-
 #ifdef WOLFCRYPT_HAVE_SAKKE
     ECC_SAKKE_1,
 #endif
@@ -237,6 +240,9 @@ typedef enum ecc_curve_id {
 #endif
     ECC_CURVE_MAX
 } ecc_curve_id;
+#endif
+
+#ifdef HAVE_ECC
 
 #ifdef HAVE_OID_ENCODING
 typedef word16 ecc_oid_t;

Some files were not shown because too many files changed in this diff