diff --git a/IDE/iotsafe/memory-tls.c b/IDE/iotsafe/memory-tls.c index e5f8036e8..fd095b705 100644 --- a/IDE/iotsafe/memory-tls.c +++ b/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 */ } } diff --git a/certs/statickeys/gen-static.sh b/certs/statickeys/gen-static.sh index dc92757db..681a77edf 100644 --- a/certs/statickeys/gen-static.sh +++ b/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 diff --git a/certs/statickeys/include.am b/certs/statickeys/include.am index 123764dd5..84641be10 100644 --- a/certs/statickeys/include.am +++ b/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 diff --git a/certs/statickeys/x25519-pub.der b/certs/statickeys/x25519-pub.der new file mode 100644 index 000000000..c7458a3fe Binary files /dev/null and b/certs/statickeys/x25519-pub.der differ diff --git a/certs/statickeys/x25519-pub.pem b/certs/statickeys/x25519-pub.pem new file mode 100644 index 000000000..19fab5bb0 --- /dev/null +++ b/certs/statickeys/x25519-pub.pem @@ -0,0 +1,3 @@ +-----BEGIN PUBLIC KEY----- +MCowBQYDK2VuAyEACbyMx0UNwcICV5poOv16qKUv8Jk5mOomols4/ZbbKiY= +-----END PUBLIC KEY----- diff --git a/certs/statickeys/x25519.der b/certs/statickeys/x25519.der new file mode 100644 index 000000000..916a5d797 Binary files /dev/null and b/certs/statickeys/x25519.der differ diff --git a/certs/statickeys/x25519.pem b/certs/statickeys/x25519.pem new file mode 100644 index 000000000..92f96ca2b --- /dev/null +++ b/certs/statickeys/x25519.pem @@ -0,0 +1,3 @@ +-----BEGIN PRIVATE KEY----- +MC4CAQAwBQYDK2VuBCIEIHiOMVwzqRnAXjZwG6To78GJjLMVxnnTrCIArvqztw94 +-----END PRIVATE KEY----- diff --git a/configure.ac b/configure.ac index 6a4a3e490..312abb893 100644 --- a/configure.ac +++ b/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" && \ diff --git a/examples/server/server.c b/examples/server/server.c index e67125318..ec95f7659 100644 --- a/examples/server/server.c +++ b/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) { diff --git a/scripts/include.am b/scripts/include.am index dc47aad84..2d2ca7948 100644 --- a/scripts/include.am +++ b/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 \ diff --git a/scripts/sniffer-testsuite.test b/scripts/sniffer-testsuite.test index 083974bcf..d01bf6e8b 100755 --- a/scripts/sniffer-testsuite.test +++ b/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 diff --git a/scripts/sniffer-tls13-gen.sh b/scripts/sniffer-tls13-gen.sh index a98e7b4d4..b3421a785 100755 --- a/scripts/sniffer-tls13-gen.sh +++ b/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 +# 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 + # 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 diff --git a/scripts/sniffer-tls13-x25519.pcap b/scripts/sniffer-tls13-x25519.pcap new file mode 100644 index 000000000..193271282 Binary files /dev/null and b/scripts/sniffer-tls13-x25519.pcap differ diff --git a/src/internal.c b/src/internal.c index 7c3b90038..82101ec0c 100644 --- a/src/internal.c +++ b/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 */ diff --git a/src/ocsp.c b/src/ocsp.c index 3b2dfce6d..b7a2d9c15 100644 --- a/src/ocsp.c +++ b/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)"; diff --git a/src/sniffer.c b/src/sniffer.c index 2336f0bdc..8a13eb71e 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -91,6 +91,20 @@ #include #include #include + +#ifndef NO_RSA + #include +#endif +#ifndef NO_DH + #include +#endif +#ifdef HAVE_ECC + #include +#endif +#ifdef HAVE_CURVE25519 + #include +#endif + #ifdef NO_INLINE #include #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 } diff --git a/src/ssl.c b/src/ssl.c index c0db9e4d5..fa55639e6 100644 --- a/src/ssl.c +++ b/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 */ diff --git a/src/tls.c b/src/tls.c index 114800e02..06c66344f 100644 --- a/src/tls.c +++ b/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); + } } } diff --git a/src/tls13.c b/src/tls13.c index 13e87ef70..99e40a1cd 100644 --- a/src/tls13.c +++ b/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; } diff --git a/sslSniffer/sslSnifferTest/snifftest.c b/sslSniffer/sslSnifferTest/snifftest.c index e95d5dd68..4e0a4fe8d 100644 --- a/sslSniffer/sslSnifferTest/snifftest.c +++ b/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" diff --git a/tests/api.c b/tests/api.c index 2d5404fb1..fb3a044d0 100644 --- a/tests/api.c +++ b/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); diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 9ecbe0a87..3a5688c41 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -122,10 +122,16 @@ ASN Options: #ifdef HAVE_ED25519 #include #endif +#ifdef HAVE_CURVE25519 + #include +#endif #ifdef HAVE_ED448 #include #endif +#ifdef HAVE_CURVE448 + #include +#endif #ifdef WOLFSSL_QNX_CAAM #include @@ -554,7 +560,8 @@ static const char* TagString(byte tag) */ #define ASNIntMSBSet(asn, data, i) \ ((asn[i].tag == ASN_INTEGER) && \ - ((data[i].data.buffer.data[0] & 0x80) == 0x80)) + (data[i].data.buffer.data != NULL && \ + (data[i].data.buffer.data[0] & 0x80) == 0x80)) /* Calculate the size of a DER encoded number. @@ -1909,7 +1916,7 @@ void SetASN_ReplaceBuffer(ASNSetData *dataASN, const byte* data, word32 length) dataASN->data.buffer.length = length; } -/* Setup an ASN data item to set an muli-precision number. +/* Setup an ASN data item to set an multi-precision number. * * @param [in] dataASN Dynamic ASN data item. * @param [in] num Multi-precision number. @@ -3808,9 +3815,15 @@ static word32 SetBitString16Bit(word16 val, byte* output) #ifdef HAVE_ED25519 static const byte keyEd25519Oid[] = {43, 101, 112}; #endif /* HAVE_ED25519 */ +#ifdef HAVE_CURVE25519 + static const byte keyCurve25519Oid[] = {43, 101, 110}; +#endif #ifdef HAVE_ED448 static const byte keyEd448Oid[] = {43, 101, 113}; #endif /* HAVE_ED448 */ +#ifdef HAVE_CURVE448 + static const byte keyCurve448Oid[] = {43, 101, 111}; +#endif /* HAVE_CURVE448 */ #ifndef NO_DH static const byte keyDhOid[] = {42, 134, 72, 134, 247, 13, 1, 3, 1}; #endif /* !NO_DH */ @@ -4261,12 +4274,24 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) *oidSz = sizeof(keyEd25519Oid); break; #endif /* HAVE_ED25519 */ + #ifdef HAVE_CURVE25519 + case X25519k: + oid = keyCurve25519Oid; + *oidSz = sizeof(keyCurve25519Oid); + break; + #endif /* HAVE_CURVE25519 */ #ifdef HAVE_ED448 case ED448k: oid = keyEd448Oid; *oidSz = sizeof(keyEd448Oid); break; #endif /* HAVE_ED448 */ + #ifdef HAVE_CURVE448 + case X448k: + oid = keyCurve448Oid; + *oidSz = sizeof(keyCurve448Oid); + break; + #endif /* HAVE_CURVE448 */ #ifndef NO_DH case DHk: oid = keyDhOid; @@ -5593,6 +5618,15 @@ int ToTraditionalInline_ex(const byte* input, word32* inOutIdx, word32 sz, } break; #endif + #ifdef HAVE_CURVE25519 + case X25519k: + /* Neither NULL item nor OBJECT_ID item allowed. */ + if ((dataASN[5].tag != 0) || + (dataASN[4].tag != 0)) { + ret = ASN_PARSE_E; + } + break; + #endif #ifdef HAVE_ED448 case ED448k: /* Neither NULL item nor OBJECT_ID item allowed. */ @@ -5601,6 +5635,15 @@ int ToTraditionalInline_ex(const byte* input, word32* inOutIdx, word32 sz, ret = ASN_PARSE_E; } break; + #endif + #ifdef HAVE_CURVE448 + case X448k: + /* Neither NULL item nor OBJECT_ID item allowed. */ + if ((dataASN[5].tag != 0) || + (dataASN[4].tag != 0)) { + ret = ASN_PARSE_E; + } + break; #endif /* DSAk not supported. */ /* Ignore OID lookup failures. */ @@ -12378,10 +12421,16 @@ static WC_INLINE int IsSigAlgoECC(int algoOID) #ifdef HAVE_ED25519 || (algoOID == ED25519k) #endif + #ifdef HAVE_CURVE25519 + || (algoOID == X25519k) + #endif #ifdef HAVE_ED448 || (algoOID == ED448k) #endif - ); + #ifdef HAVE_CURVE448 + || (algoOID == X448k) + #endif + ); } /* Encode an algorithm identifier. @@ -12409,7 +12458,6 @@ word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz) (type == oidKeyType && algoOID == RSAk)) ? 2 : 0; algoName = OidFromId(algoOID, type, &algoSz); - if (algoName == NULL) { WOLFSSL_MSG("Unknown Algorithm"); return 0; @@ -14293,9 +14341,9 @@ static int DecodeBasicCaConstraint(const byte* input, int sz, DecodedCert* cert) ret = GetBoolean(input, &idx, sz); -/* Removed logic for WOLFSSL_X509_BASICCONS_INT which was mistreating the - * pathlen value as if it were the CA Boolean value 7/2/2021 - KH. - * When CA Boolean not asserted use the default value "False" */ + /* Removed logic for WOLFSSL_X509_BASICCONS_INT which was mistreating the + * pathlen value as if it were the CA Boolean value 7/2/2021 - KH. + * When CA Boolean not asserted use the default value "False" */ if (ret < 0) { WOLFSSL_MSG("\tfail: constraint not valid BOOLEAN, set default FALSE"); ret = 0; @@ -20212,7 +20260,7 @@ int wc_EccPublicKeyDerSize(ecc_key* key, int with_AlgCurve) #endif /* HAVE_ECC && HAVE_ECC_KEY_EXPORT */ #ifdef WOLFSSL_ASN_TEMPLATE -#if defined(HAVE_ED25519) || defined(HAVE_ED448) +#if defined(WC_ENABLE_ASYM_KEY_EXPORT) || defined(WC_ENABLE_ASYM_KEY_IMPORT) /* ASN.1 template for Ed25519 and Ed448 public key (SubkectPublicKeyInfo). * RFC 8410, 4 - Subject Public Key Fields */ @@ -20229,116 +20277,98 @@ static const ASNItem edPubKeyASN[] = { /* Number of items in ASN.1 template for Ed25519 and Ed448 public key. */ #define edPubKeyASN_Length (sizeof(edPubKeyASN) / sizeof(ASNItem)) -#endif /* HAVE_ED25519 || HAVE_ED448 */ +#endif /* WC_ENABLE_ASYM_KEY_EXPORT || WC_ENABLE_ASYM_KEY_IMPORT */ #endif /* WOLFSSL_ASN_TEMPLATE */ -#if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_EXPORT) && \ - (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN)) +#ifdef WC_ENABLE_ASYM_KEY_EXPORT -/* Encode the public part of an Ed25519 key in DER. +/* Build ASN.1 formatted public key based on RFC 8410 * * Pass NULL for output to get the size of the encoding. * - * @param [out] output Buffer to put encoded data in. - * @param [in] key Ed25519 key object. - * @param [in] outLen Size of buffer in bytes. - * @param [in] with_header Whether to use SubjectPublicKeyInfo format. - * @return Size of encoded data in bytes on success. + * @param [in] pubKey public key buffer + * @param [in] pubKeyLen public ket buffer length + * @param [out] output Buffer to put encoded data in (optional) + * @param [in] outLen Size of buffer in bytes + * @param [in] keyType is "enum Key_Sum" like ED25519k + * @param [in] withHeader Whether to include SubjectPublicKeyInfo around key. + * @return Size of encoded data in bytes on success * @return BAD_FUNC_ARG when key is NULL. * @return MEMORY_E when dynamic memory allocation failed. */ -static int SetEd25519PublicKey(byte* output, ed25519_key* key, int outLen, - int with_header) +static int SetAsymKeyDerPublic(const byte* pubKey, word32 pubKeyLen, + byte* output, word32 outLen, int keyType, int withHeader) { + int ret = 0; #ifndef WOLFSSL_ASN_TEMPLATE - byte bitString[1 + MAX_LENGTH_SZ + 1]; - int algoSz; - int bitStringSz; - int idx; - word32 pubSz = ED25519_PUB_KEY_SIZE; -#ifdef WOLFSSL_SMALL_STACK - byte* algo = NULL; - byte* pub; + word32 idx = 0, bitStringSz, algoSz, sz = 0; #else - byte algo[MAX_ALGO_SZ]; - byte pub[ED25519_PUB_KEY_SIZE]; + int sz = 0; + DECL_ASNSETDATA(dataASN, edPubKeyASN_Length); #endif - (void)outLen; + if (pubKey == NULL) { + return BAD_FUNC_ARG; + } -#ifdef WOLFSSL_SMALL_STACK - pub = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (pub == NULL) - return MEMORY_E; -#endif +#ifndef WOLFSSL_ASN_TEMPLATE + /* calculate size */ + if (withHeader) { + algoSz = SetAlgoID(keyType, NULL, oidKeyType, 0); + bitStringSz = SetBitString(pubKeyLen, 0, NULL); - idx = wc_ed25519_export_public(key, pub, &pubSz); - if (idx != 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return idx; + sz = algoSz + bitStringSz + pubKeyLen; + sz += SetSequence(outLen, NULL); + } + else { + sz = pubKeyLen; + } + + /* checkout output size */ + if (output != NULL && sz > outLen) { + ret = BUFFER_E; } /* headers */ - if (with_header) { -#ifdef WOLFSSL_SMALL_STACK - algo = (byte*)XMALLOC(MAX_ALGO_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (algo == NULL) { - XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; - } -#endif - algoSz = SetAlgoID(ED25519k, algo, oidKeyType, 0); - - bitStringSz = SetBitString(pubSz, 0, bitString); - - idx = SetSequence(pubSz + bitStringSz + algoSz, output); + if (ret == 0 && output != NULL && withHeader) { + /* sequence */ + idx = SetSequence(algoSz + bitStringSz + pubKeyLen, output); /* algo */ - XMEMCPY(output + idx, algo, algoSz); + algoSz = SetAlgoID(keyType, output + idx, oidKeyType, 0); idx += algoSz; /* bit string */ - XMEMCPY(output + idx, bitString, bitStringSz); + bitStringSz = SetBitString(pubKeyLen, 0, output + idx); idx += bitStringSz; } - else - idx = 0; - /* pub */ - XMEMCPY(output + idx, pub, pubSz); - idx += pubSz; + if (ret == 0 && output != NULL) { + /* pub */ + XMEMCPY(output + idx, pubKey, pubKeyLen); + idx += pubKeyLen; -#ifdef WOLFSSL_SMALL_STACK - if (with_header) { - XFREE(algo, NULL, DYNAMIC_TYPE_TMP_BUFFER); + sz = idx; } - XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return idx; + if (ret == 0) { + ret = sz; + } #else - word32 pubSz = ED25519_PUB_KEY_SIZE; - int sz = 0; - int ret = 0; - - if (with_header) { - DECL_ASNSETDATA(dataASN, edPubKeyASN_Length); - + if (withHeader) { CALLOC_ASNSETDATA(dataASN, edPubKeyASN_Length, ret, NULL); if (ret == 0) { - /* Set the Ed25519 OID. */ - SetASN_Buffer(&dataASN[2], keyEd25519Oid, sizeof(keyEd25519Oid)); + /* Set the OID. */ + SetASN_OID(&dataASN[2], keyType, oidKeyType); /* Leave space for public point. */ - SetASN_Buffer(&dataASN[3], NULL, ED25519_PUB_KEY_SIZE); - /* Calculate size of Ed25519 public key encoding. */ + SetASN_Buffer(&dataASN[3], NULL, pubKeyLen); + /* Calculate size of public key encoding. */ ret = SizeASN_Items(edPubKeyASN, dataASN, edPubKeyASN_Length, &sz); } - if ((ret == 0) && (output != NULL) && (sz > outLen)) { + if ((ret == 0) && (output != NULL) && (sz > (int)outLen)) { ret = BUFFER_E; } if ((ret == 0) && (output != NULL)) { - /* Encode Ed25519 public key. */ + /* Encode public key. */ SetASN_Items(edPubKeyASN, dataASN, edPubKeyASN_Length, output); /* Set location to encode public point. */ output = (byte*)dataASN[3].data.buffer.data; @@ -20346,25 +20376,26 @@ static int SetEd25519PublicKey(byte* output, ed25519_key* key, int outLen, FREE_ASNSETDATA(dataASN, NULL); } - else if ((output != NULL) && (ED25519_PUB_KEY_SIZE > outLen)) { + else if ((output != NULL) && (pubKeyLen > outLen)) { ret = BUFFER_E; } else if (ret == 0) { - sz = ED25519_PUB_KEY_SIZE; + sz = pubKeyLen; } if ((ret == 0) && (output != NULL)) { /* Put public key into space provided. */ - ret = wc_ed25519_export_public(key, output, &pubSz); + XMEMCPY(output, pubKey, pubKeyLen); } if (ret == 0) { ret = sz; } - - return ret; #endif /* WOLFSSL_ASN_TEMPLATE */ + return ret; } +#endif /* WC_ENABLE_ASYM_KEY_EXPORT */ +#if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_EXPORT) /* Encode the public part of an Ed25519 key in DER. * * Pass NULL for output to get the size of the encoding. @@ -20372,7 +20403,7 @@ static int SetEd25519PublicKey(byte* output, ed25519_key* key, int outLen, * @param [in] key Ed25519 key object. * @param [out] output Buffer to put encoded data in. * @param [in] outLen Size of buffer in bytes. - * @param [in] with_alg Whether to use SubjectPublicKeyInfo format. + * @param [in] withAlg Whether to use SubjectPublicKeyInfo format. * @return Size of encoded data in bytes on success. * @return BAD_FUNC_ARG when key is NULL. * @return MEMORY_E when dynamic memory allocation failed. @@ -20380,175 +20411,24 @@ static int SetEd25519PublicKey(byte* output, ed25519_key* key, int outLen, int wc_Ed25519PublicKeyToDer(ed25519_key* key, byte* output, word32 inLen, int withAlg) { -#ifndef WOLFSSL_ASN_TEMPLATE - word32 infoSz = 0; - word32 keySz = 0; - int ret; + int ret; + byte pubKey[ED25519_PUB_KEY_SIZE]; + word32 pubKeyLen = (word32)sizeof(pubKey); - if (output == NULL || key == NULL) { + if (key == NULL || output == NULL) { return BAD_FUNC_ARG; } - if (withAlg) { - /* buffer space for algorithm */ - infoSz += MAX_SEQ_SZ; - infoSz += MAX_ALGO_SZ; - - /* buffer space for public key sequence */ - infoSz += MAX_SEQ_SZ; - infoSz += TRAILING_ZERO; - } - - if ((ret = wc_ed25519_export_public(key, output, &keySz)) != BUFFER_E) { - WOLFSSL_MSG("Error in getting ECC public key size"); - return ret; - } - - if (inLen < keySz + infoSz) { - return BUFFER_E; - } -#else - if (output == NULL || key == NULL) { - return BAD_FUNC_ARG; - } -#endif - - return SetEd25519PublicKey(output, key, inLen, withAlg); -} -#endif /* HAVE_ED25519 && HAVE_ED25519_KEY_EXPORT && (WOLFSSL_CERT_GEN || WOLFSSL_KEY_GEN) */ -#if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_EXPORT) && \ - (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN)) - -/* Encode the public part of an Ed448 key in DER. - * - * Pass NULL for output to get the size of the encoding. - * - * @param [out] output Buffer to put encoded data in. - * @param [in] key Ed448 key object. - * @param [in] outLen Size of buffer in bytes. - * @param [in] with_header Whether to use SubjectPublicKeyInfo format. - * @return Size of encoded data in bytes on success. - * @return BAD_FUNC_ARG when key is NULL. - * @return MEMORY_E when dynamic memory allocation failed. - */ -static int SetEd448PublicKey(byte* output, ed448_key* key, int outLen, - int with_header) -{ -#ifndef WOLFSSL_ASN_TEMPLATE - byte bitString[1 + MAX_LENGTH_SZ + 1]; - int algoSz; - int bitStringSz; - int idx; - word32 pubSz = ED448_PUB_KEY_SIZE; -#ifdef WOLFSSL_SMALL_STACK - byte* algo = NULL; - byte* pub = NULL; -#else - byte algo[MAX_ALGO_SZ]; - byte pub[ED448_PUB_KEY_SIZE]; -#endif - - (void)outLen; - -#ifdef WOLFSSL_SMALL_STACK - pub = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (pub == NULL) - return MEMORY_E; -#endif - - idx = wc_ed448_export_public(key, pub, &pubSz); - if (idx != 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return idx; - } - - /* headers */ - if (with_header) { -#ifdef WOLFSSL_SMALL_STACK - algo = (byte*)XMALLOC(MAX_ALGO_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (algo == NULL) { - XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; - } -#endif - algoSz = SetAlgoID(ED448k, algo, oidKeyType, 0); - - bitStringSz = SetBitString(pubSz, 0, bitString); - - idx = SetSequence(pubSz + bitStringSz + algoSz, output); - /* algo */ - XMEMCPY(output + idx, algo, algoSz); - idx += algoSz; - /* bit string */ - XMEMCPY(output + idx, bitString, bitStringSz); - idx += bitStringSz; - } - else - idx = 0; - - /* pub */ - XMEMCPY(output + idx, pub, pubSz); - idx += pubSz; - -#ifdef WOLFSSL_SMALL_STACK - if (with_header) { - XFREE(algo, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } - XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return idx; -#else - word32 pubSz = ED448_PUB_KEY_SIZE; - int sz = 0; - int ret = 0; - - if (with_header) { - DECL_ASNSETDATA(dataASN, edPubKeyASN_Length); - - CALLOC_ASNSETDATA(dataASN, edPubKeyASN_Length, ret, NULL); - - if (ret == 0) { - /* Set the Ed448 OID. */ - SetASN_Buffer(&dataASN[2], keyEd448Oid, sizeof(keyEd448Oid)); - /* Leave space for public point. */ - SetASN_Buffer(&dataASN[3], NULL, ED448_PUB_KEY_SIZE); - /* Calculate size of Ed448 public key encoding. */ - ret = SizeASN_Items(edPubKeyASN, dataASN, edPubKeyASN_Length, &sz); - } - if ((ret == 0) && (output != NULL) && (sz > outLen)) { - ret = BUFFER_E; - } - if ((ret == 0) && (output != NULL)) { - /* Encode Ed448 public key. */ - SetASN_Items(edPubKeyASN, dataASN, edPubKeyASN_Length, output); - /* Set location to encode public point. */ - output = (byte*)dataASN[3].data.buffer.data; - } - - FREE_ASNSETDATA(dataASN, NULL); - } - else if ((output != NULL) && (ED448_PUB_KEY_SIZE > outLen)) { - ret = BUFFER_E; - } - else if (ret == 0) { - sz = ED448_PUB_KEY_SIZE; - } - - if ((ret == 0) && (output != NULL)) { - /* Put public key into space provided. */ - ret = wc_ed448_export_public(key, output, &pubSz); - } + ret = wc_ed25519_export_public(key, pubKey, &pubKeyLen); if (ret == 0) { - ret = sz; + ret = SetAsymKeyDerPublic(pubKey, pubKeyLen, output, inLen, + ED25519k, withAlg); } - return ret; -#endif /* WOLFSSL_ASN_TEMPLATE */ } +#endif /* HAVE_ED25519 && HAVE_ED25519_KEY_EXPORT */ +#if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_EXPORT) /* Encode the public part of an Ed448 key in DER. * * Pass NULL for output to get the size of the encoding. @@ -20556,7 +20436,7 @@ static int SetEd448PublicKey(byte* output, ed448_key* key, int outLen, * @param [in] key Ed448 key object. * @param [out] output Buffer to put encoded data in. * @param [in] outLen Size of buffer in bytes. - * @param [in] with_alg Whether to use SubjectPublicKeyInfo format. + * @param [in] withAlg Whether to use SubjectPublicKeyInfo format. * @return Size of encoded data in bytes on success. * @return BAD_FUNC_ARG when key is NULL. * @return MEMORY_E when dynamic memory allocation failed. @@ -20564,42 +20444,22 @@ static int SetEd448PublicKey(byte* output, ed448_key* key, int outLen, int wc_Ed448PublicKeyToDer(ed448_key* key, byte* output, word32 inLen, int withAlg) { -#ifndef WOLFSSL_ASN_TEMPLATE - word32 infoSz = 0; - word32 keySz = 0; - int ret; + int ret; + byte pubKey[ED448_PUB_KEY_SIZE]; + word32 pubKeyLen = (word32)sizeof(pubKey); - if (output == NULL || key == NULL) { + if (key == NULL || output == NULL) { return BAD_FUNC_ARG; } - if (withAlg) { - /* buffer space for algorithm */ - infoSz += MAX_SEQ_SZ; - infoSz += MAX_ALGO_SZ; - - /* buffer space for public key sequence */ - infoSz += MAX_SEQ_SZ; - infoSz += TRAILING_ZERO; + ret = wc_ed448_export_public(key, pubKey, &pubKeyLen); + if (ret == 0) { + ret = SetAsymKeyDerPublic(pubKey, pubKeyLen, output, inLen, + ED448k, withAlg); } - - if ((ret = wc_ed448_export_public(key, output, &keySz)) != BUFFER_E) { - WOLFSSL_MSG("Error in getting ECC public key size"); - return ret; - } - - if (inLen < keySz + infoSz) { - return BUFFER_E; - } -#else - if (output == NULL || key == NULL) { - return BAD_FUNC_ARG; - } -#endif - - return SetEd448PublicKey(output, key, inLen, withAlg); + return ret; } -#endif /* HAVE_ED448 && HAVE_ED448_KEY_EXPORT && (WOLFSSL_CERT_GEN || WOLFSSL_KEY_GEN) */ +#endif /* HAVE_ED448 && HAVE_ED448_KEY_EXPORT */ #ifdef WOLFSSL_CERT_GEN @@ -22016,7 +21876,7 @@ static int EncodePublicKey(int keyType, byte* output, int outLen, #endif /* HAVE_ECC */ #ifdef HAVE_ED25519 case ED25519_KEY: - ret = SetEd25519PublicKey(output, ed25519Key, outLen, 1); + ret = wc_Ed25519PublicKeyToDer(ed25519Key, output, outLen, 1); if (ret <= 0) { ret = PUBLIC_KEY_E; } @@ -22024,7 +21884,7 @@ static int EncodePublicKey(int keyType, byte* output, int outLen, #endif #ifdef HAVE_ED448 case ED448_KEY: - ret = SetEd448PublicKey(output, ed448Key, outLen, 1); + ret = wc_Ed448PublicKeyToDer(ed448Key, output, outLen, 1); if (ret <= 0) { ret = PUBLIC_KEY_E; } @@ -22476,8 +22336,8 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey, if (cert->keyType == ED25519_KEY) { if (ed25519Key == NULL) return PUBLIC_KEY_E; - der->publicKeySz = SetEd25519PublicKey(der->publicKey, ed25519Key, - sizeof(der->publicKey), 1); + der->publicKeySz = wc_Ed25519PublicKeyToDer(ed25519Key, der->publicKey, + (word32)sizeof(der->publicKey), 1); } #endif @@ -22485,8 +22345,8 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey, if (cert->keyType == ED448_KEY) { if (ed448Key == NULL) return PUBLIC_KEY_E; - der->publicKeySz = SetEd448PublicKey(der->publicKey, ed448Key, - sizeof(der->publicKey), 1); + der->publicKeySz = wc_Ed448PublicKeyToDer(ed448Key, der->publicKey, + (word32)sizeof(der->publicKey), 1); } #endif @@ -23575,8 +23435,8 @@ static int EncodeCertReq(Cert* cert, DerCert* der, RsaKey* rsaKey, if (cert->keyType == ED25519_KEY) { if (ed25519Key == NULL) return PUBLIC_KEY_E; - der->publicKeySz = SetEd25519PublicKey(der->publicKey, ed25519Key, - sizeof(der->publicKey), 1); + der->publicKeySz = wc_Ed25519PublicKeyToDer(ed25519Key, der->publicKey, + (word32)sizeof(der->publicKey), 1); } #endif @@ -23584,8 +23444,8 @@ static int EncodeCertReq(Cert* cert, DerCert* der, RsaKey* rsaKey, if (cert->keyType == ED448_KEY) { if (ed448Key == NULL) return PUBLIC_KEY_E; - der->publicKeySz = SetEd448PublicKey(der->publicKey, ed448Key, - sizeof(der->publicKey), 1); + der->publicKeySz = wc_Ed448PublicKeyToDer(ed448Key, der->publicKey, + (word32)sizeof(der->publicKey), 1); } #endif if (der->publicKeySz <= 0) @@ -24226,13 +24086,15 @@ static int SetKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey, #endif #if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_EXPORT) /* ED25519 public key */ - if (ed25519Key != NULL) - bufferSz = SetEd25519PublicKey(buf, ed25519Key, MAX_PUBLIC_KEY_SZ, 0); + if (ed25519Key != NULL) { + bufferSz = wc_Ed25519PublicKeyToDer(ed25519Key, buf, MAX_PUBLIC_KEY_SZ, 0); + } #endif #if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_EXPORT) /* ED448 public key */ - if (ed448Key != NULL) - bufferSz = SetEd448PublicKey(buf, ed448Key, MAX_PUBLIC_KEY_SZ, 0); + if (ed448Key != NULL) { + bufferSz = wc_Ed448PublicKeyToDer(ed448Key, buf, MAX_PUBLIC_KEY_SZ, 0); + } #endif if (bufferSz <= 0) { @@ -26870,8 +26732,8 @@ int wc_EccKeyToPKCS8(ecc_key* key, byte* output, #endif /* HAVE_ECC_KEY_EXPORT && !NO_ASN_CRYPT */ #endif /* HAVE_ECC */ +#ifdef WC_ENABLE_ASYM_KEY_IMPORT #ifdef WOLFSSL_ASN_TEMPLATE -#if defined(HAVE_ED25519) || defined(HAVE_ED448) /* ASN.1 template for Ed25519 and Ed448 private key. * RFC 8410, 7 - Private Key Format (but public value is EXPLICIT OCTET_STRING) */ @@ -26896,25 +26758,28 @@ static const ASNItem edKeyASN[] = { /* Number of items in ASN.1 template for Ed25519 and Ed448 private key. */ #define edKeyASN_Length (sizeof(edKeyASN) / sizeof(ASNItem)) -#endif /* HAVE_ED25519 || HAVE_ED448 */ -#endif /* WOLFSSL_ASN_TEMPLATE */ +#endif -#ifdef HAVE_ED25519 - -#ifdef HAVE_ED25519_KEY_IMPORT - -int wc_Ed25519PrivateKeyDecode(const byte* input, word32* inOutIdx, - ed25519_key* key, word32 inSz) +static int DecodeAsymKey(const byte* input, word32* inOutIdx, word32 inSz, + byte* privKey, word32* privKeyLen, + byte* pubKey, word32* pubKeyLen, int keyType) { + int ret = 0; #ifndef WOLFSSL_ASN_TEMPLATE - word32 oid; - int ret, version, length, endKeyIdx, privSz, pubSz; + word32 oid; + int version, length, endKeyIdx, privSz, pubSz; const byte* priv; const byte* pub; +#else + DECL_ASNGETDATA(dataASN, edKeyASN_Length); +#endif - if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) + if (input == NULL || inOutIdx == NULL || inSz == 0 || + privKey == NULL || privKeyLen == NULL) { return BAD_FUNC_ARG; + } +#ifndef WOLFSSL_ASN_TEMPLATE if (GetSequence(input, inOutIdx, &length, inSz) >= 0) { endKeyIdx = *inOutIdx + length; @@ -26927,7 +26792,7 @@ int wc_Ed25519PrivateKeyDecode(const byte* input, word32* inOutIdx, if (GetAlgoId(input, inOutIdx, &oid, oidKeyType, inSz) < 0) return ASN_PARSE_E; - if (oid != ED25519k) + if (oid != (word32)keyType) return ASN_PARSE_E; if (GetOctetString(input, inOutIdx, &length, inSz) < 0) @@ -26943,42 +26808,45 @@ int wc_Ed25519PrivateKeyDecode(const byte* input, word32* inOutIdx, if (GetOctetString(input, inOutIdx, &privSz, inSz) < 0) return ASN_PARSE_E; - if (privSz != 32) - return ASN_PARSE_E; - priv = input + *inOutIdx; *inOutIdx += privSz; endKeyIdx = *inOutIdx; } if (endKeyIdx == (int)*inOutIdx) { - ret = wc_ed25519_import_private_only(priv, privSz, key); + *privKeyLen = privSz; + XMEMCPY(privKey, priv, *privKeyLen); + if (pubKeyLen != NULL) + *pubKeyLen = 0; } else { if (GetASNHeader(input, ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1, inOutIdx, &length, inSz) < 0) { return ASN_PARSE_E; } - if (GetOctetString(input, inOutIdx, &pubSz, inSz) < 0) + if (GetOctetString(input, inOutIdx, &pubSz, inSz) < 0) { return ASN_PARSE_E; + } pub = input + *inOutIdx; *inOutIdx += pubSz; - ret = wc_ed25519_import_private_key(priv, privSz, pub, pubSz, key); + *privKeyLen = privSz; + XMEMCPY(privKey, priv, *privKeyLen); + if (pubKeyLen != NULL) + *pubKeyLen = pubSz; + if (pubKey != NULL && pubKeyLen != NULL) + XMEMCPY(pubKey, pub, *pubKeyLen); } if (ret == 0 && endKeyIdx != (int)*inOutIdx) return ASN_PARSE_E; - - return ret; #else - DECL_ASNGETDATA(dataASN, edKeyASN_Length); - int ret = 0; - CALLOC_ASNGETDATA(dataASN, edKeyASN_Length, ret, NULL); if (ret == 0) { - /* Require Ed25519 OID. */ - GetASN_ExpBuffer(&dataASN[3], keyEd25519Oid, sizeof(keyEd25519Oid)); + /* Require OID. */ + word32 oidSz; + const byte* oid = OidFromId(keyType, oidKeyType, &oidSz); + GetASN_ExpBuffer(&dataASN[3], oid, oidSz); /* Parse full private key. */ ret = GetASN_Items(edKeyASN, dataASN, edKeyASN_Length, 1, input, inOutIdx, inSz); @@ -26992,50 +26860,61 @@ int wc_Ed25519PrivateKeyDecode(const byte* input, word32* inOutIdx, } } /* Check the private value length is correct. */ - if ((ret == 0) && dataASN[5].data.ref.length != ED25519_KEY_SIZE) { + if ((ret == 0) && dataASN[5].data.ref.length > *privKeyLen) { ret = ASN_PARSE_E; } if ((ret == 0) && dataASN[7].tag == 0) { - /* Import just the private value. */ - ret = wc_ed25519_import_private_only(dataASN[5].data.ref.data, - ED25519_KEY_SIZE, key); + *privKeyLen = dataASN[5].data.ref.length; + XMEMCPY(privKey, dataASN[5].data.ref.data, *privKeyLen); + if (pubKeyLen != NULL) + *pubKeyLen = 0; } else if ((ret == 0) && - (dataASN[8].data.ref.length != ED25519_PUB_KEY_SIZE)) { + (dataASN[8].data.ref.length > *pubKeyLen)) { ret = ASN_PARSE_E; } else if (ret == 0) { /* Import private and public value. */ - ret = wc_ed25519_import_private_key(dataASN[5].data.ref.data, - ED25519_KEY_SIZE, dataASN[8].data.ref.data, - ED25519_PUB_KEY_SIZE, key); + *privKeyLen = dataASN[5].data.ref.length; + XMEMCPY(privKey, dataASN[5].data.ref.data, *privKeyLen); + if (pubKeyLen != NULL) + *pubKeyLen = dataASN[8].data.ref.length; + if (pubKey != NULL && pubKeyLen != NULL) + XMEMCPY(pubKey, dataASN[8].data.ref.data, *pubKeyLen); } FREE_ASNGETDATA(dataASN, NULL); - return ret; #endif /* WOLFSSL_ASN_TEMPLATE */ + return ret; } - -int wc_Ed25519PublicKeyDecode(const byte* input, word32* inOutIdx, - ed25519_key* key, word32 inSz) +static int DecodeAsymKeyPublic(const byte* input, word32* inOutIdx, word32 inSz, + byte* pubKey, word32* pubKeyLen, int keyType) { + int ret = 0; #ifndef WOLFSSL_ASN_TEMPLATE - int length; - int ret; + int length; + word32 oid; +#else + DECL_ASNGETDATA(dataASN, edPubKeyASN_Length); +#endif - if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) + if (input == NULL || inSz == 0 || inOutIdx == NULL || + pubKey == NULL || pubKeyLen == NULL) { return BAD_FUNC_ARG; + } +#ifndef WOLFSSL_ASN_TEMPLATE if (GetSequence(input, inOutIdx, &length, inSz) < 0) return ASN_PARSE_E; if (GetSequence(input, inOutIdx, &length, inSz) < 0) return ASN_PARSE_E; - ret = SkipObjectId(input, inOutIdx, inSz); - if (ret != 0) - return ret; + if (GetObjectId(input, inOutIdx, &oid, oidKeyType, inSz) < 0) + return ASN_PARSE_E; + if (oid != (word32)keyType) + return ASN_PARSE_E; /* key header */ ret = CheckBitString(input, inOutIdx, NULL, inSz, 1, NULL); @@ -27043,19 +26922,16 @@ int wc_Ed25519PublicKeyDecode(const byte* input, word32* inOutIdx, return ret; /* This is the raw point data compressed or uncompressed. */ - if (wc_ed25519_import_public(input + *inOutIdx, inSz - *inOutIdx, key) != 0) - return ASN_ECC_KEY_E; - - return 0; + *pubKeyLen = inSz - *inOutIdx; + XMEMCPY(pubKey, input + *inOutIdx, *pubKeyLen); #else - DECL_ASNGETDATA(dataASN, edPubKeyASN_Length); - int ret = 0; - CALLOC_ASNGETDATA(dataASN, edPubKeyASN_Length, ret, NULL); if (ret == 0) { - /* Require Ed25519 OID. */ - GetASN_ExpBuffer(&dataASN[2], keyEd25519Oid, sizeof(keyEd25519Oid)); + /* Require OID. */ + word32 oidSz; + const byte* oid = OidFromId(keyType, oidKeyType, &oidSz); + GetASN_ExpBuffer(&dataASN[2], oid, oidSz); /* Decode Ed25519 private key. */ ret = GetASN_Items(edPubKeyASN, dataASN, edPubKeyASN_Length, 1, input, inOutIdx, inSz); @@ -27064,103 +26940,201 @@ int wc_Ed25519PublicKeyDecode(const byte* input, word32* inOutIdx, } } /* Check the public value length is correct. */ - if ((ret == 0) && (dataASN[3].data.ref.length != ED25519_PUB_KEY_SIZE)) { + if ((ret == 0) && (dataASN[3].data.ref.length > *pubKeyLen)) { ret = ASN_PARSE_E; } if (ret == 0) { - /* Import the public value. */ - ret = wc_ed25519_import_public(dataASN[3].data.ref.data, - ED25519_PUB_KEY_SIZE, key); - if (ret != 0) { - ret = ASN_ECC_KEY_E; - } + *pubKeyLen = dataASN[3].data.ref.length; + XMEMCPY(pubKey, dataASN[3].data.ref.data, *pubKeyLen); } FREE_ASNGETDATA(dataASN, NULL); - return ret; #endif /* WOLFSSL_ASN_TEMPLATE */ + return ret; +} +#endif /* WC_ENABLE_ASYM_KEY_IMPORT */ + +#if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_IMPORT) +int wc_Ed25519PrivateKeyDecode(const byte* input, word32* inOutIdx, + ed25519_key* key, word32 inSz) +{ + int ret; + byte privKey[ED25519_KEY_SIZE], pubKey[ED25519_PUB_KEY_SIZE]; + word32 privKeyLen = (word32)sizeof(privKey); + word32 pubKeyLen = (word32)sizeof(pubKey); + + if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) { + return BAD_FUNC_ARG; + } + + ret = DecodeAsymKey(input, inOutIdx, inSz, privKey, &privKeyLen, + pubKey, &pubKeyLen, ED25519k); + if (ret == 0) { + if (pubKeyLen == 0) { + ret = wc_ed25519_import_private_only(privKey, privKeyLen, key); + } + else { + ret = wc_ed25519_import_private_key(privKey, privKeyLen, + pubKey, pubKeyLen, key); + } + } + return ret; } -#endif /* HAVE_ED25519_KEY_IMPORT */ - -#if defined(WOLFSSL_KEY_GEN) && defined(HAVE_ED25519_KEY_EXPORT) - -/* build DER formatted ED25519 key, - * return length on success, negative on error */ -static int wc_BuildEd25519KeyDer(ed25519_key* key, byte* output, word32 inLen, - int pubOut) +int wc_Ed25519PublicKeyDecode(const byte* input, word32* inOutIdx, + ed25519_key* key, word32 inSz) { -#ifndef WOLFSSL_ASN_TEMPLATE - byte algoArray[MAX_ALGO_SZ]; - byte ver[MAX_VERSION_SZ]; - byte seq[MAX_SEQ_SZ]; - int ret; - word32 idx = 0, seqSz, verSz, algoSz, privSz, pubSz = 0; + int ret; + byte pubKey[ED25519_PUB_KEY_SIZE]; + word32 pubKeyLen = (word32)sizeof(pubKey); - if (key == NULL || output == NULL || inLen == 0) + if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) { return BAD_FUNC_ARG; - - if (pubOut) - pubSz = 2 + 2 + ED25519_PUB_KEY_SIZE; - privSz = 2 + 2 + ED25519_KEY_SIZE; - algoSz = SetAlgoID(ED25519k, algoArray, oidKeyType, 0); - verSz = SetMyVersion(0, ver, FALSE); - seqSz = SetSequence(verSz + algoSz + privSz + pubSz, seq); - - if (seqSz + verSz + algoSz + privSz + pubSz > inLen) - return BAD_FUNC_ARG; - - /* write out */ - /* seq */ - XMEMCPY(output + idx, seq, seqSz); - idx = seqSz; - /* ver */ - XMEMCPY(output + idx, ver, verSz); - idx += verSz; - /* algo */ - XMEMCPY(output + idx, algoArray, algoSz); - idx += algoSz; - /* privKey */ - idx += SetOctetString(2 + ED25519_KEY_SIZE, output + idx); - idx += SetOctetString(ED25519_KEY_SIZE, output + idx); - ret = wc_ed25519_export_private_only(key, output + idx, &privSz); - if (ret != 0) - return ret; - idx += privSz; - /* pubKey */ - if (pubOut) { - idx += SetExplicit(1, 2 + ED25519_PUB_KEY_SIZE, output + idx); - idx += SetOctetString(ED25519_KEY_SIZE, output + idx); - ret = wc_ed25519_export_public(key, output + idx, &pubSz); - if (ret != 0) - return ret; - idx += pubSz; } - return idx; + ret = DecodeAsymKeyPublic(input, inOutIdx, inSz, + pubKey, &pubKeyLen, ED25519k); + if (ret == 0) { + ret = wc_ed25519_import_public(pubKey, pubKeyLen, key); + } + return ret; +} +#endif /* HAVE_ED25519 && HAVE_ED25519_KEY_IMPORT */ + +#if defined(HAVE_CURVE25519) && defined(HAVE_CURVE25519_KEY_IMPORT) +int wc_Curve25519PrivateKeyDecode(const byte* input, word32* inOutIdx, + curve25519_key* key, word32 inSz) +{ + int ret; + byte privKey[CURVE25519_KEYSIZE]; + word32 privKeyLen = CURVE25519_KEYSIZE; + + if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) { + return BAD_FUNC_ARG; + } + + ret = DecodeAsymKey(input, inOutIdx, inSz, privKey, &privKeyLen, + NULL, NULL, X25519k); + if (ret == 0) { + ret = wc_curve25519_import_private(privKey, privKeyLen, key); + } + return ret; +} + +int wc_Curve25519PublicKeyDecode(const byte* input, word32* inOutIdx, + curve25519_key* key, word32 inSz) +{ + int ret; + byte pubKey[CURVE25519_KEYSIZE]; + word32 pubKeyLen = (word32)sizeof(pubKey); + + if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) { + return BAD_FUNC_ARG; + } + + ret = DecodeAsymKeyPublic(input, inOutIdx, inSz, + pubKey, &pubKeyLen, X25519k); + if (ret == 0) { + ret = wc_curve25519_import_public(pubKey, pubKeyLen, key); + } + return ret; +} +#endif /* HAVE_CURVE25519 && HAVE_ED25519_KEY_IMPORT */ + + +#ifdef WC_ENABLE_ASYM_KEY_EXPORT + +/* Build ASN.1 formatted key based on RFC 5958 (Asymmetric Key Packages) + * + * Pass NULL for output to get the size of the encoding. + * + * @param [in] privKey private key buffer + * @param [in] privKeyLen private ket buffer length + * @param [in] pubKey public key buffer (optional) + * @param [in] pubKeyLen public ket buffer length + * @param [out] output Buffer to put encoded data in (optional) + * @param [in] outLen Size of buffer in bytes + * @param [in] keyType is "enum Key_Sum" like ED25519k + * @return Size of encoded data in bytes on success + * @return BAD_FUNC_ARG when key is NULL. + * @return MEMORY_E when dynamic memory allocation failed. + * @return LENGTH_ONLY_E return length only. + */ +static int SetAsymKeyDer(const byte* privKey, word32 privKeyLen, + const byte* pubKey, word32 pubKeyLen, + byte* output, word32 outLen, int keyType) +{ + int ret = 0; +#ifndef WOLFSSL_ASN_TEMPLATE + word32 idx = 0, seqSz, verSz, algoSz, privSz, pubSz = 0, sz; #else DECL_ASNSETDATA(dataASN, edKeyASN_Length); - word32 privSz; - int ret = 0; int sz; +#endif /* Validate parameters. */ - if ((key == NULL) || (output == NULL) || (inLen == 0)) { + if (privKey == NULL || outLen == 0) { + return BAD_FUNC_ARG; + } + +#ifndef WOLFSSL_ASN_TEMPLATE + /* calculate size */ + if (pubKey) { + pubSz = 2 + 2 + pubKeyLen; + } + privSz = 2 + 2 + privKeyLen; + algoSz = SetAlgoID(keyType, NULL, oidKeyType, 0); + verSz = 3; /* version is 3 bytes (enum + id + version(byte)) */ + seqSz = SetSequence(verSz + algoSz + privSz + pubSz, NULL); + sz = seqSz + verSz + algoSz + privSz + pubSz; + + /* checkout output size */ + if (ret == 0 && output != NULL && sz > outLen) { ret = BAD_FUNC_ARG; } + if (ret == 0 && output != NULL) { + /* write out */ + /* seq */ + seqSz = SetSequence(verSz + algoSz + privSz + pubSz, output); + idx = seqSz; + /* ver */ + SetMyVersion(0, output + idx, FALSE); + idx += verSz; + /* algo */ + algoSz = SetAlgoID(keyType, output + idx, oidKeyType, 0); + idx += algoSz; + /* privKey */ + idx += SetOctetString(2 + privKeyLen, output + idx); + idx += SetOctetString(privKeyLen, output + idx); + XMEMCPY(output + idx, privKey, privKeyLen); + idx += privKeyLen; + /* pubKey */ + if (pubKey) { + idx += SetExplicit(1, 2 + pubKeyLen, output + idx); + idx += SetOctetString(pubKeyLen, output + idx); + XMEMCPY(output + idx, pubKey, pubKeyLen); + idx += pubKeyLen; + } + + ret = idx; + } +#else + CALLOC_ASNSETDATA(dataASN, edKeyASN_Length, ret, NULL); if (ret == 0) { - /* Set Ed25519 OID. */ - SetASN_Buffer(&dataASN[1], keyEd25519Oid, sizeof(keyEd25519Oid)); + /* Set version = 0 */ + SetASN_Int8Bit(&dataASN[1], 0); + /* Set OID. */ + SetASN_OID(&dataASN[3], keyType, oidKeyType); /* Leave space for private key. */ - SetASN_Buffer(&dataASN[5], NULL, ED25519_KEY_SIZE); + SetASN_Buffer(&dataASN[5], NULL, privKeyLen); /* Don't write out attributes. */ dataASN[6].noOut = 1; - if (pubOut) { + if (pubKey) { /* Leave space for public key. */ - SetASN_Buffer(&dataASN[8], NULL, ED25519_PUB_KEY_SIZE); + SetASN_Buffer(&dataASN[8], NULL, pubKeyLen); } else { /* Don't put out public part. */ @@ -27170,24 +27144,22 @@ static int wc_BuildEd25519KeyDer(ed25519_key* key, byte* output, word32 inLen, /* Calculate the size of encoding. */ ret = SizeASN_Items(edKeyASN, dataASN, edKeyASN_Length, &sz); } + /* Check buffer is big enough. */ - if ((ret == 0) && (sz > (int)inLen)) { + if ((ret == 0) && (output != NULL) && (sz > (int)outLen)) { ret = BAD_FUNC_ARG; } - if (ret == 0) { - /* Encode Ed25519 private key. */ + if (ret == 0 && output != NULL) { + /* Encode private key. */ SetASN_Items(edKeyASN, dataASN, edKeyASN_Length, output); /* Put private value into space provided. */ - privSz = ED25519_KEY_SIZE; - ret = wc_ed25519_export_private_only(key, - (byte*)dataASN[5].data.buffer.data, &privSz); - } - if ((ret == 0) && pubOut) { - /* Put public value into space provided. */ - word32 pubSz = ED25519_PUB_KEY_SIZE; - ret = wc_ed25519_export_public(key, (byte*)dataASN[8].data.buffer.data, - &pubSz); + XMEMCPY((byte*)dataASN[5].data.buffer.data, privKey, privKeyLen); + + if (pubKey != NULL) { + /* Put public value into space provided. */ + XMEMCPY((byte*)dataASN[8].data.buffer.data, pubKey, pubKeyLen); + } } if (ret == 0) { @@ -27196,348 +27168,234 @@ static int wc_BuildEd25519KeyDer(ed25519_key* key, byte* output, word32 inLen, } FREE_ASNSETDATA(dataASN, NULL); - return ret; #endif + return ret; } +#endif /* WC_ENABLE_ASYM_KEY_EXPORT */ -/* Write a Private ecc key, including public to DER format, +#if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_EXPORT) +/* Write a Private ED25519 key, including public to DER format, * length on success else < 0 */ int wc_Ed25519KeyToDer(ed25519_key* key, byte* output, word32 inLen) { - return wc_BuildEd25519KeyDer(key, output, inLen, 1); + if (key == NULL) { + return BAD_FUNC_ARG; + } + return SetAsymKeyDer(key->k, ED25519_KEY_SIZE, + key->p, ED25519_PUB_KEY_SIZE, output, inLen, ED25519k); } -/* Write only private Ed25519 key to DER format, +/* Write only private ED25519 key to DER format, * length on success else < 0 */ int wc_Ed25519PrivateKeyToDer(ed25519_key* key, byte* output, word32 inLen) { - return wc_BuildEd25519KeyDer(key, output, inLen, 0); + if (key == NULL) { + return BAD_FUNC_ARG; + } + return SetAsymKeyDer(key->k, ED25519_KEY_SIZE, + NULL, 0, output, inLen, ED25519k); +} +#endif /* HAVE_ED25519 && HAVE_ED25519_KEY_EXPORT */ + +#if defined(HAVE_CURVE25519) && defined(HAVE_CURVE25519_KEY_EXPORT) +/* Write only private Curve25519 key to DER format, + * length on success else < 0 */ +int wc_Curve25519PrivateKeyToDer(curve25519_key* key, byte* output, word32 inLen) +{ + int ret; + byte privKey[CURVE25519_KEYSIZE]; + word32 privKeyLen = CURVE25519_KEYSIZE; + + if (key == NULL) { + return BAD_FUNC_ARG; + } + + ret = wc_curve25519_export_private_raw(key, privKey, &privKeyLen); + if (ret == 0) { + ret = SetAsymKeyDer(privKey, privKeyLen, NULL, 0, output, inLen, + X25519k); + } + return ret; } -#endif /* WOLFSSL_KEY_GEN && HAVE_ED25519_KEY_EXPORT */ +/* Write a public Curve25519 key to DER format, + * length on success else < 0 */ +int wc_Curve25519PublicKeyToDer(curve25519_key* key, byte* output, word32 inLen, + int withAlg) +{ + int ret; + byte pubKey[CURVE25519_KEYSIZE]; + word32 pubKeyLen = (word32)sizeof(pubKey); -#endif /* HAVE_ED25519 */ + if (key == NULL || output == NULL) { + return BAD_FUNC_ARG; + } -#ifdef HAVE_ED448 + ret = wc_curve25519_export_public(key, pubKey, &pubKeyLen); + if (ret == 0) { + ret = SetAsymKeyDerPublic(pubKey, pubKeyLen, output, inLen, + X25519k, withAlg); + } + return ret; +} +#endif /* HAVE_CURVE25519 && HAVE_CURVE25519_KEY_EXPORT */ -#ifdef HAVE_ED448_KEY_IMPORT +#if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_IMPORT) int wc_Ed448PrivateKeyDecode(const byte* input, word32* inOutIdx, - ed448_key* key, word32 inSz) + ed448_key* key, word32 inSz) { -#ifndef WOLFSSL_ASN_TEMPLATE - word32 oid; - int ret, version, length, endKeyIdx, privSz, pubSz; - const byte* priv; - const byte* pub; + int ret; + byte privKey[ED448_KEY_SIZE], pubKey[ED448_PUB_KEY_SIZE]; + word32 privKeyLen = (word32)sizeof(privKey); + word32 pubKeyLen = (word32)sizeof(pubKey); - if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) + if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) { return BAD_FUNC_ARG; - - if (GetSequence(input, inOutIdx, &length, inSz) >= 0) { - endKeyIdx = *inOutIdx + length; - - if (GetMyVersion(input, inOutIdx, &version, inSz) < 0) - return ASN_PARSE_E; - if (version != 0) { - WOLFSSL_MSG("Unrecognized version of ED448 private key"); - return ASN_PARSE_E; - } - - if (GetAlgoId(input, inOutIdx, &oid, oidKeyType, inSz) < 0) - return ASN_PARSE_E; - if (oid != ED448k) - return ASN_PARSE_E; - - if (GetOctetString(input, inOutIdx, &length, inSz) < 0) - return ASN_PARSE_E; - - if (GetOctetString(input, inOutIdx, &privSz, inSz) < 0) - return ASN_PARSE_E; - - priv = input + *inOutIdx; - *inOutIdx += privSz; - } - else { - if (GetOctetString(input, inOutIdx, &privSz, inSz) < 0) - return ASN_PARSE_E; - - if (privSz != 57) - return ASN_PARSE_E; - - priv = input + *inOutIdx; - *inOutIdx += privSz; - endKeyIdx = *inOutIdx; } - if (endKeyIdx == (int)*inOutIdx) { - ret = wc_ed448_import_private_only(priv, privSz, key); - } - else { - if (GetASNHeader(input, ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1, - inOutIdx, &length, inSz) < 0) { - return ASN_PARSE_E; - } - if (GetOctetString(input, inOutIdx, &pubSz, inSz) < 0) - return ASN_PARSE_E; - pub = input + *inOutIdx; - *inOutIdx += pubSz; - - ret = wc_ed448_import_private_key(priv, privSz, pub, pubSz, key); - } - if (ret == 0 && endKeyIdx != (int)*inOutIdx) - return ASN_PARSE_E; - - return ret; -#else - DECL_ASNGETDATA(dataASN, edKeyASN_Length); - int ret = 0; - - CALLOC_ASNGETDATA(dataASN, edKeyASN_Length, ret, NULL); - + ret = DecodeAsymKey(input, inOutIdx, inSz, privKey, &privKeyLen, + pubKey, &pubKeyLen, ED448k); if (ret == 0) { - /* Require Ed448 OID. */ - GetASN_ExpBuffer(&dataASN[3], keyEd448Oid, sizeof(keyEd448Oid)); - /* Parse full private key. */ - ret = GetASN_Items(edKeyASN, dataASN, edKeyASN_Length, 1, input, - inOutIdx, inSz); - if (ret != 0) { - /* Parse just the OCTET_STRING. */ - ret = GetASN_Items(&edKeyASN[5], &dataASN[5], 1, 0, input, inOutIdx, - inSz); - if (ret != 0) { - ret = ASN_PARSE_E; - } - } - } - /* Check the private value length is correct. */ - if ((ret == 0) && dataASN[5].data.ref.length != ED448_KEY_SIZE) { - ret = ASN_PARSE_E; - } - if ((ret == 0) && dataASN[7].tag == 0) { - /* Import just the private value. */ - ret = wc_ed448_import_private_only(dataASN[5].data.ref.data, - ED448_KEY_SIZE, key); - } - else if ((ret == 0) && (dataASN[8].data.ref.length != ED448_PUB_KEY_SIZE)) { - ret = ASN_PARSE_E; - } - else if (ret == 0) { - /* Import private and public value. */ - ret = wc_ed448_import_private_key(dataASN[5].data.ref.data, - ED448_KEY_SIZE, dataASN[8].data.ref.data, ED448_PUB_KEY_SIZE, - key); - } - - FREE_ASNGETDATA(dataASN, NULL); - return ret; -#endif /* WOLFSSL_ASN_TEMPLATE */ -} - - -int wc_Ed448PublicKeyDecode(const byte* input, word32* inOutIdx, - ed448_key* key, word32 inSz) -{ -#ifndef WOLFSSL_ASN_TEMPLATE - int length; - int ret; - - if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) - return BAD_FUNC_ARG; - - if (GetSequence(input, inOutIdx, &length, inSz) < 0) - return ASN_PARSE_E; - - if (GetSequence(input, inOutIdx, &length, inSz) < 0) - return ASN_PARSE_E; - - ret = SkipObjectId(input, inOutIdx, inSz); - if (ret != 0) - return ret; - - /* key header */ - ret = CheckBitString(input, inOutIdx, NULL, inSz, 1, NULL); - if (ret != 0) - return ret; - - /* This is the raw point data compressed or uncompressed. */ - if (wc_ed448_import_public(input + *inOutIdx, inSz - *inOutIdx, key) != 0) - return ASN_ECC_KEY_E; - - return 0; -#else - DECL_ASNGETDATA(dataASN, edPubKeyASN_Length); - int ret = 0; - - CALLOC_ASNGETDATA(dataASN, edPubKeyASN_Length, ret, NULL); - - if (ret == 0) { - /* Require Ed448 OID. */ - GetASN_ExpBuffer(&dataASN[2], keyEd448Oid, sizeof(keyEd448Oid)); - /* Decode Ed448 private key. */ - ret = GetASN_Items(edPubKeyASN, dataASN, edPubKeyASN_Length, 1, input, - inOutIdx, inSz); - if (ret != 0) { - ret = ASN_PARSE_E; - } - } - /* Check the public value length is correct. */ - if ((ret == 0) && (dataASN[3].data.ref.length != ED448_PUB_KEY_SIZE)) { - ret = ASN_PARSE_E; - } - if (ret == 0) { - /* Import the public value. */ - ret = wc_ed448_import_public(dataASN[3].data.ref.data, - ED448_PUB_KEY_SIZE, key); - if (ret != 0) { - ret = ASN_ECC_KEY_E; - } - } - - FREE_ASNGETDATA(dataASN, NULL); - return ret; -#endif /* WOLFSSL_ASN_TEMPLATE */ -} -#endif /* HAVE_ED448_KEY_IMPORT */ - -#if defined(WOLFSSL_KEY_GEN) && defined(HAVE_ED448_KEY_EXPORT) - -/* build DER formatted ED448 key, - * return length on success, negative on error */ -static int wc_BuildEd448KeyDer(ed448_key* key, byte* output, word32 inLen, - int pubOut) -{ -#ifndef WOLFSSL_ASN_TEMPLATE - byte algoArray[MAX_ALGO_SZ]; - byte ver[MAX_VERSION_SZ]; - byte seq[MAX_SEQ_SZ]; - int ret; - word32 idx = 0, seqSz, verSz, algoSz, privSz, pubSz = 0; - - if (key == NULL || output == NULL || inLen == 0) - return BAD_FUNC_ARG; - - if (pubOut) { - pubSz = 2 + 2 + ED448_PUB_KEY_SIZE; - } - privSz = 2 + 2 + ED448_KEY_SIZE; - algoSz = SetAlgoID(ED448k, algoArray, oidKeyType, 0); - verSz = SetMyVersion(0, ver, FALSE); - seqSz = SetSequence(verSz + algoSz + privSz + pubSz, seq); - - if (seqSz + verSz + algoSz + privSz + pubSz > inLen) - return BAD_FUNC_ARG; - - /* write out */ - /* seq */ - XMEMCPY(output + idx, seq, seqSz); - idx = seqSz; - /* ver */ - XMEMCPY(output + idx, ver, verSz); - idx += verSz; - /* algo */ - XMEMCPY(output + idx, algoArray, algoSz); - idx += algoSz; - /* privKey */ - idx += SetOctetString(2 + ED448_KEY_SIZE, output + idx); - idx += SetOctetString(ED448_KEY_SIZE, output + idx); - ret = wc_ed448_export_private_only(key, output + idx, &privSz); - if (ret != 0) - return ret; - idx += privSz; - /* pubKey */ - if (pubOut) { - idx += SetExplicit(1, 2 + ED448_PUB_KEY_SIZE, output + idx); - idx += SetOctetString(ED448_KEY_SIZE, output + idx); - ret = wc_ed448_export_public(key, output + idx, &pubSz); - if (ret != 0) - return ret; - idx += pubSz; - } - - return idx; -#else - DECL_ASNSETDATA(dataASN, edKeyASN_Length); - word32 privSz; - int ret = 0; - int sz; - - /* Validate parameters. */ - if ((key == NULL) || (output == NULL) || (inLen == 0)) { - ret = BAD_FUNC_ARG; - } - - CALLOC_ASNSETDATA(dataASN, edKeyASN_Length, ret, NULL); - - if (ret == 0) { - /* Set Ed448 OID. */ - SetASN_Buffer(&dataASN[1], keyEd448Oid, sizeof(keyEd448Oid)); - /* Leave space for private key. */ - SetASN_Buffer(&dataASN[5], NULL, ED448_KEY_SIZE); - /* Don't write out attributes. */ - dataASN[6].noOut = 1; - if (pubOut) { - /* Leave space for public key. */ - SetASN_Buffer(&dataASN[8], NULL, ED448_PUB_KEY_SIZE); + if (pubKeyLen == 0) { + ret = wc_ed448_import_private_only(privKey, privKeyLen, key); } else { - /* Don't put out public part. */ - dataASN[7].noOut = dataASN[8].noOut = 1; + ret = wc_ed448_import_private_key(privKey, privKeyLen, + pubKey, pubKeyLen, key); } - - /* Calculate the size of encoding. */ - ret = SizeASN_Items(edKeyASN, dataASN, edKeyASN_Length, &sz); } - /* Check buffer is big enough. */ - if ((ret == 0) && (sz > (int)inLen)) { - ret = BAD_FUNC_ARG; - } - if (ret == 0) { - /* Encode Ed448 private key. */ - SetASN_Items(edKeyASN, dataASN, edKeyASN_Length, output); - - /* Put private value into space provided. */ - privSz = ED448_KEY_SIZE; - ret = wc_ed448_export_private_only(key, - (byte*)dataASN[5].data.buffer.data, &privSz); - } - if ((ret == 0) && pubOut) { - /* Put public value into space provided. */ - word32 pubSz = ED448_PUB_KEY_SIZE; - ret = wc_ed448_export_public(key, (byte*)dataASN[8].data.buffer.data, - &pubSz); - } - - if (ret == 0) { - /* Return size of encoding. */ - ret = sz; - } - - FREE_ASNSETDATA(dataASN, NULL); return ret; -#endif } +int wc_Ed448PublicKeyDecode(const byte* input, word32* inOutIdx, + ed448_key* key, word32 inSz) +{ + int ret; + byte pubKey[ED448_PUB_KEY_SIZE]; + word32 pubKeyLen = (word32)sizeof(pubKey); + + if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) { + return BAD_FUNC_ARG; + } + + ret = DecodeAsymKeyPublic(input, inOutIdx, inSz, + pubKey, &pubKeyLen, ED448k); + if (ret == 0) { + ret = wc_ed448_import_public(pubKey, pubKeyLen, key); + } + return ret; +} +#endif /* HAVE_ED448 && HAVE_ED448_KEY_IMPORT */ + +#if defined(HAVE_CURVE448) && defined(HAVE_CURVE448_KEY_IMPORT) +int wc_Curve448PrivateKeyDecode(const byte* input, word32* inOutIdx, + curve448_key* key, word32 inSz) +{ + int ret; + byte privKey[CURVE448_KEY_SIZE]; + word32 privKeyLen = CURVE448_KEY_SIZE; + + if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) { + return BAD_FUNC_ARG; + } + + ret = DecodeAsymKey(input, inOutIdx, inSz, privKey, &privKeyLen, + NULL, NULL, X448k); + if (ret == 0) { + ret = wc_curve448_import_private(privKey, privKeyLen, key); + } + return ret; +} + +int wc_Curve448PublicKeyDecode(const byte* input, word32* inOutIdx, + curve448_key* key, word32 inSz) +{ + int ret; + byte pubKey[CURVE448_PUB_KEY_SIZE]; + word32 pubKeyLen = (word32)sizeof(pubKey); + + if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) { + return BAD_FUNC_ARG; + } + + ret = DecodeAsymKeyPublic(input, inOutIdx, inSz, + pubKey, &pubKeyLen, X448k); + if (ret == 0) { + ret = wc_curve448_import_public(pubKey, pubKeyLen, key); + } + return ret; +} +#endif /* HAVE_CURVE448 && HAVE_ED448_KEY_IMPORT */ + +#if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_EXPORT) /* Write a Private ecc key, including public to DER format, * length on success else < 0 */ int wc_Ed448KeyToDer(ed448_key* key, byte* output, word32 inLen) { - return wc_BuildEd448KeyDer(key, output, inLen, 1); + if (key == NULL) { + return BAD_FUNC_ARG; + } + return SetAsymKeyDer(key->k, ED448_KEY_SIZE, + key->p, ED448_KEY_SIZE, output, inLen, ED448k); } - - /* Write only private ecc key to DER format, * length on success else < 0 */ int wc_Ed448PrivateKeyToDer(ed448_key* key, byte* output, word32 inLen) { - return wc_BuildEd448KeyDer(key, output, inLen, 0); + if (key == NULL) { + return BAD_FUNC_ARG; + } + return SetAsymKeyDer(key->k, ED448_KEY_SIZE, + NULL, 0, output, inLen, ED448k); } -#endif /* WOLFSSL_KEY_GEN && HAVE_ED448_KEY_EXPORT */ +#endif /* HAVE_ED448 && HAVE_ED448_KEY_EXPORT */ -#endif /* HAVE_ED448 */ +#if defined(HAVE_CURVE448) && defined(HAVE_CURVE448_KEY_EXPORT) +/* Write private Curve448 key to DER format, + * length on success else < 0 */ +int wc_Curve448PrivateKeyToDer(curve448_key* key, byte* output, word32 inLen) +{ + int ret; + byte privKey[CURVE448_KEY_SIZE]; + word32 privKeyLen = CURVE448_KEY_SIZE; -#if (defined(HAVE_OCSP) || defined(HAVE_CRL)) && !defined(WOLFSSL_ASN_TEMPLATE) + if (key == NULL) { + return BAD_FUNC_ARG; + } + + ret = wc_curve448_export_private_raw(key, privKey, &privKeyLen); + if (ret == 0) { + ret = SetAsymKeyDer(privKey, privKeyLen, NULL, 0, output, inLen, + X448k); + } + return ret; +} +/* Write a public Curve448 key to DER format, + * length on success else < 0 */ +int wc_Curve448PublicKeyToDer(curve448_key* key, byte* output, word32 inLen, + int withAlg) +{ + int ret; + byte pubKey[CURVE448_PUB_KEY_SIZE]; + word32 pubKeyLen = (word32)sizeof(pubKey); + + if (key == NULL || output == NULL) { + return BAD_FUNC_ARG; + } + + ret = wc_curve448_export_public(key, pubKey, &pubKeyLen); + if (ret == 0) { + ret = SetAsymKeyDerPublic(pubKey, pubKeyLen, output, inLen, + X448k, withAlg); + } + return ret; +} +#endif /* HAVE_CURVE448 && HAVE_CURVE448_KEY_EXPORT */ + + +#if defined(HAVE_OCSP) || defined(HAVE_CRL) /* Get raw Date only, no processing, 0 on success */ static int GetBasicDate(const byte* source, word32* idx, byte* date, diff --git a/wolfcrypt/src/curve25519.c b/wolfcrypt/src/curve25519.c index 07f1696b2..fe8afd317 100644 --- a/wolfcrypt/src/curve25519.c +++ b/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)) - return ECC_BAD_ARG_E; - - /* check clamping */ - if ((priv[0] & ~248) || - (priv[CURVE25519_KEYSIZE-1] & 128)) { + if ((pub == NULL) || (priv == NULL)) { return ECC_BAD_ARG_E; } + /* check clamping */ + 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; + if (ret == 0) { + /* Clamp the private key */ + ret = curve25519_priv_clamp(key); + } - /* Clamp the private key */ - key[0] &= 248; - key[CURVE25519_KEYSIZE-1] &= 63; /* same &=127 because |=64 after */ - key[CURVE25519_KEYSIZE-1] |= 64; - - 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; } + + /* 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); + } + /* export public point with endianess */ + curve25519_copy_point(out, key->p.point, endian); *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]; - } - else - XMEMCPY(out, key->p.point, 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(<cPoint); - #endif +#ifdef FREESCALE_LTC_ECC + ltcPoint.X = &key->p.point[0]; + ltcPoint.Y = &key->p.pointY[0]; + LTC_PKHA_Curve25519ComputeY(<cPoint); +#endif return 0; } @@ -481,18 +494,11 @@ int wc_curve25519_export_private_raw_ex(curve25519_key* key, byte* out, *outLen = CURVE25519_KEYSIZE; return ECC_BAD_ARG_E; } + + /* export private scalar with endianess */ + curve25519_copy_point(out, key->k, endian); *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); - 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*/ - diff --git a/wolfcrypt/src/curve448.c b/wolfcrypt/src/curve448.c index e926351fd..3a6389cff 100644 --- a/wolfcrypt/src/curve448.c +++ b/wolfcrypt/src/curve448.c @@ -42,6 +42,28 @@ #include #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; + } } diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index a323d2909..fa26ff740 100644 --- a/wolfcrypt/test/test.c +++ b/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); diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 4ad2e6d6d..af99d28a4 100644 --- a/wolfssl/internal.h +++ b/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 diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 1a9829aa3..333e8f66c 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/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 #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; diff --git a/wolfssl/wolfcrypt/asn_public.h b/wolfssl/wolfcrypt/asn_public.h index 9acbd60f7..e8f0be466 100644 --- a/wolfssl/wolfcrypt/asn_public.h +++ b/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, diff --git a/wolfssl/wolfcrypt/curve25519.h b/wolfssl/wolfcrypt/curve25519.h index 3646667e0..b3e5b13a1 100644 --- a/wolfssl/wolfcrypt/curve25519.h +++ b/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 { diff --git a/wolfssl/wolfcrypt/curve448.h b/wolfssl/wolfcrypt/curve448.h index ba2059410..83986fbe3 100644 --- a/wolfssl/wolfcrypt/curve448.h +++ b/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, diff --git a/wolfssl/wolfcrypt/ecc.h b/wolfssl/wolfcrypt/ecc.h index ba8338929..40a6b7993 100644 --- a/wolfssl/wolfcrypt/ecc.h +++ b/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;