Jelajahi Sumber

Merge pull request #7286 from Frauschi/hybrid_signatures

Improvements to dual algorithm certificates
JacobBarthelmeh 2 bulan lalu
induk
melakukan
8b587b563c

+ 14 - 14
examples/client/client.c

@@ -2082,6 +2082,17 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
     WOLFSSL_HEAP_HINT *heap = NULL;
 #endif
 
+#ifdef WOLFSSL_DUAL_ALG_CERTS
+    /* Set our preference for verfication to be for both the native and
+     * alternative chains. Ultimately, its the server's choice. This will be
+     * used in the call to wolfSSL_UseCKS(). */
+    byte cks_order[3] = {
+        WOLFSSL_CKS_SIGSPEC_BOTH,
+        WOLFSSL_CKS_SIGSPEC_ALTERNATIVE,
+        WOLFSSL_CKS_SIGSPEC_NATIVE,
+    };
+#endif /* WOLFSSL_DUAL_ALG_CERTS */
+
     ((func_args*)args)->return_code = -1; /* error state */
 
 #ifndef NO_RSA
@@ -3559,20 +3570,9 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
     }
 
 #ifdef WOLFSSL_DUAL_ALG_CERTS
-    /* Set our preference for verfication to be for both the native and
-     * alternative chains. Ultimately, its the server's choice.
-     */
-    {
-        byte cks_order[3] = {
-            WOLFSSL_CKS_SIGSPEC_BOTH,
-            WOLFSSL_CKS_SIGSPEC_ALTERNATIVE,
-            WOLFSSL_CKS_SIGSPEC_NATIVE,
-        };
-
-        if (!wolfSSL_UseCKS(ssl, cks_order, sizeof(cks_order))) {
-            wolfSSL_CTX_free(ctx); ctx = NULL;
-            err_sys("unable to set the CKS order.");
-        }
+    if (!wolfSSL_UseCKS(ssl, cks_order, sizeof(cks_order))) {
+        wolfSSL_CTX_free(ctx); ctx = NULL;
+        err_sys("unable to set the CKS order.");
     }
 #endif /* WOLFSSL_DUAL_ALG_CERTS */
 

+ 408 - 74
src/internal.c

@@ -2251,6 +2251,9 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap)
 
 #ifndef NO_CERTS
     ctx->privateKeyDevId = INVALID_DEVID;
+#ifdef WOLFSSL_DUAL_ALG_CERTS
+    ctx->altPrivateKeyDevId = INVALID_DEVID;
+#endif
 #endif
 
 #ifndef NO_DH
@@ -4333,11 +4336,15 @@ void DecodeSigAlg(const byte* input, byte* hashAlgo, byte* hsType)
     #endif
 #ifdef HAVE_PQC
         case PQC_SA_MAJOR:
-            /* Hash performed as part of sign/verify operation. */
+            /* Hash performed as part of sign/verify operation.
+             * However, if we want a dual alg signature with a
+             * classic algorithm as alternative, we need an explicit
+             * hash algo here.
+             */
     #ifdef HAVE_FALCON
             if (input[1] == FALCON_LEVEL1_SA_MINOR) {
                 *hsType = falcon_level1_sa_algo;
-                *hashAlgo = sha512_mac;
+                *hashAlgo = sha256_mac;
             }
             else if (input[1] == FALCON_LEVEL5_SA_MINOR) {
                 *hsType = falcon_level5_sa_algo;
@@ -4347,11 +4354,11 @@ void DecodeSigAlg(const byte* input, byte* hashAlgo, byte* hsType)
     #ifdef HAVE_DILITHIUM
             if (input[1] == DILITHIUM_LEVEL2_SA_MINOR) {
                 *hsType = dilithium_level2_sa_algo;
-                *hashAlgo = sha512_mac;
+                *hashAlgo = sha256_mac;
             }
             else if (input[1] == DILITHIUM_LEVEL3_SA_MINOR) {
                 *hsType = dilithium_level3_sa_algo;
-                *hashAlgo = sha512_mac;
+                *hashAlgo = sha384_mac;
             }
             else if (input[1] == DILITHIUM_LEVEL5_SA_MINOR) {
                 *hsType = dilithium_level5_sa_algo;
@@ -6761,9 +6768,12 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
     ssl->buffers.keySz    = ctx->privateKeySz;
     ssl->buffers.keyDevId = ctx->privateKeyDevId;
 #ifdef WOLFSSL_DUAL_ALG_CERTS
-    ssl->buffers.altKey     = ctx->altPrivateKey;
-    ssl->buffers.altKeySz   = ctx->altPrivateKeySz;
-    ssl->buffers.altKeyType = ctx->altPrivateKeyType;
+    ssl->buffers.altKey      = ctx->altPrivateKey;
+    ssl->buffers.altKeyType  = ctx->altPrivateKeyType;
+    ssl->buffers.altKeyId    = ctx->altPrivateKeyId;
+    ssl->buffers.altKeyLabel = ctx->altPrivateKeyLabel;
+    ssl->buffers.altKeySz    = ctx->altPrivateKeySz;
+    ssl->buffers.altKeyDevId = ctx->altPrivateKeyDevId;
 #endif /* WOLFSSL_DUAL_ALG_CERTS */
 #endif
 #if !defined(WOLFSSL_NO_CLIENT_AUTH) && \
@@ -12975,23 +12985,40 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert)
     /* Copy over alternative sig and pubkey. In this case we will allocate new
      * buffers for them as we have no knowledge of when the DecodedCert is
      * freed. */
-    x509->sapkiDer = (byte*)XMALLOC(dCert->sapkiLen, x509->heap,
-                                    DYNAMIC_TYPE_X509_EXT);
-    x509->altSigAlgDer = (byte*)XMALLOC(dCert->altSigAlgLen, x509->heap,
+    if (dCert->extSapkiSet) {
+        x509->sapkiDer = (byte*)XMALLOC(dCert->sapkiLen, x509->heap,
                                         DYNAMIC_TYPE_X509_EXT);
-    x509->altSigValDer = (byte*)XMALLOC(dCert->altSigValLen, x509->heap,
-                                        DYNAMIC_TYPE_X509_EXT);
-    if ((x509->sapkiDer != NULL) && (x509->altSigAlgDer != NULL) &&
-        (x509->altSigValDer != NULL)) {
-        XMEMCPY(x509->sapkiDer, dCert->sapkiDer, dCert->sapkiLen);
-        XMEMCPY(x509->altSigAlgDer, dCert->altSigAlgDer, dCert->altSigAlgLen);
-        XMEMCPY(x509->altSigValDer, dCert->altSigValDer, dCert->altSigValLen);
-        x509->sapkiLen = dCert->sapkiLen;
-        x509->altSigAlgLen = dCert->altSigAlgLen;
-        x509->altSigValLen = dCert->altSigValLen;
+        if (x509->sapkiDer != NULL) {
+            XMEMCPY(x509->sapkiDer, dCert->sapkiDer, dCert->sapkiLen);
+            x509->sapkiLen = dCert->sapkiLen;
+        }
+        else {
+            ret = MEMORY_E;
+        }
     }
-    else {
-        ret = MEMORY_E;
+    if (dCert->extAltSigAlgSet) {
+        x509->altSigAlgDer = (byte*)XMALLOC(dCert->altSigAlgLen, x509->heap,
+                                            DYNAMIC_TYPE_X509_EXT);
+        if (x509->altSigAlgDer != NULL) {
+            XMEMCPY(x509->altSigAlgDer, dCert->altSigAlgDer,
+                    dCert->altSigAlgLen);
+            x509->altSigAlgLen = dCert->altSigAlgLen;
+        }
+        else {
+            ret = MEMORY_E;
+        }
+    }
+    if (dCert->extAltSigValSet) {
+        x509->altSigValDer = (byte*)XMALLOC(dCert->altSigValLen, x509->heap,
+                                            DYNAMIC_TYPE_X509_EXT);
+        if (x509->altSigValDer != NULL) {
+            XMEMCPY(x509->altSigValDer, dCert->altSigValDer,
+                    dCert->altSigValLen);
+            x509->altSigValLen = dCert->altSigValLen;
+        }
+        else {
+            ret = MEMORY_E;
+        }
     }
 #endif /* WOLFSSL_DUAL_ALG_CERTS */
 
@@ -13942,39 +13969,6 @@ PRAGMA_GCC_DIAG_POP
         alreadySigner = AlreadySigner(SSL_CM(ssl), subjectHash);
     }
 
-#ifdef WOLFSSL_DUAL_ALG_CERTS
-    if ((ret == 0) && (args->dCert->sapkiDer != NULL)) {
-#ifndef WOLFSSL_SMALL_STACK
-        byte der[MAX_CERT_VERIFY_SZ];
-#else
-        byte *der = (byte*)XMALLOC(MAX_CERT_VERIFY_SZ, ssl->heap,
-                                   DYNAMIC_TYPE_DCERT);
-        if (der == NULL) {
-            ret = MEMORY_E;
-        }
-#endif /* ! WOLFSSL_SMALL_STACK */
-
-        if (ret == 0) {
-            ret = wc_GeneratePreTBS(args->dCert, der, MAX_CERT_VERIFY_SZ);
-
-            if (ret > 0) {
-                ret = wc_ConfirmAltSignature(der, ret,
-                    args->dCert->sapkiDer, args->dCert->sapkiLen,
-                    args->dCert->sapkiOID,
-                    args->dCert->altSigValDer, args->dCert->altSigValLen,
-                    args->dCert->altSigAlgOID, ssl->heap);
-            }
-#ifdef WOLFSSL_SMALL_STACK
-            XFREE(der, ssl->heap, DYNAMIC_TYPE_DCERT);
-#endif /* WOLFSSL_SMALL_STACK */
-
-            if (ret == 0) {
-               WOLFSSL_MSG("Alternative signature has been verified!");
-            }
-        }
-    }
-#endif /* WOLFSSL_DUAL_ALG_CERTS */
-
 #ifdef WOLFSSL_SMALL_CERT_VERIFY
     /* get signature check failures from above */
     if (ret == 0)
@@ -27721,9 +27715,12 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length)
             ssl->hsType = DYNAMIC_TYPE_RSA;
         else if (ssl->buffers.keyType == ecc_dsa_sa_algo)
             ssl->hsType = DYNAMIC_TYPE_ECC;
-        else if (ssl->buffers.keyType == falcon_level5_sa_algo)
+        else if ((ssl->buffers.keyType == falcon_level1_sa_algo) ||
+                 (ssl->buffers.keyType == falcon_level5_sa_algo))
             ssl->hsType = DYNAMIC_TYPE_FALCON;
-        else if (ssl->buffers.keyType == dilithium_level5_sa_algo)
+        else if ((ssl->buffers.keyType == dilithium_level2_sa_algo) ||
+                 (ssl->buffers.keyType == dilithium_level3_sa_algo) ||
+                 (ssl->buffers.keyType == dilithium_level5_sa_algo))
             ssl->hsType = DYNAMIC_TYPE_DILITHIUM;
         ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey);
         if (ret != 0) {
@@ -27782,7 +27779,8 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length)
             ret = NOT_COMPILED_IN;
     #endif
         }
-        else if (ssl->buffers.keyType == falcon_level5_sa_algo) {
+        else if ((ssl->buffers.keyType == falcon_level1_sa_algo) ||
+                 (ssl->buffers.keyType == falcon_level5_sa_algo)) {
     #if defined(HAVE_PQC) && defined(HAVE_FALCON)
             if (ssl->buffers.keyLabel) {
                 ret = wc_falcon_init_label((falcon_key*)ssl->hsKey,
@@ -27795,6 +27793,14 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length)
                                         ssl->buffers.key->length, ssl->heap,
                                         ssl->buffers.keyDevId);
             }
+            if (ret == 0) {
+                if (ssl->buffers.keyType == falcon_level1_sa_algo) {
+                    ret = wc_falcon_set_level((falcon_key*)ssl->hsKey, 1);
+                }
+                else if (ssl->buffers.keyType == falcon_level5_sa_algo) {
+                    ret = wc_falcon_set_level((falcon_key*)ssl->hsKey, 5);
+                }
+            }
             if (ret == 0) {
                 if (ssl->buffers.keySz < ssl->options.minFalconKeySz) {
                     WOLFSSL_MSG("Falcon key size too small");
@@ -27808,7 +27814,9 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length)
             ret = NOT_COMPILED_IN;
     #endif
         }
-        else if (ssl->buffers.keyType == dilithium_level5_sa_algo) {
+        else if ((ssl->buffers.keyType == dilithium_level2_sa_algo) ||
+                 (ssl->buffers.keyType == dilithium_level3_sa_algo) ||
+                 (ssl->buffers.keyType == dilithium_level5_sa_algo)) {
     #if defined(HAVE_PQC) && defined(HAVE_DILITHIUM)
             if (ssl->buffers.keyLabel) {
                 ret = wc_dilithium_init_label((dilithium_key*)ssl->hsKey,
@@ -27821,6 +27829,17 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length)
                                         ssl->buffers.key->length, ssl->heap,
                                         ssl->buffers.keyDevId);
             }
+            if (ret == 0) {
+                if (ssl->buffers.keyType == dilithium_level2_sa_algo) {
+                    ret = wc_dilithium_set_level((dilithium_key*)ssl->hsKey, 2);
+                }
+                else if (ssl->buffers.keyType == dilithium_level3_sa_algo) {
+                    ret = wc_dilithium_set_level((dilithium_key*)ssl->hsKey, 3);
+                }
+                else if (ssl->buffers.keyType == dilithium_level5_sa_algo) {
+                    ret = wc_dilithium_set_level((dilithium_key*)ssl->hsKey, 5);
+                }
+            }
             if (ret == 0) {
                 if (ssl->buffers.keySz < ssl->options.minDilithiumKeySz) {
                     WOLFSSL_MSG("Dilithium key size too small");
@@ -28116,13 +28135,14 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length)
             WOLFSSL_MSG("Using Falcon private key");
 
             /* Check it meets the minimum Falcon key size requirements. */
-            if (FALCON_MAX_KEY_SIZE < ssl->options.minFalconKeySz) {
+            keySz = wc_falcon_size((falcon_key*)ssl->hsKey);
+            if (keySz < ssl->options.minFalconKeySz) {
                 WOLFSSL_MSG("Falcon key size too small");
                 ERROR_OUT(FALCON_KEY_SIZE_E, exit_dpk);
             }
 
             /* Return the maximum signature length. */
-            *length = FALCON_MAX_SIG_SIZE;
+            *length = wc_falcon_sig_size((falcon_key*)ssl->hsKey);
 
             goto exit_dpk;
         }
@@ -28187,13 +28207,14 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length)
             WOLFSSL_MSG("Using Dilithium private key");
 
             /* Check it meets the minimum Dilithium key size requirements. */
-            if (DILITHIUM_MAX_KEY_SIZE < ssl->options.minDilithiumKeySz) {
+            keySz = wc_dilithium_size((dilithium_key*)ssl->hsKey);
+            if (keySz < ssl->options.minDilithiumKeySz) {
                 WOLFSSL_MSG("Dilithium key size too small");
                 ERROR_OUT(DILITHIUM_KEY_SIZE_E, exit_dpk);
             }
 
             /* Return the maximum signature length. */
-            *length = DILITHIUM_MAX_SIG_SIZE;
+            *length = wc_dilithium_sig_size((dilithium_key*)ssl->hsKey);
 
             goto exit_dpk;
         }
@@ -28213,12 +28234,15 @@ exit_dpk:
     return ret;
 }
 
-#if defined(HAVE_PQC) && defined(WOLFSSL_DUAL_ALG_CERTS)
-/* This is just like the above, but only consider Falcon and Dilthium and
- * only for the alternative key; not the native key. */
+#if defined(WOLFSSL_DUAL_ALG_CERTS)
+/* This is just like the above, but only consider RSA, ECC, Falcon and
+ * Dilthium; Furthermore, use the alternative key, not the native key.
+ */
 int DecodeAltPrivateKey(WOLFSSL *ssl, word16* length)
 {
     int      ret = BAD_FUNC_ARG;
+    int      keySz;
+    word32   idx;
 
     /* make sure alt private key exists */
     if (ssl->buffers.altKey == NULL || ssl->buffers.altKey->buffer == NULL) {
@@ -28226,8 +28250,280 @@ int DecodeAltPrivateKey(WOLFSSL *ssl, word16* length)
         ERROR_OUT(NO_PRIVATE_KEY, exit_dapk);
     }
 
+#ifdef WOLF_PRIVATE_KEY_ID
+    if (ssl->buffers.altKeyDevId != INVALID_DEVID &&
+        (ssl->buffers.altKeyId || ssl->buffers.altKeyLabel)) {
+        if (ssl->buffers.altKeyType == rsa_sa_algo)
+            ssl->hsAltType = DYNAMIC_TYPE_RSA;
+        else if (ssl->buffers.altKeyType == ecc_dsa_sa_algo)
+            ssl->hsAltType = DYNAMIC_TYPE_ECC;
+        else if ((ssl->buffers.altKeyType == falcon_level1_sa_algo) ||
+                 (ssl->buffers.altKeyType == falcon_level5_sa_algo))
+            ssl->hsAltType = DYNAMIC_TYPE_FALCON;
+        else if ((ssl->buffers.altKeyType == dilithium_level2_sa_algo) ||
+                 (ssl->buffers.altKeyType == dilithium_level3_sa_algo) ||
+                 (ssl->buffers.altKeyType == dilithium_level5_sa_algo))
+            ssl->hsAltType = DYNAMIC_TYPE_DILITHIUM;
+        ret = AllocKey(ssl, ssl->hsAltType, &ssl->hsAltKey);
+        if (ret != 0) {
+            goto exit_dapk;
+        }
+
+        if (ssl->buffers.altKeyType == rsa_sa_algo) {
+    #ifndef NO_RSA
+            if (ssl->buffers.altKeyLabel) {
+                ret = wc_InitRsaKey_Label((RsaKey*)ssl->hsAltKey,
+                                          (char*)ssl->buffers.altKey->buffer,
+                                          ssl->heap, ssl->buffers.altKeyDevId);
+            }
+            else if (ssl->buffers.altKeyId) {
+                ret = wc_InitRsaKey_Id((RsaKey*)ssl->hsAltKey,
+                                       ssl->buffers.altKey->buffer,
+                                       ssl->buffers.altKey->length, ssl->heap,
+                                       ssl->buffers.altKeyDevId);
+            }
+            if (ret == 0) {
+                if (ssl->buffers.altKeySz < ssl->options.minRsaKeySz) {
+                    WOLFSSL_MSG("RSA key size too small");
+                    ERROR_OUT(RSA_KEY_SIZE_E, exit_dapk);
+                }
+
+                /* Return the maximum signature length. */
+                *length = (word16)ssl->buffers.altKeySz;
+            }
+    #else
+            ret = NOT_COMPILED_IN;
+    #endif
+        }
+        else if (ssl->buffers.altKeyType == ecc_dsa_sa_algo) {
+    #ifdef HAVE_ECC
+            if (ssl->buffers.altKeyLabel) {
+                ret = wc_ecc_init_label((ecc_key*)ssl->hsAltKey,
+                                        (char*)ssl->buffers.altKey->buffer,
+                                        ssl->heap, ssl->buffers.altKeyDevId);
+            }
+            else if (ssl->buffers.altKeyId) {
+                ret = wc_ecc_init_id((ecc_key*)ssl->hsAltKey,
+                                     ssl->buffers.altKey->buffer,
+                                     ssl->buffers.altKey->length, ssl->heap,
+                                     ssl->buffers.altKeyDevId);
+            }
+            if (ret == 0) {
+                if (ssl->buffers.altKeySz < ssl->options.minEccKeySz) {
+                    WOLFSSL_MSG("ECC key size too small");
+                    ERROR_OUT(ECC_KEY_SIZE_E, exit_dapk);
+                }
+
+                /* Return the maximum signature length. */
+                *length = (word16)wc_ecc_sig_size_calc(ssl->buffers.altKeySz);
+            }
+    #else
+            ret = NOT_COMPILED_IN;
+    #endif
+        }
+        else if ((ssl->buffers.altKeyType == falcon_level1_sa_algo) ||
+                 (ssl->buffers.altKeyType == falcon_level5_sa_algo)) {
+    #if defined(HAVE_PQC) && defined(HAVE_FALCON)
+            if (ssl->buffers.altKeyLabel) {
+                ret = wc_falcon_init_label((falcon_key*)ssl->hsAltKey,
+                                           (char*)ssl->buffers.altKey->buffer,
+                                           ssl->heap, ssl->buffers.altKeyDevId);
+            }
+            else if (ssl->buffers.altKeyId) {
+                ret = wc_falcon_init_id((falcon_key*)ssl->hsAltKey,
+                                        ssl->buffers.altKey->buffer,
+                                        ssl->buffers.altKey->length, ssl->heap,
+                                        ssl->buffers.altKeyDevId);
+            }
+            if (ret == 0) {
+                if (ssl->buffers.altKeyType == falcon_level1_sa_algo) {
+                    ret = wc_falcon_set_level((falcon_key*)ssl->hsAltKey, 1);
+                }
+                else if (ssl->buffers.altKeyType == falcon_level5_sa_algo) {
+                    ret = wc_falcon_set_level((falcon_key*)ssl->hsAltKey, 5);
+                }
+            }
+            if (ret == 0) {
+                if (ssl->buffers.altKeySz < ssl->options.minFalconKeySz) {
+                    WOLFSSL_MSG("Falcon key size too small");
+                    ERROR_OUT(FALCON_KEY_SIZE_E, exit_dapk);
+                }
+
+                /* Return the maximum signature length. */
+                *length = (word16)
+                            wc_falcon_sig_size((falcon_key*)ssl->hsAltKey);
+            }
+    #else
+            ret = NOT_COMPILED_IN;
+    #endif
+        }
+        else if ((ssl->buffers.altKeyType == dilithium_level2_sa_algo) ||
+                 (ssl->buffers.altKeyType == dilithium_level3_sa_algo) ||
+                 (ssl->buffers.altKeyType == dilithium_level5_sa_algo)) {
+    #if defined(HAVE_PQC) && defined(HAVE_DILITHIUM)
+            if (ssl->buffers.altKeyLabel) {
+                ret = wc_dilithium_init_label((dilithium_key*)ssl->hsAltKey,
+                                        (char*)ssl->buffers.altKey->buffer,
+                                        ssl->heap, ssl->buffers.altKeyDevId);
+            }
+            else if (ssl->buffers.altKeyId) {
+                ret = wc_dilithium_init_id((dilithium_key*)ssl->hsAltKey,
+                                        ssl->buffers.altKey->buffer,
+                                        ssl->buffers.altKey->length, ssl->heap,
+                                        ssl->buffers.altKeyDevId);
+            }
+            if (ret == 0) {
+                if (ssl->buffers.altKeyType == dilithium_level2_sa_algo) {
+                    ret = wc_dilithium_set_level(
+                                        (dilithium_key*)ssl->hsAltKey, 2);
+                }
+                else if (ssl->buffers.altKeyType == dilithium_level3_sa_algo) {
+                    ret = wc_dilithium_set_level(
+                                        (dilithium_key*)ssl->hsAltKey, 3);
+                }
+                else if (ssl->buffers.altKeyType == dilithium_level5_sa_algo) {
+                    ret = wc_dilithium_set_level(
+                                        (dilithium_key*)ssl->hsAltKey, 5);
+                }
+            }
+            if (ret == 0) {
+                if (ssl->buffers.altKeySz < ssl->options.minDilithiumKeySz) {
+                    WOLFSSL_MSG("Dilithium key size too small");
+                    ERROR_OUT(DILITHIUM_KEY_SIZE_E, exit_dapk);
+                }
+
+                /* Return the maximum signature length. */
+                *length = (word16)wc_dilithium_sig_size(
+                                    (dilithium_key*)ssl->hsAltKey);
+            }
+    #else
+            ret = NOT_COMPILED_IN;
+    #endif
+        }
+        goto exit_dapk;
+    }
+#endif /* WOLF_PRIVATE_KEY_ID */
+
+#ifndef NO_RSA
+    if (ssl->buffers.altKeyType == rsa_sa_algo ||
+        ssl->buffers.altKeyType == 0) {
+        ssl->hsAltType = DYNAMIC_TYPE_RSA;
+        ret = AllocKey(ssl, ssl->hsAltType, &ssl->hsAltKey);
+        if (ret != 0) {
+            goto exit_dapk;
+        }
+
+        WOLFSSL_MSG("Trying RSA private key");
+
+        /* Set start of data to beginning of buffer. */
+        idx = 0;
+        /* Decode the key assuming it is an RSA private key. */
+        ret = wc_RsaPrivateKeyDecode(ssl->buffers.altKey->buffer, &idx,
+                    (RsaKey*)ssl->hsAltKey, ssl->buffers.altKey->length);
+    #ifdef WOLF_PRIVATE_KEY_ID
+        /* if using external key then allow using a public key */
+        if (ret != 0 && (ssl->devId != INVALID_DEVID
+        #ifdef HAVE_PK_CALLBACKS
+            || wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)
+        #endif
+        )) {
+            WOLFSSL_MSG("Trying RSA public key with crypto callbacks");
+            idx = 0;
+            ret = wc_RsaPublicKeyDecode(ssl->buffers.altKey->buffer, &idx,
+                        (RsaKey*)ssl->hsAltKey, ssl->buffers.altKey->length);
+        }
+    #endif
+        if (ret == 0) {
+            WOLFSSL_MSG("Using RSA private key");
+
+            /* It worked so check it meets minimum key size requirements. */
+            keySz = wc_RsaEncryptSize((RsaKey*)ssl->hsAltKey);
+            if (keySz < 0) { /* check if keySz has error case */
+                ERROR_OUT(keySz, exit_dapk);
+            }
+
+            if (keySz < ssl->options.minRsaKeySz) {
+                WOLFSSL_MSG("RSA key size too small");
+                ERROR_OUT(RSA_KEY_SIZE_E, exit_dapk);
+            }
+
+            /* Return the maximum signature length. */
+            *length = (word16)keySz;
+
+            goto exit_dapk;
+        }
+    }
+#endif /* !NO_RSA */
+
+#ifdef HAVE_ECC
+#ifndef NO_RSA
+    FreeKey(ssl, ssl->hsAltType, (void**)&ssl->hsAltKey);
+#endif /* !NO_RSA */
+
+    if (ssl->buffers.altKeyType == ecc_dsa_sa_algo ||
+        ssl->buffers.altKeyType == 0
+    #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+         || ssl->buffers.altKeyType == sm2_sa_algo
+    #endif
+        ) {
+        ssl->hsAltType = DYNAMIC_TYPE_ECC;
+        ret = AllocKey(ssl, ssl->hsAltType, &ssl->hsAltKey);
+        if (ret != 0) {
+            goto exit_dapk;
+        }
+
+    #ifndef NO_RSA
+        WOLFSSL_MSG("Trying ECC private key, RSA didn't work");
+    #else
+        WOLFSSL_MSG("Trying ECC private key");
+    #endif
+
+        /* Set start of data to beginning of buffer. */
+        idx = 0;
+        /* Decode the key assuming it is an ECC private key. */
+        ret = wc_EccPrivateKeyDecode(ssl->buffers.altKey->buffer, &idx,
+                                     (ecc_key*)ssl->hsAltKey,
+                                     ssl->buffers.altKey->length);
+    #ifdef WOLF_PRIVATE_KEY_ID
+        /* if using external key then allow using a public key */
+        if (ret != 0 && (ssl->devId != INVALID_DEVID
+        #ifdef HAVE_PK_CALLBACKS
+            || wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)
+        #endif
+        )) {
+            WOLFSSL_MSG("Trying ECC public key with crypto callbacks");
+            idx = 0;
+            ret = wc_EccPublicKeyDecode(ssl->buffers.altKey->buffer, &idx,
+                                     (ecc_key*)ssl->hsAltKey,
+                                     ssl->buffers.altKey->length);
+        }
+    #endif
+        if (ret == 0) {
+            WOLFSSL_MSG("Using ECC private key");
+
+            /* Check it meets the minimum ECC key size requirements. */
+            keySz = wc_ecc_size((ecc_key*)ssl->hsAltKey);
+            if (keySz < ssl->options.minEccKeySz) {
+                WOLFSSL_MSG("ECC key size too small");
+                ERROR_OUT(ECC_KEY_SIZE_E, exit_dapk);
+            }
+
+            /* Return the maximum signature length. */
+            *length = (word16)wc_ecc_sig_size((ecc_key*)ssl->hsAltKey);
+
+            goto exit_dapk;
+        }
+    }
+#endif
+#if defined(HAVE_PQC)
+#if defined(HAVE_FALCON)
+    #if !defined(NO_RSA) || defined(HAVE_ECC)
+        FreeKey(ssl, ssl->hsAltType, (void**)&ssl->hsAltKey);
+    #endif
+
     if (ssl->buffers.altKeyType == falcon_level1_sa_algo ||
-        ssl->buffers.altKeyType == falcon_level5_sa_algo) {
+        ssl->buffers.altKeyType == falcon_level5_sa_algo ||
+        ssl->buffers.altKeyType == 0) {
 
         ssl->hsAltType = DYNAMIC_TYPE_FALCON;
         ret = AllocKey(ssl, ssl->hsAltType, &ssl->hsAltKey);
@@ -28242,14 +28538,25 @@ int DecodeAltPrivateKey(WOLFSSL *ssl, word16* length)
             ret = wc_falcon_set_level((falcon_key*)ssl->hsAltKey, 5);
         }
         else {
+            /* What if ssl->buffers.keyType is 0? We might want to do something
+             * more graceful here. */
             ret = ALGO_ID_E;
         }
 
         if (ret != 0) {
             goto exit_dapk;
         }
-        WOLFSSL_MSG("Trying Falcon private key");
 
+        #if defined(HAVE_ECC)
+            WOLFSSL_MSG("Trying Falcon private key, ECC didn't work");
+        #elif !defined(NO_RSA)
+            WOLFSSL_MSG("Trying Falcon private key, RSA didn't work");
+        #else
+            WOLFSSL_MSG("Trying Falcon private key");
+        #endif
+
+        /* Set start of data to beginning of buffer. */
+        idx = 0;
         /* Decode the key assuming it is a Falcon private key. */
         ret = wc_falcon_import_private_only(ssl->buffers.altKey->buffer,
                                             ssl->buffers.altKey->length,
@@ -28258,21 +28565,28 @@ int DecodeAltPrivateKey(WOLFSSL *ssl, word16* length)
             WOLFSSL_MSG("Using Falcon private key");
 
             /* Check it meets the minimum Falcon key size requirements. */
-            if (FALCON_MAX_KEY_SIZE < ssl->options.minFalconKeySz) {
+            keySz = wc_falcon_size((falcon_key*)ssl->hsAltKey);
+            if (keySz < ssl->options.minFalconKeySz) {
                 WOLFSSL_MSG("Falcon key size too small");
                 ERROR_OUT(FALCON_KEY_SIZE_E, exit_dapk);
             }
 
+            /* Return the maximum signature length. */
             *length = wc_falcon_sig_size((falcon_key*)ssl->hsAltKey);
 
             goto exit_dapk;
         }
     }
-    FreeKey(ssl, ssl->hsAltType, (void**)&ssl->hsAltKey);
+#endif /* HAVE_FALCON */
+#if defined(HAVE_DILITHIUM)
+    #if !defined(NO_RSA) || defined(HAVE_ECC)
+        FreeKey(ssl, ssl->hsAltType, (void**)&ssl->hsAltKey);
+    #endif
 
     if (ssl->buffers.altKeyType == dilithium_level2_sa_algo ||
         ssl->buffers.altKeyType == dilithium_level3_sa_algo ||
-        ssl->buffers.altKeyType == dilithium_level5_sa_algo) {
+        ssl->buffers.altKeyType == dilithium_level5_sa_algo ||
+        ssl->buffers.altKeyType == 0) {
 
         ssl->hsAltType = DYNAMIC_TYPE_DILITHIUM;
         ret = AllocKey(ssl, ssl->hsAltType, &ssl->hsAltKey);
@@ -28290,6 +28604,8 @@ int DecodeAltPrivateKey(WOLFSSL *ssl, word16* length)
             ret = wc_dilithium_set_level((dilithium_key*)ssl->hsAltKey, 5);
         }
         else {
+            /* What if ssl->buffers.keyType is 0? We might want to do something
+             * more graceful here. */
             ret = ALGO_ID_E;
         }
 
@@ -28297,8 +28613,18 @@ int DecodeAltPrivateKey(WOLFSSL *ssl, word16* length)
             goto exit_dapk;
         }
 
-        WOLFSSL_MSG("Trying Dilithium private key");
+        #if defined(HAVE_FALCON)
+            WOLFSSL_MSG("Trying Dilithium private key, Falcon didn't work");
+        #elif defined(HAVE_ECC)
+            WOLFSSL_MSG("Trying Dilithium private key, ECC didn't work");
+        #elif !defined(NO_RSA)
+            WOLFSSL_MSG("Trying Dilithium private key, RSA didn't work");
+        #else
+            WOLFSSL_MSG("Trying Dilithium private key");
+        #endif
 
+        /* Set start of data to beginning of buffer. */
+        idx = 0;
         /* Decode the key assuming it is a Dilithium private key. */
         ret = wc_dilithium_import_private_only(ssl->buffers.altKey->buffer,
                                                ssl->buffers.altKey->length,
@@ -28307,16 +28633,24 @@ int DecodeAltPrivateKey(WOLFSSL *ssl, word16* length)
             WOLFSSL_MSG("Using Dilithium private key");
 
             /* Check it meets the minimum Dilithium key size requirements. */
-            if (DILITHIUM_MAX_KEY_SIZE < ssl->options.minDilithiumKeySz) {
+            keySz = wc_dilithium_size((dilithium_key*)ssl->hsAltKey);
+            if (keySz < ssl->options.minDilithiumKeySz) {
                 WOLFSSL_MSG("Dilithium key size too small");
                 ERROR_OUT(DILITHIUM_KEY_SIZE_E, exit_dapk);
             }
 
+            /* Return the maximum signature length. */
             *length = wc_dilithium_sig_size((dilithium_key*)ssl->hsAltKey);
 
             goto exit_dapk;
         }
     }
+#endif /* HAVE_DILITHIUM */
+#endif /* HAVE_PQC */
+
+    (void)idx;
+    (void)keySz;
+    (void)length;
 
 exit_dapk:
     if (ret != 0) {
@@ -28325,7 +28659,7 @@ exit_dapk:
 
     return ret;
 }
-#endif /* HAVE_PQC && WOLFSSL_DUAL_ALG_CERTS */
+#endif /* WOLFSSL_DUAL_ALG_CERTS */
 #endif /* WOLFSSL_TLS13 || !NO_WOLFSSL_CLIENT */
 
 #if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_NO_TLS12)

File diff ditekan karena terlalu besar
+ 633 - 197
src/ssl.c


+ 2 - 2
src/tls.c

@@ -9583,7 +9583,7 @@ int TLSX_CKS_Parse(WOLFSSL* ssl, byte* input, word16 length,
             case WOLFSSL_CKS_SIGSPEC_EXTERNAL:
             default:
                 /* All other values (including external) are not. */
-                return WOLFSSL_NOT_IMPLEMENTED;
+                return BAD_FUNC_ARG;
         }
     }
 
@@ -9618,7 +9618,7 @@ int TLSX_CKS_Parse(WOLFSSL* ssl, byte* input, word16 length,
         for (j = 0; j < length; j++) {
             if (ssl->sigSpec[i] == input[j]) {
                 /* Got the match, set to this one. */
-                ret = wolfSSL_UseCKS(ssl, &ssl->peerSigSpec[i], 1);
+                ret = wolfSSL_UseCKS(ssl, &ssl->sigSpec[i], 1);
                 if (ret == WOLFSSL_SUCCESS) {
                     ret = TLSX_UseCKS(&ssl->extensions, ssl, ssl->heap);
                     TLSX_SetResponse(ssl, TLSX_CKS);

File diff ditekan karena terlalu besar
+ 441 - 219
src/tls13.c


+ 177 - 0
src/x509.c

@@ -10171,6 +10171,15 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_chain_up_ref(
     #endif
     #ifndef NO_DSA
         DsaKey* dsa = NULL;
+    #endif
+    #if defined(HAVE_PQC) && defined(HAVE_FALCON)
+        falcon_key* falcon = NULL;
+    #endif
+    #if defined(HAVE_PQC) && defined(HAVE_DILITHIUM)
+        dilithium_key* dilithium = NULL;
+    #endif
+    #if defined(HAVE_PQC) && defined(HAVE_SPHINCS)
+        sphincs_key* sphincs = NULL;
     #endif
         WC_RNG rng;
         word32 idx = 0;
@@ -10297,6 +10306,148 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_chain_up_ref(
             }
             key = (void*)dsa;
         }
+    #endif
+    #if defined(HAVE_PQC) && defined(HAVE_FALCON)
+        if ((x509->pubKeyOID == FALCON_LEVEL1k) ||
+            (x509->pubKeyOID == FALCON_LEVEL5k)) {
+            falcon = (falcon_key*)XMALLOC(sizeof(falcon_key), NULL,
+                                          DYNAMIC_TYPE_FALCON);
+            if (falcon == NULL) {
+                WOLFSSL_MSG("Failed to allocate memory for falcon_key");
+                XFREE(cert, NULL, DYNAMIC_TYPE_CERT);
+                return WOLFSSL_FAILURE;
+            }
+
+            ret = wc_falcon_init(falcon);
+            if (ret != 0) {
+                XFREE(falcon, NULL, DYNAMIC_TYPE_FALCON);
+                XFREE(cert, NULL, DYNAMIC_TYPE_CERT);
+                return ret;
+            }
+
+            if (x509->pubKeyOID == FALCON_LEVEL1k) {
+                type = FALCON_LEVEL1_TYPE;
+                wc_falcon_set_level(falcon, 1);
+            }
+            else if (x509->pubKeyOID == FALCON_LEVEL5k) {
+                type = FALCON_LEVEL5_TYPE;
+                wc_falcon_set_level(falcon, 5);
+            }
+
+            ret = wc_Falcon_PublicKeyDecode(x509->pubKey.buffer, &idx, falcon,
+                                            x509->pubKey.length);
+            if (ret != 0) {
+                WOLFSSL_ERROR_VERBOSE(ret);
+                wc_falcon_free(falcon);
+                XFREE(falcon, NULL, DYNAMIC_TYPE_FALCON);
+                XFREE(cert, NULL, DYNAMIC_TYPE_CERT);
+                return ret;
+            }
+            key = (void*)falcon;
+        }
+    #endif
+    #if defined(HAVE_PQC) && defined(HAVE_DILITHIUM)
+        if ((x509->pubKeyOID == DILITHIUM_LEVEL2k) ||
+            (x509->pubKeyOID == DILITHIUM_LEVEL3k) ||
+            (x509->pubKeyOID == DILITHIUM_LEVEL5k)) {
+            dilithium = (dilithium_key*)XMALLOC(sizeof(dilithium_key), NULL,
+                                          DYNAMIC_TYPE_DILITHIUM);
+            if (dilithium == NULL) {
+                WOLFSSL_MSG("Failed to allocate memory for dilithium_key");
+                XFREE(cert, NULL, DYNAMIC_TYPE_CERT);
+                return WOLFSSL_FAILURE;
+            }
+
+            ret = wc_dilithium_init(dilithium);
+            if (ret != 0) {
+                XFREE(dilithium, NULL, DYNAMIC_TYPE_DILITHIUM);
+                XFREE(cert, NULL, DYNAMIC_TYPE_CERT);
+                return ret;
+            }
+
+            if (x509->pubKeyOID == DILITHIUM_LEVEL2k) {
+                type = DILITHIUM_LEVEL2_TYPE;
+                wc_dilithium_set_level(dilithium, 2);
+            }
+            else if (x509->pubKeyOID == DILITHIUM_LEVEL3k) {
+                type = DILITHIUM_LEVEL3_TYPE;
+                wc_dilithium_set_level(dilithium, 3);
+            }
+            else if (x509->pubKeyOID == DILITHIUM_LEVEL5k) {
+                type = DILITHIUM_LEVEL5_TYPE;
+                wc_dilithium_set_level(dilithium, 5);
+            }
+
+            ret = wc_Dilithium_PublicKeyDecode(x509->pubKey.buffer, &idx,
+                                    dilithium, x509->pubKey.length);
+            if (ret != 0) {
+                WOLFSSL_ERROR_VERBOSE(ret);
+                wc_dilithium_free(dilithium);
+                XFREE(dilithium, NULL, DYNAMIC_TYPE_DILITHIUM);
+                XFREE(cert, NULL, DYNAMIC_TYPE_CERT);
+                return ret;
+            }
+            key = (void*)dilithium;
+        }
+    #endif
+    #if defined(HAVE_PQC) && defined(HAVE_SPHINCS)
+        if ((x509->pubKeyOID == SPHINCS_FAST_LEVEL1k) ||
+            (x509->pubKeyOID == SPHINCS_FAST_LEVEL3k) ||
+            (x509->pubKeyOID == SPHINCS_FAST_LEVEL5k) ||
+            (x509->pubKeyOID == SPHINCS_SMALL_LEVEL1k) ||
+            (x509->pubKeyOID == SPHINCS_SMALL_LEVEL3k) ||
+            (x509->pubKeyOID == SPHINCS_SMALL_LEVEL5k)) {
+            sphincs = (sphincs_key*)XMALLOC(sizeof(sphincs_key), NULL,
+                                          DYNAMIC_TYPE_SPHINCS);
+            if (sphincs == NULL) {
+                WOLFSSL_MSG("Failed to allocate memory for sphincs_key");
+                XFREE(cert, NULL, DYNAMIC_TYPE_CERT);
+                return WOLFSSL_FAILURE;
+            }
+
+            ret = wc_sphincs_init(sphincs);
+            if (ret != 0) {
+                XFREE(sphincs, NULL, DYNAMIC_TYPE_SPHINCS);
+                XFREE(cert, NULL, DYNAMIC_TYPE_CERT);
+                return ret;
+            }
+
+            if (x509->pubKeyOID == SPHINCS_FAST_LEVEL1k) {
+                type = SPHINCS_FAST_LEVEL1_TYPE;
+                wc_sphincs_set_level_and_optim(sphincs, 1, FAST_VARIANT);
+            }
+            else if (x509->pubKeyOID == SPHINCS_FAST_LEVEL3k) {
+                type = SPHINCS_FAST_LEVEL3_TYPE;
+                wc_sphincs_set_level_and_optim(sphincs, 3, FAST_VARIANT);
+            }
+            else if (x509->pubKeyOID == SPHINCS_FAST_LEVEL3k) {
+                type = SPHINCS_FAST_LEVEL5_TYPE;
+                wc_sphincs_set_level_and_optim(sphincs, 5, FAST_VARIANT);
+            }
+            else if (x509->pubKeyOID == SPHINCS_SMALL_LEVEL1k) {
+                type = SPHINCS_SMALL_LEVEL1_TYPE;
+                wc_sphincs_set_level_and_optim(sphincs, 1, SMALL_VARIANT);
+            }
+            else if (x509->pubKeyOID == SPHINCS_SMALL_LEVEL3k) {
+                type = SPHINCS_SMALL_LEVEL3_TYPE;
+                wc_sphincs_set_level_and_optim(sphincs, 3, SMALL_VARIANT);
+            }
+            else if (x509->pubKeyOID == SPHINCS_SMALL_LEVEL3k) {
+                type = SPHINCS_SMALL_LEVEL5_TYPE;
+                wc_sphincs_set_level_and_optim(sphincs, 5, SMALL_VARIANT);
+            }
+
+            ret = wc_Sphincs_PublicKeyDecode(x509->pubKey.buffer, &idx, sphincs,
+                                             x509->pubKey.length);
+            if (ret != 0) {
+                WOLFSSL_ERROR_VERBOSE(ret);
+                wc_sphincs_free(sphincs);
+                XFREE(sphincs, NULL, DYNAMIC_TYPE_SPHINCS);
+                XFREE(cert, NULL, DYNAMIC_TYPE_CERT);
+                return ret;
+            }
+            key = (void*)sphincs;
+        }
     #endif
         if (key == NULL) {
             WOLFSSL_MSG("No public key found for certificate");
@@ -10397,6 +10548,32 @@ cleanup:
             wc_FreeDsaKey(dsa);
             XFREE(dsa, NULL, DYNAMIC_TYPE_DSA);
         }
+    #endif
+    #if defined(HAVE_PQC) && defined(HAVE_FALCON)
+        if ((x509->pubKeyOID == FALCON_LEVEL1k) ||
+            (x509->pubKeyOID == FALCON_LEVEL5k)) {
+            wc_falcon_free(falcon);
+            XFREE(falcon, NULL, DYNAMIC_TYPE_FALCON);
+        }
+    #endif
+    #if defined(HAVE_PQC) && defined(HAVE_DILITHIUM)
+        if ((x509->pubKeyOID == DILITHIUM_LEVEL2k) ||
+            (x509->pubKeyOID == DILITHIUM_LEVEL3k) ||
+            (x509->pubKeyOID == DILITHIUM_LEVEL5k)) {
+            wc_dilithium_free(dilithium);
+            XFREE(dilithium, NULL, DYNAMIC_TYPE_DILITHIUM);
+        }
+    #endif
+    #if defined(HAVE_PQC) && defined(HAVE_SPHINCS)
+        if ((x509->pubKeyOID == SPHINCS_FAST_LEVEL1k) ||
+            (x509->pubKeyOID == SPHINCS_FAST_LEVEL3k) ||
+            (x509->pubKeyOID == SPHINCS_FAST_LEVEL5k) ||
+            (x509->pubKeyOID == SPHINCS_SMALL_LEVEL1k) ||
+            (x509->pubKeyOID == SPHINCS_SMALL_LEVEL3k) ||
+            (x509->pubKeyOID == SPHINCS_SMALL_LEVEL5k)) {
+            wc_sphincs_free(sphincs);
+            XFREE(sphincs, NULL, DYNAMIC_TYPE_SPHINCS);
+        }
     #endif
         XFREE(cert, NULL, DYNAMIC_TYPE_CERT);
 

+ 39 - 8
tests/api.c

@@ -878,7 +878,10 @@ static int do_dual_alg_root_certgen(byte **out, char *caKeyFile,
     XMEMSET(caKeyBuf, 0, caKeySz);
     ExpectNotNull(file = fopen(caKeyFile, "rb"));
     ExpectIntGT(caKeySz = (word32)fread(caKeyBuf, 1, caKeySz, file), 0);
-    fclose(file);
+    if (file) {
+        fclose(file);
+        file = NULL;
+    }
     ExpectIntEQ(wc_InitRsaKey_ex(&caKey, NULL, INVALID_DEVID), 0);
     idx = 0;
     ExpectIntEQ(wc_RsaPrivateKeyDecode(caKeyBuf, &idx, &caKey, caKeySz),
@@ -886,11 +889,17 @@ static int do_dual_alg_root_certgen(byte **out, char *caKeyFile,
     XMEMSET(sapkiBuf, 0, sapkiSz);
     ExpectNotNull(file = fopen(sapkiFile, "rb"));
     ExpectIntGT(sapkiSz = (word32)fread(sapkiBuf, 1, sapkiSz, file), 0);
-    fclose(file);
+    if (file) {
+        fclose(file);
+        file = NULL;
+    }
     XMEMSET(altPrivBuf, 0, altPrivSz);
     ExpectNotNull(file = fopen(altPrivFile, "rb"));
     ExpectIntGT(altPrivSz = (word32)fread(altPrivBuf, 1, altPrivSz, file), 0);
-    fclose(file);
+    if (file) {
+        fclose(file);
+        file = NULL;
+    }
     wc_ecc_init(&altCaKey);
     idx = 0;
     ExpectIntEQ(wc_EccPrivateKeyDecode(altPrivBuf, &idx, &altCaKey,
@@ -938,6 +947,7 @@ static int do_dual_alg_root_certgen(byte **out, char *caKeyFile,
     *out = outBuf;
     wc_FreeRsaKey(&caKey);
     wc_FreeRng(&rng);
+    wc_FreeDecodedCert(&preTBS);
     return outSz;
 }
 
@@ -981,7 +991,10 @@ static int do_dual_alg_server_certgen(byte **out, char *caKeyFile,
     ExpectNotNull(file = fopen(serverKeyFile, "rb"));
     ExpectIntGT(serverKeySz = (word32)fread(serverKeyBuf, 1, serverKeySz, file),
                 0);
-    fclose(file);
+    if (file) {
+        fclose(file);
+        file = NULL;
+    }
     ExpectIntEQ(wc_InitRsaKey_ex(&serverKey, NULL, INVALID_DEVID), 0);
     idx = 0;
     ExpectIntEQ(wc_RsaPrivateKeyDecode(serverKeyBuf, &idx, &serverKey,
@@ -989,7 +1002,10 @@ static int do_dual_alg_server_certgen(byte **out, char *caKeyFile,
     XMEMSET(caKeyBuf, 0, caKeySz);
     ExpectNotNull(file = fopen(caKeyFile, "rb"));
     ExpectIntGT(caKeySz = (word32)fread(caKeyBuf, 1, caKeySz, file), 0);
-    fclose(file);
+    if (file) {
+        fclose(file);
+        file = NULL;
+    }
     ExpectIntEQ(wc_InitRsaKey_ex(&caKey, NULL, INVALID_DEVID), 0);
     idx = 0;
     ExpectIntEQ(wc_RsaPrivateKeyDecode(caKeyBuf, &idx, &caKey,
@@ -997,11 +1013,17 @@ static int do_dual_alg_server_certgen(byte **out, char *caKeyFile,
     XMEMSET(sapkiBuf, 0, sapkiSz);
     ExpectNotNull(file = fopen(sapkiFile, "rb"));
     ExpectIntGT(sapkiSz = (word32)fread(sapkiBuf, 1, sapkiSz, file), 0);
-    fclose(file);
+    if (file) {
+        fclose(file);
+        file = NULL;
+    }
     XMEMSET(altPrivBuf, 0, altPrivSz);
     ExpectNotNull(file = fopen(altPrivFile, "rb"));
     ExpectIntGT(altPrivSz = (word32)fread(altPrivBuf, 1, altPrivSz, file), 0);
-    fclose(file);
+    if (file) {
+        fclose(file);
+        file = NULL;
+    }
     wc_ecc_init(&altCaKey);
     idx = 0;
     ExpectIntEQ(wc_EccPrivateKeyDecode(altPrivBuf, &idx, &altCaKey,
@@ -1052,6 +1074,7 @@ static int do_dual_alg_server_certgen(byte **out, char *caKeyFile,
     wc_FreeRsaKey(&caKey);
     wc_FreeRsaKey(&serverKey);
     wc_FreeRng(&rng);
+    wc_FreeDecodedCert(&preTBS);
     return outSz;
 }
 
@@ -1136,7 +1159,9 @@ static int test_dual_alg_support(void)
     /* Now we try a negative case. Note that we use wrongPrivFile to generate
      * the alternative signature and then set negative_test to true for the
      * call to do_dual_alg_tls13_connection(). Its expecting a failed connection
-     * because the signature won't verify. */
+     * because the signature won't verify. The exception is if
+     * WOLFSSL_TRUST_PEER_CERT is defined. In that case, no verfication happens
+     * and this is no longer a negative test. */
     rootSz = do_dual_alg_root_certgen(&root, keyFile, sapkiFile, wrongPrivFile);
     ExpectNotNull(root);
     ExpectIntGT(rootSz, 0);
@@ -1144,9 +1169,15 @@ static int test_dual_alg_support(void)
                                           wrongPrivFile, keyFile, root, rootSz);
     ExpectNotNull(server);
     ExpectIntGT(serverSz, 0);
+#ifdef WOLFSSL_TRUST_PEER_CERT
+    ExpectIntEQ(do_dual_alg_tls13_connection(root, rootSz,
+                server, serverSz, serverKey, (word32)serverKeySz, 0),
+                TEST_SUCCESS);
+#else
     ExpectIntEQ(do_dual_alg_tls13_connection(root, rootSz,
                 server, serverSz, serverKey, (word32)serverKeySz, 1),
                 TEST_SUCCESS);
+#endif
 
     /* Lets see if CertManager can find the new extensions */
     extCount = 0;

+ 158 - 11
wolfcrypt/src/asn.c

@@ -7770,17 +7770,59 @@ int wc_CheckPrivateKey(const byte* privKey, word32 privKeySz,
  * return 1 (true) on match
  * return 0 or negative value on failure/error
  *
- * key   : buffer holding DER format key
- * keySz : size of key buffer
- * der   : a initialized and parsed DecodedCert holding a certificate */
-int wc_CheckPrivateKeyCert(const byte* key, word32 keySz, DecodedCert* der)
+ * key      : buffer holding DER format key
+ * keySz    : size of key buffer
+ * der      : a initialized and parsed DecodedCert holding a certificate
+ * checkAlt : indicate if we check primary or alternative key
+ */
+int wc_CheckPrivateKeyCert(const byte* key, word32 keySz, DecodedCert* der,
+                           int checkAlt)
 {
+    int ret = 0;
+
     if (key == NULL || der == NULL) {
         return BAD_FUNC_ARG;
     }
 
-    return wc_CheckPrivateKey(key, keySz, der->publicKey,
-            der->pubKeySize, (enum Key_Sum) der->keyOID);
+#ifdef WOLFSSL_DUAL_ALG_CERTS
+    if (checkAlt && der->sapkiDer != NULL) {
+        /* We have to decode the public key first */
+        word32 idx = 0;
+        /* Dilithium has the largest public key at the moment */
+        word32 pubKeyLen = DILITHIUM_MAX_PUB_KEY_SIZE;
+        byte* decodedPubKey = (byte*)XMALLOC(pubKeyLen, NULL,
+                                             DYNAMIC_TYPE_PUBLIC_KEY);
+        if (decodedPubKey == NULL) {
+            ret = MEMORY_E;
+        }
+        if (ret == 0) {
+            if (der->sapkiOID == RSAk || der->sapkiOID == ECDSAk) {
+                /* Simply copy the data */
+                XMEMCPY(decodedPubKey, der->sapkiDer, der->sapkiLen);
+                pubKeyLen = der->sapkiLen;
+            }
+            else {
+                ret = DecodeAsymKeyPublic(der->sapkiDer, &idx, der->sapkiLen,
+                                          decodedPubKey, &pubKeyLen,
+                                          der->sapkiOID);
+            }
+        }
+        if (ret == 0) {
+            ret = wc_CheckPrivateKey(key, keySz, decodedPubKey, pubKeyLen,
+                                     (enum Key_Sum) der->sapkiOID);
+        }
+        XFREE(decodedPubKey, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
+    }
+    else
+#endif
+    {
+        ret = wc_CheckPrivateKey(key, keySz, der->publicKey,
+                der->pubKeySize, (enum Key_Sum) der->keyOID);
+    }
+
+    (void)checkAlt;
+
+    return ret;
 }
 
 #endif /* HAVE_PKCS12 || !NO_CHECK_PRIVATE_KEY */
@@ -15585,8 +15627,15 @@ int DecodeToKey(DecodedCert* cert, int verify)
     int ret;
     int badDate = 0;
 
+#ifdef WOLFSSL_DUAL_ALG_CERTS
+    /* Call internal version and decode completely to also handle extensions.
+     * This is required to parse a potential alternative public key in the
+     * SubjectAlternativeKey extension. */
+    ret = DecodeCertInternal(cert, verify, NULL, &badDate, 0, 0);
+#else
     /* Call internal version and stop after public key. */
     ret = DecodeCertInternal(cert, verify, NULL, &badDate, 0, 1);
+#endif
     /* Always return date errors. */
     if (ret == 0) {
         ret = badDate;
@@ -23753,6 +23802,45 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm)
                     WOLFSSL_ERROR_VERBOSE(ret);
                     return ret;
                 }
+
+            #ifdef WOLFSSL_DUAL_ALG_CERTS
+                if ((ret == 0) && cert->extAltSigAlgSet &&
+                    cert->extAltSigValSet) {
+                #ifndef WOLFSSL_SMALL_STACK
+                    byte der[MAX_CERT_VERIFY_SZ];
+                #else
+                    byte *der = (byte*)XMALLOC(MAX_CERT_VERIFY_SZ, ssl->heap,
+                                            DYNAMIC_TYPE_DCERT);
+                    if (der == NULL) {
+                        ret = MEMORY_E;
+                    } else
+                #endif /* ! WOLFSSL_SMALL_STACK */
+
+                    {
+                        ret = wc_GeneratePreTBS(cert, der, MAX_CERT_VERIFY_SZ);
+
+                        if (ret > 0) {
+                            ret = ConfirmSignature(&cert->sigCtx, der, ret,
+                                    cert->ca->sapkiDer, cert->ca->sapkiLen,
+                                    cert->ca->sapkiOID, cert->altSigValDer,
+                                    cert->altSigValLen, cert->altSigAlgOID,
+                                    NULL, 0, NULL);
+                        }
+                #ifdef WOLFSSL_SMALL_STACK
+                        XFREE(der, ssl->heap, DYNAMIC_TYPE_DCERT);
+                #endif /* WOLFSSL_SMALL_STACK */
+
+                        if (ret != 0) {
+                            WOLFSSL_MSG("Confirm alternative signature failed");
+                            WOLFSSL_ERROR_VERBOSE(ret);
+                            return ret;
+                        }
+                        else {
+                            WOLFSSL_MSG("Alt signature has been verified!");
+                        }
+                    }
+                }
+            #endif /* WOLFSSL_DUAL_ALG_CERTS */
             }
         #ifndef IGNORE_NAME_CONSTRAINTS
             if (verify == VERIFY || verify == VERIFY_OCSP ||
@@ -23852,6 +23940,9 @@ void FreeSigner(Signer* signer, void* heap)
     (void)heap;
     XFREE(signer->name, heap, DYNAMIC_TYPE_SUBJECT_CN);
     XFREE((void*)signer->publicKey, heap, DYNAMIC_TYPE_PUBLIC_KEY);
+#ifdef WOLFSSL_DUAL_ALG_CERTS
+    XFREE(signer->sapkiDer, heap, DYNAMIC_TYPE_PUBLIC_KEY);
+#endif
 #ifndef IGNORE_NAME_CONSTRAINTS
     if (signer->permittedNames)
         FreeNameSubtrees(signer->permittedNames, heap);
@@ -27591,6 +27682,17 @@ static int EncodeName(EncodedName* name, const char* nameStr,
         ret = BAD_FUNC_ARG;
     }
 
+#ifdef WOLFSSL_CUSTOM_OID
+    if (ret == 0 && type == ASN_CUSTOM_NAME) {
+        if (cname == NULL || cname->custom.oidSz == 0) {
+            name->used = 0;
+            return 0;
+        }
+    }
+#else
+    (void)cname;
+#endif
+
     CALLOC_ASNSETDATA(dataASN, rdnASN_Length, ret, NULL);
     if (ret == 0) {
         nameSz = (word32)XSTRLEN(nameStr);
@@ -28190,7 +28292,8 @@ int SetName(byte* output, word32 outputSz, CertName* name)
 static int EncodePublicKey(int keyType, byte* output, int outLen,
                            RsaKey* rsaKey, ecc_key* eccKey,
                            ed25519_key* ed25519Key, ed448_key* ed448Key,
-                           DsaKey* dsaKey)
+                           DsaKey* dsaKey, falcon_key* falconKey,
+                           dilithium_key* dilithiumKey, sphincs_key* sphincsKey)
 {
     int ret = 0;
 
@@ -28200,6 +28303,9 @@ static int EncodePublicKey(int keyType, byte* output, int outLen,
     (void)ed25519Key;
     (void)ed448Key;
     (void)dsaKey;
+    (void)falconKey;
+    (void)dilithiumKey;
+    (void)sphincsKey;
 
     switch (keyType) {
     #ifndef NO_RSA
@@ -28235,6 +28341,41 @@ static int EncodePublicKey(int keyType, byte* output, int outLen,
             }
             break;
     #endif
+    #if defined(HAVE_PQC) && defined(HAVE_FALCON)
+        case FALCON_LEVEL1_KEY:
+        case FALCON_LEVEL5_KEY:
+            ret = wc_Falcon_PublicKeyToDer(falconKey, output,
+                                           (word32)outLen, 1);
+            if (ret <= 0) {
+                ret = PUBLIC_KEY_E;
+            }
+            break;
+    #endif /* HAVE_PQC && HAVE_FALCON */
+    #if defined(HAVE_PQC) && defined(HAVE_DILITHIUM)
+        case DILITHIUM_LEVEL2_KEY:
+        case DILITHIUM_LEVEL3_KEY:
+        case DILITHIUM_LEVEL5_KEY:
+            ret = wc_Dilithium_PublicKeyToDer(dilithiumKey, output,
+                                              (word32)outLen, 1);
+            if (ret <= 0) {
+                ret = PUBLIC_KEY_E;
+            }
+            break;
+    #endif /* HAVE_PQC && HAVE_DILITHIUM */
+    #if defined(HAVE_PQC) && defined(HAVE_SPHINCS)
+        case SPHINCS_FAST_LEVEL1_KEY:
+        case SPHINCS_FAST_LEVEL3_KEY:
+        case SPHINCS_FAST_LEVEL5_KEY:
+        case SPHINCS_SMALL_LEVEL1_KEY:
+        case SPHINCS_SMALL_LEVEL3_KEY:
+        case SPHINCS_SMALL_LEVEL5_KEY:
+            ret = wc_Sphincs_PublicKeyToDer(sphincsKey, output,
+                                            (word32)outLen, 1);
+            if (ret <= 0) {
+                ret = PUBLIC_KEY_E;
+            }
+            break;
+    #endif /* HAVE_PQC && HAVE_SPHINCS */
         default:
             ret = PUBLIC_KEY_E;
             break;
@@ -30001,7 +30142,8 @@ static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz,
     if (ret >= 0) {
         /* Calculate public key encoding size. */
         ret = EncodePublicKey(cert->keyType, NULL, 0, rsaKey,
-            eccKey, ed25519Key, ed448Key, dsaKey);
+                eccKey, ed25519Key, ed448Key, dsaKey, falconKey,
+                dilithiumKey, sphincsKey);
         publicKeySz = (word32)ret;
     }
     if (ret >= 0) {
@@ -30181,7 +30323,8 @@ static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz,
                            .data.buffer.data,
             (int)dataASN[X509CERTASN_IDX_TBS_SPUBKEYINFO_SEQ]
                            .data.buffer.length,
-            rsaKey, eccKey, ed25519Key, ed448Key, dsaKey);
+            rsaKey, eccKey, ed25519Key, ed448Key, dsaKey,
+            falconKey, dilithiumKey, sphincsKey);
     }
     if ((ret >= 0) && (!dataASN[X509CERTASN_IDX_TBS_EXT_SEQ].noOut)) {
         /* Encode extensions into buffer. */
@@ -30262,6 +30405,7 @@ int wc_MakeCert(Cert* cert, byte* derBuffer, word32 derSz, RsaKey* rsaKey,
                        NULL, NULL, NULL, NULL);
 }
 
+
 #ifdef WOLFSSL_CERT_REQ
 
 #ifndef WOLFSSL_ASN_TEMPLATE
@@ -31048,7 +31192,8 @@ static int MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz,
     if (ret >= 0) {
         /* Determine encode public key size. */
          ret = EncodePublicKey(cert->keyType, NULL, 0, rsaKey,
-             eccKey, ed25519Key, ed448Key, dsaKey);
+             eccKey, ed25519Key, ed448Key, dsaKey, falconKey,
+             dilithiumKey, sphincsKey);
          publicKeySz = (word32)ret;
     }
     if (ret >= 0) {
@@ -31162,7 +31307,8 @@ static int MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz,
         ret = EncodePublicKey(cert->keyType,
             (byte*)dataASN[CERTREQBODYASN_IDX_SPUBKEYINFO_SEQ].data.buffer.data,
             (int)dataASN[CERTREQBODYASN_IDX_SPUBKEYINFO_SEQ].data.buffer.length,
-            rsaKey, eccKey, ed25519Key, ed448Key, dsaKey);
+            rsaKey, eccKey, ed25519Key, ed448Key, dsaKey, falconKey,
+            dilithiumKey, sphincsKey);
     }
     if ((ret >= 0 && derBuffer != NULL) &&
             (!dataASN[CERTREQBODYASN_IDX_EXT_BODY].noOut)) {
@@ -31486,6 +31632,7 @@ int wc_SignCert(int requestSz, int sType, byte* buf, word32 buffSz,
                     NULL, NULL, NULL, rng);
 }
 
+
 WOLFSSL_ABI
 int wc_MakeSelfCert(Cert* cert, byte* buf, word32 buffSz,
                     RsaKey* key, WC_RNG* rng)

+ 5 - 5
wolfcrypt/src/dilithium.c

@@ -395,7 +395,7 @@ int wc_dilithium_export_public(dilithium_key* key,
         return BAD_FUNC_ARG;
     }
 
-    if ((key->level != 1) && (key->level != 5)) {
+    if ((key->level != 2) && (key->level != 3) && (key->level != 5)) {
         return BAD_FUNC_ARG;
     }
 
@@ -914,11 +914,11 @@ int wc_Dilithium_PrivateKeyDecode(const byte* input, word32* inOutIdx,
                         pubKey, &pubKeyLen, keytype);
     if (ret == 0) {
         if (pubKeyLen == 0) {
-            ret = wc_dilithium_import_private_only(input, inSz, key);
+            ret = wc_dilithium_import_private_key(input, inSz, NULL, 0, key);
         }
         else {
-            ret = wc_dilithium_import_private_key(privKey, privKeyLen,
-                                               pubKey, pubKeyLen, key);
+            ret = wc_dilithium_import_private_key(input, inSz, pubKey,
+                                                  pubKeyLen, key);
         }
     }
     return ret;
@@ -983,7 +983,7 @@ int wc_Dilithium_PublicKeyToDer(dilithium_key* key, byte* output, word32 inLen,
     word32 pubKeyLen = (word32)sizeof(pubKey);
     int    keytype = 0;
 
-    if (key == NULL || output == NULL) {
+    if (key == NULL) {
         return BAD_FUNC_ARG;
     }
 

+ 4 - 4
wolfcrypt/src/falcon.c

@@ -846,11 +846,11 @@ int wc_Falcon_PrivateKeyDecode(const byte* input, word32* inOutIdx,
                         pubKey, &pubKeyLen, keytype);
     if (ret == 0) {
         if (pubKeyLen == 0) {
-            ret = wc_falcon_import_private_only(input, inSz, key);
+            ret = wc_falcon_import_private_key(input, inSz, NULL, 0, key);
         }
         else {
-            ret = wc_falcon_import_private_key(privKey, privKeyLen,
-                                               pubKey, pubKeyLen, key);
+            ret = wc_falcon_import_private_key(input, inSz, pubKey,
+                                               pubKeyLen, key);
         }
     }
     return ret;
@@ -912,7 +912,7 @@ int wc_Falcon_PublicKeyToDer(falcon_key* key, byte* output, word32 inLen,
     word32 pubKeyLen = (word32)sizeof(pubKey);
     int    keytype = 0;
 
-    if (key == NULL || output == NULL) {
+    if (key == NULL) {
         return BAD_FUNC_ARG;
     }
 

+ 1 - 1
wolfcrypt/src/pkcs12.c

@@ -1120,7 +1120,7 @@ static WARN_UNUSED_RESULT int freeDecCertList(WC_DerCertList** list,
 
         InitDecodedCert(DeCert, current->buffer, current->bufferSz, heap);
         if (ParseCertRelative(DeCert, CERT_TYPE, NO_VERIFY, NULL) == 0) {
-            if (wc_CheckPrivateKeyCert(*pkey, *pkeySz, DeCert) == 1) {
+            if (wc_CheckPrivateKeyCert(*pkey, *pkeySz, DeCert, 0) == 1) {
                 WOLFSSL_MSG("Key Pair found");
                 *cert = current->buffer;
                 *certSz = current->bufferSz;

+ 1 - 1
wolfcrypt/src/sphincs.c

@@ -952,7 +952,7 @@ int wc_Sphincs_PublicKeyToDer(sphincs_key* key, byte* output, word32 inLen,
     word32 pubKeyLen = (word32)sizeof(pubKey);
     int    keytype = 0;
 
-    if (key == NULL || output == NULL) {
+    if (key == NULL) {
         return BAD_FUNC_ARG;
     }
 

+ 12 - 6
wolfssl/internal.h

@@ -1915,10 +1915,10 @@ enum Misc {
 
 #ifdef HAVE_PQC
 #ifndef MIN_FALCONKEY_SZ
-    #define MIN_FALCONKEY_SZ    897
+    #define MIN_FALCONKEY_SZ    1281
 #endif
 #ifndef MIN_DILITHIUMKEY_SZ
-    #define MIN_DILITHIUMKEY_SZ    1312
+    #define MIN_DILITHIUMKEY_SZ    2528
 #endif
 #endif
 
@@ -3585,8 +3585,11 @@ struct WOLFSSL_CTX {
 
 #ifdef WOLFSSL_DUAL_ALG_CERTS
     DerBuffer*  altPrivateKey;
-    byte        altPrivateKeyType;
+    byte        altPrivateKeyType:6;
+    byte        altPrivateKeyId:1;
+    byte        altPrivateKeyLabel:1;
     int         altPrivateKeySz;
+    int         altPrivateKeyDevId;
 #endif /* WOLFSSL_DUAL_ALG_CERTS */
 #ifdef OPENSSL_ALL
     WOLFSSL_EVP_PKEY* privateKeyPKey;
@@ -4550,15 +4553,18 @@ typedef struct Buffers {
 #ifndef NO_CERTS
     DerBuffer*      certificate;           /* WOLFSSL_CTX owns, unless we own */
     DerBuffer*      key;                   /* WOLFSSL_CTX owns, unless we own */
-    byte            keyType:6;             /* Type of key: RSA, ECC, Ed25519 */
+    byte            keyType:6;             /* Type of key */
     byte            keyId:1;               /* Key data is an id not data */
     byte            keyLabel:1;            /* Key data is a label not data */
     int             keySz;                 /* Size of RSA key */
     int             keyDevId;              /* Device Id for key */
 #ifdef WOLFSSL_DUAL_ALG_CERTS
     DerBuffer*      altKey;                /* WOLFSSL_CTX owns, unless we own */
-    byte            altKeyType;            /* Type of key: dilithium, falcon */
-    int             altKeySz;              /* Size of key */
+    byte            altKeyType:6;          /* Type of alt key */
+    byte            altKeyId:1;            /* Key data is an id not data */
+    byte            altKeyLabel:1;         /* Key data is a label not data */
+    int             altKeySz;              /* Size of alt key */
+    int             altKeyDevId;           /* Device Id for alt key */
 #endif
     DerBuffer*      certChain;             /* WOLFSSL_CTX owns, unless we own */
                  /* chain after self, in DER, with leading size for each cert */

+ 22 - 0
wolfssl/ssl.h

@@ -3096,6 +3096,17 @@ WOLFSSL_API int wolfSSL_make_eap_keys(WOLFSSL* ssl, void* key, unsigned int len,
                                                const unsigned char* in, long sz, int format);
     WOLFSSL_API int wolfSSL_CTX_use_certificate_chain_buffer(WOLFSSL_CTX* ctx,
                                                     const unsigned char* in, long sz);
+#ifdef WOLFSSL_DUAL_ALG_CERTS
+    WOLFSSL_API int wolfSSL_CTX_use_AltPrivateKey_buffer(WOLFSSL_CTX* ctx,
+                                const unsigned char* in, long sz, int format);
+    WOLFSSL_API int wolfSSL_CTX_use_AltPrivateKey_id(WOLFSSL_CTX* ctx,
+                                const unsigned char* id, long sz,
+                                int devId, long keySz);
+    WOLFSSL_API int wolfSSL_CTX_use_AltPrivateKey_Id(WOLFSSL_CTX* ctx,
+                                const unsigned char* id, long sz, int devId);
+    WOLFSSL_API int wolfSSL_CTX_use_AltPrivateKey_Label(WOLFSSL_CTX* ctx,
+                                const char* label, int devId);
+#endif
 
     /* SSL versions */
     WOLFSSL_API int wolfSSL_use_certificate_buffer(WOLFSSL* ssl, const unsigned char* in,
@@ -3114,6 +3125,17 @@ WOLFSSL_API int wolfSSL_make_eap_keys(WOLFSSL* ssl, void* key, unsigned int len,
     WOLFSSL_API int wolfSSL_use_certificate_chain_buffer(WOLFSSL* ssl,
                                                const unsigned char* in, long sz);
     WOLFSSL_API int wolfSSL_UnloadCertsKeys(WOLFSSL* ssl);
+#ifdef WOLFSSL_DUAL_ALG_CERTS
+    WOLFSSL_API int wolfSSL_use_AltPrivateKey_buffer(WOLFSSL* ssl,
+                                const unsigned char* in, long sz, int format);
+    WOLFSSL_API int wolfSSL_use_AltPrivateKey_id(WOLFSSL* ssl,
+                                const unsigned char* id, long sz,
+                                int devId, long keySz);
+    WOLFSSL_API int wolfSSL_use_AltPrivateKey_Id(WOLFSSL* ssl,
+                                const unsigned char* id, long sz, int devId);
+    WOLFSSL_API int wolfSSL_use_AltPrivateKey_Label(WOLFSSL* ssl,
+                                const char* label, int devId);
+#endif
 
     #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
         defined(KEEP_OUR_CERT)

+ 12 - 5
wolfssl/wolfcrypt/asn.h

@@ -969,6 +969,9 @@ enum Misc_ASN {
     MAX_DSA_PRIVKEY_SZ  = (DSA_INTS * MAX_DSA_INT_SZ) + MAX_SEQ_SZ +
                           MAX_VERSION_SZ, /* Maximum size of a DSA Private
                                       key taken from DsaKeyIntsToDer. */
+#if defined(HAVE_PQC)
+    MAX_PQC_PUBLIC_KEY_SZ = 2592, /* Maximum size of a Dilithium public key. */
+#endif
     MAX_RSA_E_SZ        =  16,     /* Max RSA public e size */
     MAX_CA_SZ           =  32,     /* Max encoded CA basic constraint length */
     MAX_SN_SZ           =  35,     /* Max encoded serial number (INT) length */
@@ -1015,7 +1018,11 @@ enum Misc_ASN {
     OCSP_NONCE_EXT_SZ   = 35,      /* OCSP Nonce Extension size */
     MAX_OCSP_EXT_SZ     = 58,      /* Max OCSP Extension length */
     MAX_OCSP_NONCE_SZ   = 16,      /* OCSP Nonce size           */
+#if defined(HAVE_PQC)
+    MAX_PUBLIC_KEY_SZ   = MAX_PQC_PUBLIC_KEY_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ * 2,
+#else
     MAX_PUBLIC_KEY_SZ   = MAX_DSA_PUBKEY_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ * 2,
+#endif
 #ifdef WOLFSSL_ENCRYPTED_KEYS
     HEADER_ENCRYPTED_KEY_SIZE = 88,/* Extra header size for encrypted key */
 #else
@@ -2017,10 +2024,9 @@ struct Signer {
     word32 cm_idx;
 #endif
 #ifdef WOLFSSL_DUAL_ALG_CERTS
-    /* The Subject Alternative Public Key Info (SAPKI) will NOT be cached.
-     * Caching of it is NOT SUPPORTED yet. */
-    byte *sapkiDer;
-    int sapkiLen;
+    word32  sapkiOID; /* key type */
+    byte*   sapkiDer;
+    int     sapkiLen;
 #endif /* WOLFSSL_DUAL_ALG_CERTS */
     byte type;
 
@@ -2308,7 +2314,8 @@ WOLFSSL_LOCAL int GetNameHash(const byte* source, word32* idx, byte* hash,
                               int maxIdx);
 WOLFSSL_LOCAL int GetNameHash_ex(const byte* source, word32* idx, byte* hash,
                                  int maxIdx, word32 sigOID);
-WOLFSSL_LOCAL int wc_CheckPrivateKeyCert(const byte* key, word32 keySz, DecodedCert* der);
+WOLFSSL_LOCAL int wc_CheckPrivateKeyCert(const byte* key, word32 keySz,
+                                         DecodedCert* der, int checkAlt);
 WOLFSSL_LOCAL int wc_CheckPrivateKey(const byte* privKey, word32 privKeySz,
                                      const byte* pubKey, word32 pubKeySz, enum Key_Sum ks);
 WOLFSSL_LOCAL int StoreDHparams(byte* out, word32* outLen, mp_int* p, mp_int* g);

+ 1 - 0
wolfssl/wolfcrypt/settings.h

@@ -2008,6 +2008,7 @@ extern void uITRON4_free(void *p) ;
     #define WOLFSSL_DH_CONST
     #define WOLFSSL_HAVE_MAX
     #define NO_WRITEV
+    #define NO_STDLIB_ISASCII
 
     #define USE_FLAT_BENCHMARK_H
     #define USE_FLAT_TEST_H

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini