Adding support for dual key/signature certificates. (#7112)

Adding support for dual key/signature certificates with X9.146. Enabled with `--enable-dual-alg-certs` or `WOLFSSL_DUAL_ALG_CERTS`.
This commit is contained in:
Anthony Hu
2024-01-18 16:20:57 -05:00
committed by GitHub
parent 8a45f43eb0
commit 9be390250d
19 changed files with 2262 additions and 125 deletions

View File

@@ -8097,6 +8097,12 @@ AC_ARG_ENABLE([sys-ca-certs],
[ ENABLED_SYS_CA_CERTS=yes ]
)
AC_ARG_ENABLE([dual-alg-certs],
[AS_HELP_STRING([--enable-dual-alg-certs],[Enable support for dual key/signature certificates in TLS 1.3 as defined in X9.146 (default: disabled)])],
[ ENABLED_DUAL_ALG_CERTS=$enableval ],
[ ENABLED_DUAL_ALG_CERTS=no ]
)
# check if should run the trusted peer certs test
# (for now checking both C_FLAGS and C_EXTRA_FLAGS)
AS_CASE(["$CFLAGS $CPPFLAGS"],[*'WOLFSSL_TRUST_PEER_CERT'*],[ENABLED_TRUSTED_PEER_CERT=yes])
@@ -8462,6 +8468,9 @@ AS_IF([test "x$ENABLED_ASN" = "xno"],
AS_IF([test "x$ENABLED_SYS_CA_CERTS" = "xyes"],
[AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SYS_CA_CERTS"])
AS_IF([test "x$ENABLED_DUAL_ALG_CERTS" = "xyes"],
[AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DUAL_ALG_CERTS"])
AS_IF([test "x$ENABLED_ALTNAMES" = "xyes"],
[AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ALT_NAMES"])
@@ -9579,6 +9588,7 @@ echo " * NXP SE050: $ENABLED_SE050"
echo " * Maxim Integrated MAXQ10XX: $ENABLED_MAXQ10XX"
echo " * PSA: $ENABLED_PSA"
echo " * System CA certs: $ENABLED_SYS_CA_CERTS"
echo " * Dual alg cert support: $ENABLED_DUAL_ALG_CERTS"
echo " * ERR Queues per Thread: $ENABLED_ERRORQUEUEPERTHREAD"
echo " * rwlock: $ENABLED_RWLOCK"
echo " * keylog export: $ENABLED_KEYLOG_EXPORT"

View File

@@ -3558,6 +3558,24 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
err_sys("unable to get SSL object");
}
#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.");
}
}
#endif /* WOLFSSL_DUAL_ALG_CERTS */
#ifndef NO_PSK
if (usePsk) {
#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_TLS13) && defined(TEST_PSK_USE_SESSION)

View File

@@ -969,11 +969,15 @@ static const char* server_usage_msg[][65] = {
#endif
#ifdef HAVE_SUPPORTED_CURVES
"--onlyPskDheKe Must use DHE key exchange with PSK\n", /* 64 */
#endif
#ifdef WOLFSSL_DUAL_ALG_CERTS
"--altPrivKey <file> Generate alternative signature with this key.\n",
/* 65 */
#endif
"\n"
"For simpler wolfSSL TLS server examples, visit\n"
"https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n",
/* 65 */
/* 66 */
NULL,
},
#ifndef NO_MULTIBYTE_PRINT
@@ -1159,11 +1163,16 @@ static const char* server_usage_msg[][65] = {
#endif
#ifdef HAVE_SUPPORTED_CURVES
"--onlyPskDheKe Must use DHE key exchange with PSK\n", /* 64 */
#endif
#ifdef WOLFSSL_DUAL_ALG_CERTS
"--altPrivKey <file> Generate alternative signature with this key.\n",
/* 65 */
#endif
"\n"
"より簡単なwolfSSL TSL クライアントの例については"
"下記にアクセスしてください\n"
"https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 65 */
"https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n",
/* 66 */
NULL,
},
#endif
@@ -1320,7 +1329,10 @@ static void Usage(void)
#ifdef HAVE_SUPPORTED_CURVES
printf("%s", msg[++msgId]); /* --onlyPskDheKe */
#endif
printf("%s", msg[++msgId]); /* Examples repo link */
#ifdef WOLFSSL_DUAL_ALG_CERTS
printf("%s", msg[++msgId]); /* --altPrivKey */
#endif
printf("%s", msg[++msgId]); /* Examples repo link */
}
#ifdef WOLFSSL_SRTP
@@ -1436,6 +1448,9 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
{"crl-dir", 1, 265},
#endif
{"quieter", 0, 266},
#ifdef WOLFSSL_DUAL_ALG_CERTS
{ "altPrivKey", 1, 267},
#endif
{ 0, 0, 0 }
};
#endif
@@ -1600,6 +1615,7 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
int useX448 = 0;
int usePqc = 0;
char* pqcAlg = NULL;
char* altPrivKey = NULL;
int exitWithRet = 0;
int loadCertKeyIntoSSLObj = 0;
@@ -1674,6 +1690,7 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
(void)nonBlocking;
(void)pqcAlg;
(void)usePqc;
(void)altPrivKey;
#ifdef WOLFSSL_TIRTOS
fdOpenSession(Task_self());
@@ -2320,6 +2337,12 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
quieter = 1;
break;
#ifdef WOLFSSL_DUAL_ALG_CERTS
case 267:
altPrivKey = myoptarg;
break;
#endif
case -1:
default:
Usage();
@@ -2697,6 +2720,14 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
!= WOLFSSL_SUCCESS)
err_sys_ex(catastrophic, "can't load server private key file, "
"check file and run from wolfSSL home dir");
#ifdef WOLFSSL_DUAL_ALG_CERTS
if ((altPrivKey != NULL) &&
wolfSSL_CTX_use_AltPrivateKey_file(ctx, altPrivKey,
WOLFSSL_FILETYPE_PEM)
!= WOLFSSL_SUCCESS)
err_sys_ex(catastrophic, "can't load alt private key file, "
"check file and run from wolfSSL home dir");
#endif /* WOLFSSL_DUAL_ALG_CERTS */
#else
/* loads private key file using buffer API */
load_buffer(ctx, ourKey, WOLFSSL_KEY);

View File

@@ -2585,6 +2585,12 @@ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx)
ForceZero(ctx->privateKey->buffer, ctx->privateKey->length);
}
FreeDer(&ctx->privateKey);
#ifdef WOLFSSL_DUAL_ALG_CERTS
if (ctx->altPrivateKey != NULL && ctx->altPrivateKey->buffer != NULL) {
ForceZero(ctx->altPrivateKey->buffer, ctx->altPrivateKey->length);
}
FreeDer(&ctx->altPrivateKey);
#endif /* WOLFSSL_DUAL_ALG_CERTS */
#ifdef OPENSSL_ALL
wolfSSL_EVP_PKEY_free(ctx->privateKeyPKey);
#endif
@@ -4575,6 +4581,12 @@ void FreeX509(WOLFSSL_X509* x509)
x509->altNames = NULL;
}
#ifdef WOLFSSL_DUAL_ALG_CERTS
XFREE(x509->sapkiDer, x509->heap, DYNAMIC_TYPE_X509_EXT);
XFREE(x509->altSigAlgDer, x509->heap, DYNAMIC_TYPE_X509_EXT);
XFREE(x509->altSigValDer, x509->heap, DYNAMIC_TYPE_X509_EXT);
#endif /* WOLFSSL_DUAL_ALG_CERTS */
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
wolfSSL_RefFree(&x509->ref);
#endif
@@ -6748,6 +6760,11 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
ssl->buffers.keyLabel = ctx->privateKeyLabel;
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;
#endif /* WOLFSSL_DUAL_ALG_CERTS */
#endif
#if !defined(WOLFSSL_NO_CLIENT_AUTH) && \
((defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)) || \
@@ -7553,7 +7570,10 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
defined(WOLFSSL_SSLKEYLOGFILE) && defined(WOLFSSL_TLS13)
(void)wolfSSL_set_tls13_secret_cb(ssl, tls13ShowSecrets, NULL);
#endif
#ifdef WOLFSSL_DUAL_ALG_CERTS
ssl->sigSpec = ctx->sigSpec;
ssl->sigSpecSz = ctx->sigSpecSz;
#endif /* WOLFSSL_DUAL_ALG_CERTS */
return 0;
}
@@ -7934,6 +7954,9 @@ void FreeKeyExchange(WOLFSSL* ssl)
/* Free handshake key */
FreeKey(ssl, ssl->hsType, &ssl->hsKey);
#ifdef WOLFSSL_DUAL_ALG_CERTS
FreeKey(ssl, ssl->hsAltType, &ssl->hsAltKey);
#endif /* WOLFSSL_DUAL_ALG_CERTS */
#ifndef NO_DH
/* Free temp DH key */
@@ -8302,6 +8325,9 @@ void SSL_ResourceFree(WOLFSSL* ssl)
wolfSSL_CTX_free(ssl->initial_ctx);
ssl->initial_ctx = NULL;
#endif
#ifdef WOLFSSL_DUAL_ALG_CERTS
XFREE(ssl->peerSigSpec, ssl->heap, DYNAMIC_TYPE_TLSX);
#endif
}
/* Free any handshake resources no longer needed */
@@ -12935,6 +12961,30 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert)
x509->pkCurveOID = dCert->pkCurveOID;
#endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */
#ifdef WOLFSSL_DUAL_ALG_CERTS
/* 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,
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;
}
else {
ret = MEMORY_E;
}
#endif /* WOLFSSL_DUAL_ALG_CERTS */
return ret;
}
@@ -13881,6 +13931,39 @@ 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)
@@ -27785,6 +27868,10 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length)
#endif /* HAVE_ED448 && HAVE_ED448_KEY_IMPORT */
#if defined(HAVE_PQC)
#if defined(HAVE_FALCON)
#if !defined(NO_RSA) || defined(HAVE_ECC)
FreeKey(ssl, ssl->hsType, (void**)&ssl->hsKey);
#endif
if (ssl->buffers.keyType == falcon_level1_sa_algo ||
ssl->buffers.keyType == falcon_level5_sa_algo ||
ssl->buffers.keyType == 0) {
@@ -27846,6 +27933,10 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length)
}
#endif /* HAVE_FALCON */
#if defined(HAVE_DILITHIUM)
#if !defined(NO_RSA) || defined(HAVE_ECC)
FreeKey(ssl, ssl->hsType, (void**)&ssl->hsKey);
#endif
if (ssl->buffers.keyType == dilithium_level2_sa_algo ||
ssl->buffers.keyType == dilithium_level3_sa_algo ||
ssl->buffers.keyType == dilithium_level5_sa_algo ||
@@ -27926,6 +28017,119 @@ 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. */
int DecodeAltPrivateKey(WOLFSSL *ssl, word16* length)
{
int ret = BAD_FUNC_ARG;
/* make sure alt private key exists */
if (ssl->buffers.altKey == NULL || ssl->buffers.altKey->buffer == NULL) {
WOLFSSL_MSG("Alternative Private key missing!");
ERROR_OUT(NO_PRIVATE_KEY, exit_dapk);
}
if (ssl->buffers.altKeyType == falcon_level1_sa_algo ||
ssl->buffers.altKeyType == falcon_level5_sa_algo) {
ssl->hsAltType = DYNAMIC_TYPE_FALCON;
ret = AllocKey(ssl, ssl->hsAltType, &ssl->hsAltKey);
if (ret != 0) {
goto exit_dapk;
}
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);
}
else {
ret = ALGO_ID_E;
}
if (ret != 0) {
goto exit_dapk;
}
WOLFSSL_MSG("Trying Falcon private key");
/* Decode the key assuming it is a Falcon private key. */
ret = wc_falcon_import_private_only(ssl->buffers.altKey->buffer,
ssl->buffers.altKey->length,
(falcon_key*)ssl->hsAltKey);
if (ret == 0) {
WOLFSSL_MSG("Using Falcon private key");
/* Check it meets the minimum Falcon key size requirements. */
if (FALCON_MAX_KEY_SIZE < ssl->options.minFalconKeySz) {
WOLFSSL_MSG("Falcon key size too small");
ERROR_OUT(FALCON_KEY_SIZE_E, exit_dapk);
}
*length = wc_falcon_sig_size((falcon_key*)ssl->hsAltKey);
goto exit_dapk;
}
}
FreeKey(ssl, ssl->hsAltType, (void**)&ssl->hsAltKey);
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 == 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);
}
else {
ret = ALGO_ID_E;
}
if (ret != 0) {
goto exit_dapk;
}
WOLFSSL_MSG("Trying Dilithium private key");
/* Decode the key assuming it is a Dilithium private key. */
ret = wc_dilithium_import_private_only(ssl->buffers.altKey->buffer,
ssl->buffers.altKey->length,
(dilithium_key*)ssl->hsAltKey);
if (ret == 0) {
WOLFSSL_MSG("Using Dilithium private key");
/* Check it meets the minimum Dilithium key size requirements. */
if (DILITHIUM_MAX_KEY_SIZE < ssl->options.minDilithiumKeySz) {
WOLFSSL_MSG("Dilithium key size too small");
ERROR_OUT(DILITHIUM_KEY_SIZE_E, exit_dapk);
}
*length = wc_dilithium_sig_size((dilithium_key*)ssl->hsAltKey);
goto exit_dapk;
}
}
exit_dapk:
if (ret != 0) {
WOLFSSL_ERROR_VERBOSE(ret);
}
return ret;
}
#endif /* HAVE_PQC && WOLFSSL_DUAL_ALG_CERTS */
#endif /* WOLFSSL_TLS13 || !NO_WOLFSSL_CLIENT */
#if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_NO_TLS12)

204
src/ssl.c
View File

@@ -5879,6 +5879,12 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify)
signer->publicKey = cert->publicKey;
signer->pubKeySize = cert->pubKeySize;
}
#ifdef WOLFSSL_DUAL_ALG_CERTS
signer->sapkiDer = cert->sapkiDer;
signer->sapkiLen = cert->sapkiLen;
#endif /* WOLFSSL_DUAL_ALG_CERTS */
if (cert->subjectCNStored) {
signer->nameLen = cert->subjectCNLen;
signer->name = cert->subjectCN;
@@ -6851,12 +6857,13 @@ static int ProcessBufferTryDecodeEd448(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
#if defined(HAVE_FALCON)
static int ProcessBufferTryDecodeFalcon(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
DerBuffer* der, int* keySz, word32* idx, int* resetSuites, int* keyFormat,
void* heap)
void* heap, int type)
{
int ret;
/* make sure Falcon key can be used */
falcon_key* key = (falcon_key*)XMALLOC(sizeof(falcon_key), heap,
DYNAMIC_TYPE_FALCON);
(void) type;
if (key == NULL) {
return MEMORY_E;
}
@@ -6889,22 +6896,50 @@ static int ProcessBufferTryDecodeFalcon(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
ret = FALCON_KEY_SIZE_E;
}
if (ssl) {
if (*keyFormat == FALCON_LEVEL1k) {
ssl->buffers.keyType = falcon_level1_sa_algo;
#ifdef WOLFSSL_DUAL_ALG_CERTS
if (type == ALT_PRIVATEKEY_TYPE) {
if (*keyFormat == FALCON_LEVEL1k) {
ssl->buffers.altKeyType = falcon_level1_sa_algo;
}
else {
ssl->buffers.altKeyType = falcon_level5_sa_algo;
}
ssl->buffers.altKeySz = *keySz;
}
else {
ssl->buffers.keyType = falcon_level5_sa_algo;
else
#endif /* WOLFSSL_DUAL_ALG_CERTS */
{
if (*keyFormat == FALCON_LEVEL1k) {
ssl->buffers.keyType = falcon_level1_sa_algo;
}
else {
ssl->buffers.keyType = falcon_level5_sa_algo;
}
ssl->buffers.keySz = *keySz;
}
ssl->buffers.keySz = *keySz;
}
else {
if (*keyFormat == FALCON_LEVEL1k) {
ctx->privateKeyType = falcon_level1_sa_algo;
#ifdef WOLFSSL_DUAL_ALG_CERTS
if (type == ALT_PRIVATEKEY_TYPE) {
if (*keyFormat == FALCON_LEVEL1k) {
ctx->altPrivateKeyType = falcon_level1_sa_algo;
}
else {
ctx->altPrivateKeyType = falcon_level5_sa_algo;
}
ctx->altPrivateKeySz = *keySz;
}
else {
ctx->privateKeyType = falcon_level5_sa_algo;
else
#endif /* WOLFSSL_DUAL_ALG_CERTS */
{
if (*keyFormat == FALCON_LEVEL1k) {
ctx->privateKeyType = falcon_level1_sa_algo;
}
else {
ctx->privateKeyType = falcon_level5_sa_algo;
}
ctx->privateKeySz = *keySz;
}
ctx->privateKeySz = *keySz;
}
if (ssl && ssl->options.side == WOLFSSL_SERVER_END) {
@@ -6921,12 +6956,13 @@ static int ProcessBufferTryDecodeFalcon(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
#if defined(HAVE_DILITHIUM)
static int ProcessBufferTryDecodeDilithium(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
DerBuffer* der, int* keySz, word32* idx, int* resetSuites, int* keyFormat,
void* heap)
void* heap, int type)
{
int ret;
/* make sure Dilithium key can be used */
dilithium_key* key = (dilithium_key*)XMALLOC(sizeof(dilithium_key), heap,
DYNAMIC_TYPE_DILITHIUM);
(void) type;
if (key == NULL) {
return MEMORY_E;
}
@@ -6962,28 +6998,62 @@ static int ProcessBufferTryDecodeDilithium(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
ret = DILITHIUM_KEY_SIZE_E;
}
if (ssl) {
if (*keyFormat == DILITHIUM_LEVEL2k) {
ssl->buffers.keyType = dilithium_level2_sa_algo;
#ifdef WOLFSSL_DUAL_ALG_CERTS
if (type == ALT_PRIVATEKEY_TYPE) {
if (*keyFormat == DILITHIUM_LEVEL2k) {
ssl->buffers.altKeyType = dilithium_level2_sa_algo;
}
else if (*keyFormat == DILITHIUM_LEVEL3k) {
ssl->buffers.altKeyType = dilithium_level3_sa_algo;
}
else if (*keyFormat == DILITHIUM_LEVEL5k) {
ssl->buffers.altKeyType = dilithium_level5_sa_algo;
}
ssl->buffers.altKeySz = *keySz;
}
else if (*keyFormat == DILITHIUM_LEVEL3k) {
ssl->buffers.keyType = dilithium_level3_sa_algo;
else
#endif /* WOLFSSL_DUAL_ALG_CERTS */
{
if (*keyFormat == DILITHIUM_LEVEL2k) {
ssl->buffers.keyType = dilithium_level2_sa_algo;
}
else if (*keyFormat == DILITHIUM_LEVEL3k) {
ssl->buffers.keyType = dilithium_level3_sa_algo;
}
else if (*keyFormat == DILITHIUM_LEVEL5k) {
ssl->buffers.keyType = dilithium_level5_sa_algo;
}
ssl->buffers.keySz = *keySz;
}
else if (*keyFormat == DILITHIUM_LEVEL5k) {
ssl->buffers.keyType = dilithium_level5_sa_algo;
}
ssl->buffers.keySz = *keySz;
}
else {
if (*keyFormat == DILITHIUM_LEVEL2k) {
ctx->privateKeyType = dilithium_level2_sa_algo;
#ifdef WOLFSSL_DUAL_ALG_CERTS
if (type == ALT_PRIVATEKEY_TYPE) {
if (*keyFormat == DILITHIUM_LEVEL2k) {
ctx->altPrivateKeyType = dilithium_level2_sa_algo;
}
else if (*keyFormat == DILITHIUM_LEVEL3k) {
ctx->altPrivateKeyType = dilithium_level3_sa_algo;
}
else if (*keyFormat == DILITHIUM_LEVEL5k) {
ctx->altPrivateKeyType = dilithium_level5_sa_algo;
}
ctx->altPrivateKeySz = *keySz;
}
else if (*keyFormat == DILITHIUM_LEVEL3k) {
ctx->privateKeyType = dilithium_level3_sa_algo;
else
#endif /* WOLFSSL_DUAL_ALG_CERTS */
{
if (*keyFormat == DILITHIUM_LEVEL2k) {
ctx->privateKeyType = dilithium_level2_sa_algo;
}
else if (*keyFormat == DILITHIUM_LEVEL3k) {
ctx->privateKeyType = dilithium_level3_sa_algo;
}
else if (*keyFormat == DILITHIUM_LEVEL5k) {
ctx->privateKeyType = dilithium_level5_sa_algo;
}
ctx->privateKeySz = *keySz;
}
else if (*keyFormat == DILITHIUM_LEVEL5k) {
ctx->privateKeyType = dilithium_level5_sa_algo;
}
ctx->privateKeySz = *keySz;
}
if (ssl && ssl->options.side == WOLFSSL_SERVER_END) {
@@ -7001,12 +7071,13 @@ static int ProcessBufferTryDecodeDilithium(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
DerBuffer* der, int* keySz, word32* idx, int* resetSuites, int* keyFormat,
void* heap, int devId)
void* heap, int devId, int type)
{
int ret = 0;
(void)heap;
(void)devId;
(void)type;
if (ctx == NULL && ssl == NULL)
return BAD_FUNC_ARG;
@@ -7060,7 +7131,7 @@ static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
if (((*keyFormat == 0) || (*keyFormat == FALCON_LEVEL1k) ||
(*keyFormat == FALCON_LEVEL5k))) {
ret = ProcessBufferTryDecodeFalcon(ctx, ssl, der, keySz, idx,
resetSuites, keyFormat, heap);
resetSuites, keyFormat, heap, type);
if (ret != 0)
return ret;
}
@@ -7071,7 +7142,7 @@ static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
(*keyFormat == DILITHIUM_LEVEL3k) ||
(*keyFormat == DILITHIUM_LEVEL5k)) {
ret = ProcessBufferTryDecodeDilithium(ctx, ssl, der, keySz, idx,
resetSuites, keyFormat, heap);
resetSuites, keyFormat, heap, type);
if (ret != 0) {
return ret;
}
@@ -7304,6 +7375,35 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
#endif
}
}
#ifdef WOLFSSL_DUAL_ALG_CERTS
else if (type == ALT_PRIVATEKEY_TYPE) {
if (ssl != NULL) {
/* Make sure previous is free'd */
if (ssl->buffers.weOwnAltKey) {
ForceZero(ssl->buffers.altKey->buffer,
ssl->buffers.altKey->length);
FreeDer(&ssl->buffers.altKey);
}
ssl->buffers.altKey = der;
#ifdef WOLFSSL_CHECK_MEM_ZERO
wc_MemZero_Add("SSL Buffers key", der->buffer, der->length);
#endif
ssl->buffers.weOwnAltKey = 1;
}
else if (ctx != NULL) {
if (ctx->altPrivateKey != NULL &&
ctx->altPrivateKey->buffer != NULL) {
ForceZero(ctx->altPrivateKey->buffer,
ctx->altPrivateKey->length);
}
FreeDer(&ctx->altPrivateKey);
ctx->altPrivateKey = der;
#ifdef WOLFSSL_CHECK_MEM_ZERO
wc_MemZero_Add("CTX private key", der->buffer, der->length);
#endif
}
}
#endif /* WOLFSSL_DUAL_ALG_CERTS */
else {
FreeDer(&der);
return WOLFSSL_BAD_CERTTYPE;
@@ -7312,9 +7412,13 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
if (done == 1) {
/* No operation, just skip the next section */
}
else if (type == PRIVATEKEY_TYPE) {
else if (type == PRIVATEKEY_TYPE
#ifdef WOLFSSL_DUAL_ALG_CERTS
|| type == ALT_PRIVATEKEY_TYPE
#endif /* WOLFSSL_DUAL_ALG_CERTS */
) {
ret = ProcessBufferTryDecode(ctx, ssl, der, &keySz, &idx, &resetSuites,
&keyFormat, heap, devId);
&keyFormat, heap, devId, type);
#if defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_PWDBASED)
/* for WOLFSSL_FILETYPE_PEM, PemToDer manages the decryption */
@@ -7360,7 +7464,7 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
wc_MemZero_Check(password, NAME_SZ);
#endif
ret = ProcessBufferTryDecode(ctx, ssl, der, &keySz, &idx,
&resetSuites, &keyFormat, heap, devId);
&resetSuites, &keyFormat, heap, devId, type);
}
#endif /* WOLFSSL_ENCRYPTED_KEYS && !NO_PWDBASED */
@@ -8861,7 +8965,20 @@ int wolfSSL_CTX_use_PrivateKey_file(WOLFSSL_CTX* ctx, const char* file,
return WOLFSSL_FAILURE;
}
#ifdef WOLFSSL_DUAL_ALG_CERTS
int wolfSSL_CTX_use_AltPrivateKey_file(WOLFSSL_CTX* ctx, const char* file,
int format)
{
WOLFSSL_ENTER("wolfSSL_CTX_use_AltPrivateKey_file");
if (ProcessFile(ctx, file, format, ALT_PRIVATEKEY_TYPE, NULL, 0, NULL,
GET_VERIFY_SETTING_CTX(ctx)) == WOLFSSL_SUCCESS) {
return WOLFSSL_SUCCESS;
}
return WOLFSSL_FAILURE;
}
#endif /* WOLFSSL_DUAL_ALG_CERTS */
#endif /* NO_FILESYSTEM */
@@ -16111,6 +16228,15 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
ssl->buffers.weOwnKey = 0;
}
#ifdef WOLFSSL_DUAL_ALG_CERTS
if (ssl->buffers.weOwnAltKey) {
WOLFSSL_MSG("Unloading alt key");
ForceZero(ssl->buffers.altKey->buffer, ssl->buffers.altKey->length);
FreeDer(&ssl->buffers.altKey);
ssl->buffers.weOwnAltKey = 0;
}
#endif /* WOLFSSL_DUAL_ALG_CERTS */
return WOLFSSL_SUCCESS;
}
@@ -27272,6 +27398,11 @@ void wolfSSL_certs_clear(WOLFSSL* ssl)
ssl->buffers.keyLabel = 0;
ssl->buffers.keySz = 0;
ssl->buffers.keyDevId = 0;
#ifdef WOLFSSL_DUAL_ALG_CERTS
if (ssl->buffers.weOwnAltKey)
FreeDer(&ssl->buffers.altKey);
ssl->buffers.altKey = NULL;
#endif /* WOLFSSL_DUAL_ALG_CERTS */
}
#endif
@@ -28072,6 +28203,11 @@ WOLFSSL_CTX* wolfSSL_set_SSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
ssl->options.haveStaticECC = ctx->haveStaticECC;
ssl->options.haveFalconSig = ctx->haveFalconSig;
ssl->options.haveDilithiumSig = ctx->haveDilithiumSig;
#ifdef WOLFSSL_DUAL_ALG_CERTS
ssl->buffers.altKey = ctx->altPrivateKey;
ssl->buffers.altKeySz = ctx->altPrivateKeySz;
ssl->buffers.altKeyType = ctx->altPrivateKeyType;
#endif /* WOLFSSL_DUAL_ALG_CERTS */
#endif
#ifdef WOLFSSL_SESSION_ID_CTX

166
src/tls.c
View File

@@ -1325,6 +1325,10 @@ static WC_INLINE word16 TLSX_ToSemaphore(word16 type)
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
case TLSX_ECH: /* 0xfe0d */
return 65;
#endif
#ifdef WOLFSSL_DUAL_ALG_CERTS
case TLSX_CKS:
return 66;
#endif
default:
if (type > 62) {
@@ -9474,6 +9478,121 @@ int TLSX_KeyShare_SetSupported(const WOLFSSL* ssl, TLSX** extensions)
return ret;
}
#ifdef WOLFSSL_DUAL_ALG_CERTS
/* Writes the CKS objects of a list in a buffer. */
static word16 CKS_WRITE(WOLFSSL* ssl, byte* output)
{
XMEMCPY(output, ssl->sigSpec, ssl->sigSpecSz);
return ssl->sigSpecSz;
}
static int TLSX_UseCKS(TLSX** extensions, WOLFSSL* ssl, void* heap)
{
int ret = 0;
TLSX* extension;
if (extensions == NULL) {
return BAD_FUNC_ARG;
}
extension = TLSX_Find(*extensions, TLSX_CKS);
/* If it is already present, do nothing. */
if (extension == NULL) {
/* The data required is in the ssl struct, so push it in. */
ret = TLSX_Push(extensions, TLSX_CKS, (void*)ssl, heap);
}
return ret;
}
int TLSX_CKS_Set(WOLFSSL* ssl, TLSX** extensions)
{
int ret;
TLSX* extension;
/* Push new KeyShare extension. This will also free the old one */
ret = TLSX_Push(extensions, TLSX_CKS, NULL, ssl->heap);
if (ret != 0)
return ret;
/* Extension got pushed to head */
extension = *extensions;
/* Need ssl->sigSpecSz during extension length calculation. */
extension->data = ssl;
/* Set extension to be in response. */
extension->resp = 1;
return ret;
}
int TLSX_CKS_Parse(WOLFSSL* ssl, byte* input, word16 length,
TLSX** extensions)
{
(void) extensions;
int ret;
int i, j;
/* Validating the input. */
if (length == 0)
return BUFFER_ERROR;
for (i = 0; i < length; i++) {
switch (input[i])
{
case WOLFSSL_CKS_SIGSPEC_NATIVE:
case WOLFSSL_CKS_SIGSPEC_ALTERNATIVE:
case WOLFSSL_CKS_SIGSPEC_BOTH:
/* These are all valid values; do nothing */
break;
case WOLFSSL_CKS_SIGSPEC_EXTERNAL:
default:
/* All other values (including external) are not. */
return WOLFSSL_NOT_IMPLEMENTED;
}
}
/* Extension data is valid, but if we are the server and we don't have an
* alt private key, do not respond with CKS extension. */
if (wolfSSL_is_server(ssl) && ssl->buffers.altKey == NULL) {
ssl->sigSpec = NULL;
ssl->sigSpecSz = 0;
return 0;
}
/* Copy as the lifetime of input seems to be ephemeral. */
ssl->peerSigSpec = (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_TLSX);
if (ssl->peerSigSpec == NULL) {
return BUFFER_ERROR;
}
XMEMCPY(ssl->peerSigSpec, input, length);
ssl->peerSigSpecSz = length;
/* If there is no preference set, use theirs... */
if (ssl->sigSpec == NULL) {
ret = wolfSSL_UseCKS(ssl, ssl->peerSigSpec, 1);
if (ret == WOLFSSL_SUCCESS) {
ret = TLSX_UseCKS(&ssl->extensions, ssl, ssl->heap);
TLSX_SetResponse(ssl, TLSX_CKS);
}
return ret;
}
/* ...otherwise, prioritize our preference. */
for (i = 0; i < ssl->sigSpecSz; i++) {
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);
if (ret == WOLFSSL_SUCCESS) {
ret = TLSX_UseCKS(&ssl->extensions, ssl, ssl->heap);
TLSX_SetResponse(ssl, TLSX_CKS);
}
return ret;
}
}
}
/* No match found. Cannot continue. */
return MATCH_SUITE_ERROR;
}
#endif /* WOLFSSL_DUAL_ALG_CERTS */
/* Server side KSE processing */
int TLSX_KeyShare_Choose(const WOLFSSL *ssl, TLSX* extensions,
byte cipherSuite0, byte cipherSuite, KeyShareEntry** kse, byte* searched)
@@ -12006,7 +12125,6 @@ void TLSX_FreeAll(TLSX* list, void* heap)
list = extension->next;
switch (extension->type) {
#if defined(HAVE_RPK)
case TLSX_CLIENT_CERTIFICATE_TYPE:
WOLFSSL_MSG("Client Certificate Type extension free");
@@ -12168,6 +12286,12 @@ void TLSX_FreeAll(TLSX* list, void* heap)
WOLFSSL_MSG("ECH extension free");
ECH_FREE((WOLFSSL_ECH*)extension->data, heap);
break;
#endif
#ifdef WOLFSSL_DUAL_ALG_CERTS
case TLSX_CKS:
WOLFSSL_MSG("CKS extension free");
/* nothing to do */
break;
#endif
default:
break;
@@ -12209,7 +12333,11 @@ static int TLSX_GetSize(TLSX* list, byte* semaphore, byte msgType,
length += HELLO_EXT_TYPE_SZ + OPAQUE16_LEN;
switch (extension->type) {
#ifdef WOLFSSL_DUAL_ALG_CERTS
case TLSX_CKS:
length += ((WOLFSSL*)extension->data)->sigSpecSz ;
break;
#endif
#ifdef HAVE_SNI
case TLSX_SERVER_NAME:
/* SNI only sends the name on the request. */
@@ -12400,6 +12528,13 @@ static int TLSX_Write(TLSX* list, byte* output, byte* semaphore,
/* extension data should be written internally. */
switch (extension->type) {
#ifdef WOLFSSL_DUAL_ALG_CERTS
case TLSX_CKS:
WOLFSSL_MSG("CKS extension to write");
offset += CKS_WRITE(((WOLFSSL*)extension->data),
output + offset);
break;
#endif
#ifdef HAVE_SNI
case TLSX_SERVER_NAME:
if (isRequest) {
@@ -12909,6 +13044,14 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer)
return ret;
}
}
#endif
#ifdef WOLFSSL_DUAL_ALG_CERTS
if ((IsAtLeastTLSv1_3(ssl->version)) && (ssl->sigSpec != NULL)) {
WOLFSSL_MSG("Adding CKS extension");
if ((ret = TLSX_UseCKS(&ssl->extensions, ssl, ssl->heap)) != 0) {
return ret;
}
}
#endif
} /* is not server */
@@ -13653,6 +13796,10 @@ int TLSX_WriteRequest(WOLFSSL* ssl, byte* output, byte msgType, word16* pOffset)
TURN_ON(semaphore,
TLSX_ToSemaphore(TLSX_CERTIFICATE_AUTHORITIES));
#endif
#ifdef WOLFSSL_DUAL_ALG_CERTS
TURN_ON(semaphore,
TLSX_ToSemaphore(TLSX_CKS));
#endif
}
#endif
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
@@ -13747,7 +13894,6 @@ int TLSX_WriteRequest(WOLFSSL* ssl, byte* output, byte msgType, word16* pOffset)
return ret;
}
#endif /* WOLFSSL_TLS13 || !NO_WOLFSSL_CLIENT */
#if defined(WOLFSSL_TLS13) || !defined(NO_WOLFSSL_SERVER)
@@ -14278,7 +14424,19 @@ int TLSX_Parse(WOLFSSL* ssl, const byte* input, word16 length, byte msgType,
ret = EC_PARSE(ssl, input + offset, size, isRequest,
&ssl->extensions);
break;
#ifdef WOLFSSL_DUAL_ALG_CERTS
case TLSX_CKS:
WOLFSSL_MSG("CKS extension received");
if (!IsAtLeastTLSv1_3(ssl->version) ||
(msgType != client_hello &&
msgType != encrypted_extensions)) {
WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
return EXT_NOT_ALLOWED;
}
ret = TLSX_CKS_Parse(ssl, (byte *)(input + offset), size,
&ssl->extensions);
break;
#endif /* WOLFSSL_DUAL_ALG_CERTS */
case TLSX_EC_POINT_FORMATS:
WOLFSSL_MSG("Point Formats extension received");
#ifdef WOLFSSL_DEBUG_TLS

View File

@@ -117,6 +117,7 @@
#include <wolfssl/wolfcrypt/asn.h>
#include <wolfssl/wolfcrypt/dh.h>
#include <wolfssl/wolfcrypt/kdf.h>
#include <wolfssl/wolfcrypt/signature.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
@@ -7784,6 +7785,54 @@ static WC_INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output)
}
}
#ifdef WOLFSSL_DUAL_ALG_CERTS
/* These match up with what the OQS team has defined. */
#define HYBRID_SA_MAJOR 0xFE
#define HYBRID_P256_DILITHIUM_LEVEL2_SA_MINOR 0xA1
#define HYBRID_RSA3072_DILITHIUM_LEVEL2_SA_MINOR 0xA2
#define HYBRID_P384_DILITHIUM_LEVEL3_SA_MINOR 0xA4
#define HYBRID_P521_DILITHIUM_LEVEL5_SA_MINOR 0xA6
#define HYBRID_P256_FALCON_LEVEL1_SA_MINOR 0x0C
#define HYBRID_RSA3072_FALCON_LEVEL1_SA_MINOR 0x0D
#define HYBRID_P521_FALCON_LEVEL5_SA_MINOR 0x0F
static void EncodeDualSigAlg(byte sigAlg, byte altSigAlg, byte* output)
{
/* Initialize output to error indicator. */
output[0] = 0x0;
output[1] = 0x0;
if (sigAlg == ecc_dsa_sa_algo && altSigAlg == dilithium_level2_sa_algo) {
output[1] = HYBRID_P256_DILITHIUM_LEVEL2_SA_MINOR;
}
else if (sigAlg == rsa_pss_sa_algo &&
altSigAlg == dilithium_level2_sa_algo) {
output[1] = HYBRID_RSA3072_DILITHIUM_LEVEL2_SA_MINOR;
}
else if (sigAlg == ecc_dsa_sa_algo &&
altSigAlg == dilithium_level3_sa_algo) {
output[1] = HYBRID_P384_DILITHIUM_LEVEL3_SA_MINOR;
}
else if (sigAlg == ecc_dsa_sa_algo &&
altSigAlg == dilithium_level5_sa_algo) {
output[1] = HYBRID_P521_DILITHIUM_LEVEL5_SA_MINOR;
}
else if (sigAlg == ecc_dsa_sa_algo && altSigAlg == falcon_level1_sa_algo) {
output[1] = HYBRID_P256_FALCON_LEVEL1_SA_MINOR;
}
else if (sigAlg == rsa_pss_sa_algo && altSigAlg == falcon_level1_sa_algo) {
output[1] = HYBRID_RSA3072_FALCON_LEVEL1_SA_MINOR;
}
else if (sigAlg == ecc_dsa_sa_algo && altSigAlg == falcon_level5_sa_algo) {
output[1] = HYBRID_P521_FALCON_LEVEL5_SA_MINOR;
}
if (output[1] != 0x0) {
output[0] = HYBRID_SA_MAJOR;
}
}
#endif /* WOLFSSL_DUAL_ALG_CERTS */
/* Decode the signature algorithm.
*
* input The encoded signature algorithm.
@@ -7876,6 +7925,65 @@ static WC_INLINE int DecodeTls13SigAlg(byte* input, byte* hashAlgo,
return ret;
}
#ifdef WOLFSSL_DUAL_ALG_CERTS
/* Decode the hybrid signature algorithm.
*
* input The encoded signature algorithm.
* hashalgo The hash algorithm.
* hsType The signature type.
* returns INVALID_PARAMETER if not recognized and 0 otherwise.
*/
static WC_INLINE int DecodeTls13HybridSigAlg(byte* input, byte* hashAlg,
byte *sigAlg, byte *altSigAlg)
{
if (input[0] != HYBRID_SA_MAJOR) {
return INVALID_PARAMETER;
}
if (input[1] == HYBRID_P256_DILITHIUM_LEVEL2_SA_MINOR) {
*sigAlg = ecc_dsa_sa_algo;
*hashAlg = 4; /* WC_HASH_TYPE_SHA? Reviewer? */
*altSigAlg = dilithium_level2_sa_algo;
}
else if (input[1] == HYBRID_RSA3072_DILITHIUM_LEVEL2_SA_MINOR) {
*sigAlg = rsa_pss_sa_algo;
*hashAlg = 4;
*altSigAlg = dilithium_level2_sa_algo;
}
else if (input[1] == HYBRID_P384_DILITHIUM_LEVEL3_SA_MINOR) {
*sigAlg = ecc_dsa_sa_algo;
*hashAlg = 5;
*altSigAlg = dilithium_level3_sa_algo;
}
else if (input[1] == HYBRID_P521_DILITHIUM_LEVEL5_SA_MINOR) {
*sigAlg = ecc_dsa_sa_algo;
*hashAlg = 6;
*altSigAlg = dilithium_level5_sa_algo;
}
else if (input[1] == HYBRID_P256_FALCON_LEVEL1_SA_MINOR) {
*sigAlg = ecc_dsa_sa_algo;
*hashAlg = 4;
*altSigAlg = falcon_level1_sa_algo;
}
else if (input[1] == HYBRID_RSA3072_FALCON_LEVEL1_SA_MINOR) {
*sigAlg = rsa_pss_sa_algo;
*hashAlg = 4;
*altSigAlg = falcon_level1_sa_algo;
}
else if (input[1] == HYBRID_P521_FALCON_LEVEL5_SA_MINOR) {
*sigAlg = ecc_dsa_sa_algo;
*hashAlg = 6;
*altSigAlg = falcon_level5_sa_algo;
}
else {
return INVALID_PARAMETER;
}
return 0;
}
#endif /* WOLFSSL_DUAL_ALG_CERTS */
/* Get the hash of the messages so far.
*
* ssl The SSL/TLS object.
@@ -8529,6 +8637,10 @@ typedef struct Scv13Args {
byte sigAlgo;
byte* sigData;
word16 sigDataSz;
#ifdef WOLFSSL_DUAL_ALG_CERTS
byte altSigAlgo;
word16 altSigLen; /* Only used in the case of both native and alt. */
#endif
} Scv13Args;
static void FreeScv13Args(WOLFSSL* ssl, void* pArgs)
@@ -8671,6 +8783,29 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl)
ERROR_OUT(NO_PRIVATE_KEY, exit_scv);
}
else {
#ifdef WOLFSSL_DUAL_ALG_CERTS
if (wolfSSL_is_server(ssl) &&
ssl->sigSpec != NULL &&
*ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_ALTERNATIVE) {
/* In the case of alternative, we swap in the alt. */
if (ssl->ctx->altPrivateKey == NULL) {
ERROR_OUT(NO_PRIVATE_KEY, exit_scv);
}
ssl->buffers.keyType = ssl->buffers.altKeyType;
ssl->buffers.keySz = ssl->buffers.altKeySz;
/* If we own it, free key before overriding it. */
if (ssl->buffers.weOwnKey) {
FreeDer(&ssl->buffers.key);
}
/* Transfer ownership. ssl->ctx always owns the alt private
* key. */
ssl->buffers.key = ssl->ctx->altPrivateKey;
ssl->ctx->altPrivateKey = NULL;
ssl->buffers.weOwnKey = 1;
ssl->buffers.weOwnAltKey = 0;
}
#endif /* WOLFSSL_DUAL_ALG_CERTS */
ret = DecodePrivateKey(ssl, &args->length);
if (ret != 0)
goto exit_scv;
@@ -8752,7 +8887,51 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl)
else {
ERROR_OUT(ALGO_ID_E, exit_scv);
}
EncodeSigAlg(ssl->options.hashAlgo, args->sigAlgo, args->verify);
#ifdef WOLFSSL_DUAL_ALG_CERTS
if (ssl->peerSigSpec == NULL) {
/* The peer did not respond. We didn't send CKS or they don't
* support it. Either way, we do not need to handle dual
* key/sig case. */
ssl->sigSpec = NULL;
ssl->sigSpecSz = 0;
}
if (wolfSSL_is_server(ssl) &&
ssl->sigSpec != NULL &&
*ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_BOTH) {
/* The native was already decoded. Now we need to do the
* alternative. Note that no swap was done because this case is
* both native and alternative, not just alternative. */
if (ssl->ctx->altPrivateKey == NULL) {
ERROR_OUT(NO_PRIVATE_KEY, exit_scv);
}
if (ssl->buffers.altKeyType == falcon_level1_sa_algo ||
ssl->buffers.altKeyType == falcon_level5_sa_algo ||
ssl->buffers.altKeyType == dilithium_level2_sa_algo ||
ssl->buffers.altKeyType == dilithium_level3_sa_algo ||
ssl->buffers.altKeyType == dilithium_level5_sa_algo) {
args->altSigAlgo = ssl->buffers.altKeyType;
}
else {
ERROR_OUT(ALGO_ID_E, exit_scv);
}
/* After this call, args->altSigLen has the length we need for
* the alternative signature. */
ret = DecodeAltPrivateKey(ssl, &args->altSigLen);
if (ret != 0)
goto exit_scv;
EncodeDualSigAlg(args->sigAlgo, args->altSigAlgo, args->verify);
if (args->verify[0] == 0) {
ERROR_OUT(ALGO_ID_E, exit_scv);
}
}
else
#endif /* WOLFSSL_DUAL_ALG_CERTS */
EncodeSigAlg(ssl->options.hashAlgo, args->sigAlgo,
args->verify);
if (args->sigData == NULL) {
if (ssl->hsType == DYNAMIC_TYPE_RSA) {
@@ -8831,6 +9010,7 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl)
}
sig->length = ED448_SIG_SIZE;
}
#endif /* HAVE_ED448 */
#if defined(HAVE_PQC)
#if defined(HAVE_FALCON)
@@ -8874,6 +9054,32 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl)
#endif
);
}
#ifdef WOLFSSL_DUAL_ALG_CERTS
if (wolfSSL_is_server(ssl) &&
ssl->sigSpec != NULL &&
*ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_BOTH) {
if (ssl->hsAltType == DYNAMIC_TYPE_DILITHIUM) {
/* note the + sig->length; we are appending. */
ret = wc_dilithium_sign_msg(
args->sigData, args->sigDataSz,
args->verify + HASH_SIG_SIZE +
VERIFY_HEADER + sig->length,
(word32*)&args->altSigLen,
(dilithium_key*)ssl->hsAltKey, ssl->rng);
}
else if (ssl->hsAltType == DYNAMIC_TYPE_FALCON) {
/* note the sig->length; we are appending. */
ret = wc_falcon_sign_msg(args->sigData, args->sigDataSz,
args->verify + HASH_SIG_SIZE +
VERIFY_HEADER + sig->length,
(word32*)&args->altSigLen,
(falcon_key*)ssl->hsAltKey,
ssl->rng);
}
}
#endif /* WOLFSSL_DUAL_ALG_CERTS */
args->length = (word16)sig->length;
}
#endif /* HAVE_ECC */
@@ -8933,6 +9139,36 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl)
(RsaKey*)ssl->hsKey,
ssl->buffers.key
);
#ifdef WOLFSSL_DUAL_ALG_CERTS
/* In the case of RSA, we need to do the CKS both case here
* BEFORE args->sigData is overwritten!! We keep the sig
* separate and then append later so we don't interfere with the
* checks below. */
if (wolfSSL_is_server(ssl) &&
ssl->sigSpec != NULL &&
*ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_BOTH) {
if (ssl->hsAltType == DYNAMIC_TYPE_DILITHIUM) {
/* note the + args->sigLen; we are appending. */
ret = wc_dilithium_sign_msg(args->sigData,
args->sigDataSz,
args->verify + HASH_SIG_SIZE + VERIFY_HEADER +
args->sigLen,
(word32*)&args->altSigLen,
(dilithium_key*)ssl->hsAltKey, ssl->rng);
}
else if (ssl->hsAltType == DYNAMIC_TYPE_FALCON) {
/* note the + args->sigLen; we are appending. */
ret = wc_falcon_sign_msg(args->sigData, args->sigDataSz,
args->verify + HASH_SIG_SIZE +
VERIFY_HEADER + args->sigLen,
(word32*)&args->altSigLen,
(falcon_key*)ssl->hsAltKey,
ssl->rng);
}
}
#endif /* WOLFSSL_DUAL_ALG_CERTS */
if (ret == 0) {
args->length = (word16)args->sigLen;
@@ -8948,6 +9184,11 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl)
goto exit_scv;
}
#ifdef WOLFSSL_DUAL_ALG_CERTS
/* Add in length of the alt sig which will be appended to the sig */
args->length += args->altSigLen;
#endif /* WOLFSSL_DUAL_ALG_CERTS */
/* Add signature length. */
c16toa(args->length, args->verify + HASH_SIG_SIZE);
@@ -9171,6 +9412,13 @@ typedef struct Dcv13Args {
byte* sigData;
word16 sigDataSz;
#ifdef WOLFSSL_DUAL_ALG_CERTS
byte altSigAlgo;
byte* altSigData;
word16 altSigDataSz;
word16 altSignatureSz;
byte altPeerAuthGood;
#endif
} Dcv13Args;
static void FreeDcv13Args(WOLFSSL* ssl, void* pArgs)
@@ -9181,10 +9429,82 @@ static void FreeDcv13Args(WOLFSSL* ssl, void* pArgs)
XFREE(args->sigData, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
args->sigData = NULL;
}
#ifdef WOLFSSL_DUAL_ALG_CERTS
if (args && args->altSigData != NULL) {
XFREE(args->altSigData, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
args->altSigData = NULL;
}
#endif
(void)ssl;
}
#ifdef WOLFSSL_DUAL_ALG_CERTS
/* ssl->peerCert->sapkiDer is the alternative public key. Hopefully it is a
* dilithium public key. Convert it into a usable public key. */
static int decodeDilithiumKey(WOLFSSL* ssl, int level)
{
int keyRet;
word32 tmpIdx = 0;
if (ssl->peerDilithiumKeyPresent)
return INVALID_PARAMETER;
keyRet = AllocKey(ssl, DYNAMIC_TYPE_DILITHIUM,
(void**)&ssl->peerDilithiumKey);
if (keyRet != 0)
return PEER_KEY_ERROR;
ssl->peerDilithiumKeyPresent = 1;
keyRet = wc_dilithium_init(ssl->peerDilithiumKey);
if (keyRet != 0)
return PEER_KEY_ERROR;
keyRet = wc_dilithium_set_level(ssl->peerDilithiumKey, level);
if (keyRet != 0)
return PEER_KEY_ERROR;
keyRet = wc_Dilithium_PublicKeyDecode(ssl->peerCert.sapkiDer, &tmpIdx,
ssl->peerDilithiumKey,
ssl->peerCert.sapkiLen);
if (keyRet != 0)
return PEER_KEY_ERROR;
return 0;
}
/* ssl->peerCert->sapkiDer is the alternative public key. Hopefully it is a
* falcon public key. Convert it into a usable public key. */
static int decodeFalconKey(WOLFSSL* ssl, int level)
{
int keyRet;
word32 tmpIdx = 0;
if (ssl->peerFalconKeyPresent)
return INVALID_PARAMETER;
keyRet = AllocKey(ssl, DYNAMIC_TYPE_FALCON, (void**)&ssl->peerFalconKey);
if (keyRet != 0)
return PEER_KEY_ERROR;
ssl->peerFalconKeyPresent = 1;
keyRet = wc_falcon_init(ssl->peerFalconKey);
if (keyRet != 0)
return PEER_KEY_ERROR;
keyRet = wc_falcon_set_level(ssl->peerFalconKey, level);
if (keyRet != 0)
return PEER_KEY_ERROR;
keyRet = wc_Falcon_PublicKeyDecode(ssl->peerCert.sapkiDer, &tmpIdx,
ssl->peerFalconKey,
ssl->peerCert.sapkiLen);
if (keyRet != 0)
return PEER_KEY_ERROR;
return 0;
}
#endif
/* handle processing TLS v1.3 certificate_verify (15) */
/* Parse and handle a TLS v1.3 CertificateVerify message.
*
@@ -9274,8 +9594,36 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input,
if ((args->idx - args->begin) + ENUM_LEN + ENUM_LEN > totalSz) {
ERROR_OUT(BUFFER_ERROR, exit_dcv);
}
ret = DecodeTls13SigAlg(input + args->idx, &args->hashAlgo,
&args->sigAlgo);
#ifdef WOLFSSL_DUAL_ALG_CERTS
if (ssl->peerSigSpec == NULL) {
/* The peer did not respond. We didn't send CKS or they don't
* support it. Either way, we do not need to handle dual
* key/sig case. */
ssl->sigSpec = NULL;
ssl->sigSpecSz = 0;
}
/* If no CKS extension or either native or alternative, then just
* get a normal sigalgo. But if BOTH, then get the native and alt
* sig algos. */
if (wolfSSL_is_server(ssl) ||
ssl->sigSpec == NULL ||
*ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_NATIVE ||
*ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_ALTERNATIVE) {
#endif /* WOLFSSL_DUAL_ALG_CERTS */
ret = DecodeTls13SigAlg(input + args->idx, &args->hashAlgo,
&args->sigAlgo);
#ifdef WOLFSSL_DUAL_ALG_CERTS
}
else {
ret = DecodeTls13HybridSigAlg(input + args->idx,
&args->hashAlgo,
&args->sigAlgo,
&args->altSigAlgo);
}
#endif /* WOLFSSL_DUAL_ALG_CERTS */
if (ret < 0)
goto exit_dcv;
args->idx += OPAQUE16_LEN;
@@ -9293,6 +9641,95 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input,
ERROR_OUT(BUFFER_ERROR, exit_dcv);
}
#ifdef WOLFSSL_DUAL_ALG_CERTS
if (!wolfSSL_is_server(ssl) &&
(ssl->sigSpec != NULL) &&
(*ssl->sigSpec != WOLFSSL_CKS_SIGSPEC_NATIVE)) {
word16 sa;
if (args->altSigAlgo == 0)
sa = args->sigAlgo;
else
sa = args->altSigAlgo;
switch(sa) {
case dilithium_level2_sa_algo:
ret = decodeDilithiumKey(ssl, 2);
break;
case dilithium_level3_sa_algo:
ret = decodeDilithiumKey(ssl, 3);
break;
case dilithium_level5_sa_algo:
ret = decodeDilithiumKey(ssl, 5);
break;
case falcon_level1_sa_algo:
ret = decodeFalconKey(ssl, 1);
break;
case falcon_level5_sa_algo:
ret = decodeFalconKey(ssl, 5);
break;
default:
ERROR_OUT(PEER_KEY_ERROR, exit_dcv);
break;
}
if (ret != 0)
ERROR_OUT(ret, exit_dcv);
if (*ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_ALTERNATIVE) {
/* Now swap in the alternative. We only support hybrid certs
* where native is RSA or ECC so check that either of those
* are present and then remove it. */
if (ssl->peerRsaKeyPresent &&
ssl->peerEccDsaKeyPresent) {
/* They shouldn't both be present. */
ERROR_OUT(PEER_KEY_ERROR, exit_dcv);
}
else if (ssl->peerRsaKeyPresent) {
FreeKey(ssl, DYNAMIC_TYPE_RSA,
(void**)&ssl->peerRsaKey);
ssl->peerRsaKeyPresent = 0;
}
else if (ssl->peerEccDsaKeyPresent) {
FreeKey(ssl, DYNAMIC_TYPE_ECC,
(void**)&ssl->peerEccDsaKey);
ssl->peerEccDsaKeyPresent = 0;
}
else {
ERROR_OUT(WOLFSSL_NOT_IMPLEMENTED, exit_dcv);
}
}
else if (*ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_BOTH) {
/* Use alternative public key to figure out the expected
* alt sig size. We only support Post-quantum key as SAPKI.
*/
switch(sa) {
case dilithium_level2_sa_algo:
case dilithium_level3_sa_algo:
case dilithium_level5_sa_algo:
ret = wc_dilithium_sig_size(ssl->peerDilithiumKey);
break;
case falcon_level1_sa_algo:
case falcon_level5_sa_algo:
ret = wc_falcon_sig_size(ssl->peerFalconKey);
break;
default:
ERROR_OUT(PEER_KEY_ERROR, exit_dcv);
break;
}
if (ret <= 0) {
ERROR_OUT(PEER_KEY_ERROR, exit_dcv);
}
args->altSignatureSz = ret;
ret = 0;
}
else {
ERROR_OUT(WOLFSSL_NOT_IMPLEMENTED, exit_dcv);
}
}
#endif /* WOLFSSL_DUAL_ALG_CERTS */
/* Check for public key of required type. */
/* Assume invalid unless signature algo matches the key provided */
validSigAlgo = 0;
@@ -9367,14 +9804,48 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input,
ERROR_OUT(SIG_VERIFY_E, exit_dcv);
}
sig->buffer = (byte*)XMALLOC(args->sz, ssl->heap,
sig->length = args->sz;
#ifdef WOLFSSL_DUAL_ALG_CERTS
if (!wolfSSL_is_server(ssl) &&
ssl->sigSpec != NULL &&
*ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_BOTH) {
/* If its RSA, we only hybridize with RSA3072 which has a sig
* size of 384. For ECC, this is actually encoded as an RFC5912
* formatted signature which means we can use the ASN APIs to
* figure out the length. Note that some post-quantum sig algs
* have variable length signatures (Falcon). That is why we
* don't do:
* sig->length -= args->altSignatureSz; */
#define RSA3072_SIG_LEN 384
if (args->sigAlgo == rsa_pss_sa_algo) {
sig->length = RSA3072_SIG_LEN;
}
else if (args->sigAlgo == ecc_dsa_sa_algo) {
word32 tmpIdx = args->idx;
sig->length = wc_SignatureGetSize(WC_SIGNATURE_TYPE_ECC,
ssl->peerEccDsaKey,
sizeof(*ssl->peerEccDsaKey));
if (GetSequence(input, &tmpIdx, (int*)&sig->length,
args->sz) < 0) {
ERROR_OUT(SIG_VERIFY_E, exit_dcv);
}
/* We have to increment by the size of the header. */
sig->length += tmpIdx - args->idx;
}
else {
ERROR_OUT(WOLFSSL_NOT_IMPLEMENTED, exit_dcv);
}
}
#endif
sig->buffer = (byte*)XMALLOC(sig->length, ssl->heap,
DYNAMIC_TYPE_SIGNATURE);
if (sig->buffer == NULL) {
ERROR_OUT(MEMORY_E, exit_dcv);
}
sig->length = args->sz;
XMEMCPY(sig->buffer, input + args->idx, args->sz);
XMEMCPY(sig->buffer, input + args->idx, sig->length);
#ifdef HAVE_ECC
if (ssl->peerEccDsaKeyPresent) {
WOLFSSL_MSG("Doing ECC peer cert verify");
@@ -9430,29 +9901,29 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input,
}
#endif
#ifdef HAVE_PQC
if (ssl->peerFalconKeyPresent) {
WOLFSSL_MSG("Doing Falcon peer cert verify");
args->sigData = (byte*)XMALLOC(MAX_SIG_DATA_SZ, ssl->heap,
if (ssl->peerFalconKeyPresent || ssl->peerDilithiumKeyPresent) {
word16 sigDataSz;
byte *sigData = (byte*)XMALLOC(MAX_SIG_DATA_SZ, ssl->heap,
DYNAMIC_TYPE_SIGNATURE);
if (args->sigData == NULL) {
if (sigData == NULL) {
ERROR_OUT(MEMORY_E, exit_dcv);
}
CreateSigData(ssl, args->sigData, &args->sigDataSz, 1);
ret = 0;
}
if (ssl->peerDilithiumKeyPresent) {
WOLFSSL_MSG("Doing Dilithium peer cert verify");
args->sigData = (byte*)XMALLOC(MAX_SIG_DATA_SZ, ssl->heap,
DYNAMIC_TYPE_SIGNATURE);
if (args->sigData == NULL) {
ERROR_OUT(MEMORY_E, exit_dcv);
CreateSigData(ssl, sigData, &sigDataSz, 1);
#ifdef WOLFSSL_DUAL_ALG_CERTS
if (!wolfSSL_is_server(ssl) &&
ssl->sigSpec != NULL &&
*ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_BOTH) {
/* In this case (BOTH), the pq sig is the alternative. */
args->altSigData = sigData;
args->altSigDataSz = sigDataSz;
}
else
#endif /* WOLFSSL_DUAL_ALG_CERTS */
{
args->sigData = sigData;
args->sigDataSz = sigDataSz;
}
CreateSigData(ssl, args->sigData, &args->sigDataSz, 1);
ret = 0;
}
#endif
@@ -9492,7 +9963,7 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input,
else
#endif
{
ret = EccVerify(ssl, input + args->idx, args->sz,
ret = EccVerify(ssl, input + args->idx, sig->length,
args->sigData, args->sigDataSz,
ssl->peerEccDsaKey,
#ifdef HAVE_PK_CALLBACKS
@@ -9559,15 +10030,43 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input,
#if defined(HAVE_PQC) && defined(HAVE_FALCON)
if (ssl->peerFalconKeyPresent) {
int res = 0;
byte *sigIn = input + args->idx;
word32 sigInLen = args->sz;
byte *sigData = args->sigData;
word32 sigDataSz = args->sigDataSz;
WOLFSSL_MSG("Doing Falcon peer cert verify");
ret = wc_falcon_verify_msg(input + args->idx, args->sz,
args->sigData, args->sigDataSz,
&res, ssl->peerFalconKey);
#ifdef WOLFSSL_DUAL_ALG_CERTS
if (!wolfSSL_is_server(ssl) &&
ssl->sigSpec != NULL &&
*ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_BOTH) {
/* Note: + sig->length; we are skipping the native sig. */
sigIn = input + args->idx + sig->length;
sigInLen = args->sz - sig->length;
/* For RSA, something different was verified. */
if (ssl->peerRsaKeyPresent) {
sigData = args->altSigData;
sigDataSz = args->altSigDataSz;
}
}
#endif /* WOLFSSL_DUAL_ALG_CERTS */
ret = wc_falcon_verify_msg(sigIn, sigInLen,
sigData, sigDataSz,
&res, ssl->peerFalconKey);
if ((ret >= 0) && (res == 1)) {
/* CLIENT/SERVER: data verified with public key from
* certificate. */
ssl->options.peerAuthGood = 1;
#ifdef WOLFSSL_DUAL_ALG_CERTS
if (!wolfSSL_is_server(ssl) &&
ssl->sigSpec != NULL &&
*ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_BOTH) {
args->altPeerAuthGood = 1;
}
else
#endif /* WOLFSSL_DUAL_ALG_CERTS */
ssl->options.peerAuthGood = 1;
FreeKey(ssl, DYNAMIC_TYPE_FALCON,
(void**)&ssl->peerFalconKey);
ssl->peerFalconKeyPresent = 0;
@@ -9577,15 +10076,43 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input,
#if defined(HAVE_PQC) && defined(HAVE_DILITHIUM)
if (ssl->peerDilithiumKeyPresent) {
int res = 0;
byte *sigIn = input + args->idx;
word32 sigInLen = args->sz;
byte *sigData = args->sigData;
word32 sigDataSz = args->sigDataSz;
WOLFSSL_MSG("Doing Dilithium peer cert verify");
ret = wc_dilithium_verify_msg(input + args->idx, args->sz,
args->sigData, args->sigDataSz,
#ifdef WOLFSSL_DUAL_ALG_CERTS
if (!wolfSSL_is_server(ssl) &&
ssl->sigSpec != NULL &&
*ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_BOTH) {
/* Go backwards from the end of the signature the size of
* the alt sig to find the beginning of the alt sig. */
sigIn = input + args->idx + args->sz - args->altSignatureSz;
sigInLen = args->altSignatureSz;
/* For RSA, something different was verified. */
if (ssl->peerRsaKeyPresent) {
sigData = args->altSigData;
sigDataSz = args->altSigDataSz;
}
}
#endif /* WOLFSSL_DUAL_ALG_CERTS */
ret = wc_dilithium_verify_msg(sigIn, sigInLen,
sigData, sigDataSz,
&res, ssl->peerDilithiumKey);
if ((ret >= 0) && (res == 1)) {
/* CLIENT/SERVER: data verified with public key from
* certificate. */
ssl->options.peerAuthGood = 1;
#ifdef WOLFSSL_DUAL_ALG_CERTS
if (!wolfSSL_is_server(ssl) &&
ssl->sigSpec != NULL &&
*ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_BOTH) {
args->altPeerAuthGood = 1;
}
else
#endif /* WOLFSSL_DUAL_ALG_CERTS */
ssl->options.peerAuthGood = 1;
FreeKey(ssl, DYNAMIC_TYPE_DILITHIUM,
(void**)&ssl->peerDilithiumKey);
ssl->peerDilithiumKeyPresent = 0;
@@ -9627,6 +10154,14 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input,
case TLS_ASYNC_FINALIZE:
{
#ifdef WOLFSSL_DUAL_ALG_CERTS
if (!wolfSSL_is_server(ssl) &&
ssl->options.peerAuthGood &&
ssl->sigSpec != NULL &&
*ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_BOTH) {
ssl->options.peerAuthGood = args->altPeerAuthGood;
}
#endif /* WOLFSSL_DUAL_ALG_CERTS */
ssl->options.havePeerVerify = 1;
/* Set final index */
@@ -12510,6 +13045,30 @@ int wolfSSL_NoKeyShares(WOLFSSL* ssl)
}
#endif
#ifdef WOLFSSL_DUAL_ALG_CERTS
int wolfSSL_UseCKS(WOLFSSL* ssl, byte *sigSpec, word16 sigSpecSz)
{
if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->ctx->method->version) ||
sigSpec == NULL || sigSpecSz == 0)
return BAD_FUNC_ARG;
ssl->sigSpec = sigSpec;
ssl->sigSpecSz = sigSpecSz;
return WOLFSSL_SUCCESS;
}
int wolfSSL_CTX_UseCKS(WOLFSSL_CTX* ctx, byte *sigSpec, word16 sigSpecSz)
{
if (ctx == NULL || !IsAtLeastTLSv1_3(ctx->method->version) ||
sigSpec == NULL || sigSpecSz == 0)
return BAD_FUNC_ARG;
ctx->sigSpec = sigSpec;
ctx->sigSpecSz = sigSpecSz;
return WOLFSSL_SUCCESS;
}
#endif /* WOLFSSL_DUAL_ALG_CERTS */
/* Do not send a ticket after TLS v1.3 handshake for resumption.
*
* ctx The SSL/TLS CTX object.

View File

@@ -7523,6 +7523,45 @@ int wolfSSL_i2d_X509(WOLFSSL_X509* x509, unsigned char** out)
return derSz;
}
#ifdef WOLFSSL_DUAL_ALG_CERTS
int wc_GeneratePreTBS(DecodedCert* cert, byte *der, int derSz) {
int ret = 0;
WOLFSSL_X509 *x = NULL;
if ((cert == NULL) || (der == NULL) || (derSz <= 0)) {
return BAD_FUNC_ARG;
}
x = wolfSSL_X509_new();
if (x == NULL) {
ret = MEMORY_E;
}
else {
ret = CopyDecodedToX509(x, cert);
}
if (ret == 0) {
/* Remove the altsigval extension. */
XFREE(x->altSigValDer, x->heap, DYNAMIC_TYPE_X509_EXT);
x->altSigValDer = NULL;
x->altSigValDer = 0;
/* Remove sigOID so it won't be encoded. */
x->sigOID = 0;
/* We now have a PreTBS. Encode it. */
ret = wolfssl_x509_make_der(x, 0, der, &derSz, 0);
if (ret == WOLFSSL_SUCCESS) {
ret = derSz;
}
}
if (x != NULL) {
wolfSSL_X509_free(x);
}
return ret;
}
#endif /* WOLFSSL_DUAL_ALG_CERTS */
#ifndef NO_BIO
/**
* Converts the DER from bio and creates a WOLFSSL_X509 structure from it.
@@ -9928,6 +9967,16 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_chain_up_ref(
XMEMCPY(cert->crlInfo, x509->rawCRLInfo, x509->rawCRLInfoSz);
cert->crlInfoSz = x509->rawCRLInfoSz;
}
#ifdef WOLFSSL_DUAL_ALG_CERTS
/* We point to instance in x509 so DON'T need to be free'd. */
cert->sapkiDer = x509->sapkiDer;
cert->sapkiLen = x509->sapkiLen;
cert->altSigAlgDer = x509->altSigAlgDer;
cert->altSigAlgLen = x509->altSigAlgLen;
cert->altSigValDer = x509->altSigValDer;
cert->altSigValLen = x509->altSigValLen;
#endif /* WOLFSSL_DUAL_ALG_CERTS */
#endif /* WOLFSSL_CERT_EXT */
#ifdef WOLFSSL_CERT_REQ

View File

@@ -835,6 +835,314 @@ static int test_wolfSSL_Method_Allocators(void)
return EXPECT_RESULT();
}
#if defined(WOLFSSL_DUAL_ALG_CERTS) && !defined(NO_FILESYSTEM)
/*----------------------------------------------------------------------------*
| Dual algorithm Certificate Tests
*----------------------------------------------------------------------------*/
#define LARGE_TEMP_SZ 4096
/* To better understand this, please see the X9.146 example in wolfssl-examples
* repo. */
static int do_dual_alg_root_certgen(byte **out, char *caKeyFile,
char *sapkiFile, char *altPrivFile)
{
EXPECT_DECLS;
FILE* file = NULL;
Cert newCert;
DecodedCert preTBS;
byte caKeyBuf[LARGE_TEMP_SZ];
word32 caKeySz = LARGE_TEMP_SZ;
byte sapkiBuf[LARGE_TEMP_SZ];
word32 sapkiSz = LARGE_TEMP_SZ;
byte altPrivBuf[LARGE_TEMP_SZ];
word32 altPrivSz = LARGE_TEMP_SZ;
byte altSigAlgBuf[LARGE_TEMP_SZ];
word32 altSigAlgSz = LARGE_TEMP_SZ;
byte scratchBuf[LARGE_TEMP_SZ];
word32 scratchSz = LARGE_TEMP_SZ;
byte preTbsBuf[LARGE_TEMP_SZ];
word32 preTbsSz = LARGE_TEMP_SZ;
byte altSigValBuf[LARGE_TEMP_SZ];
word32 altSigValSz = LARGE_TEMP_SZ;
byte *outBuf = NULL;
word32 outSz = LARGE_TEMP_SZ;
WC_RNG rng;
RsaKey caKey;
ecc_key altCaKey;
word32 idx = 0;
ExpectNotNull(outBuf = (byte*)XMALLOC(outSz, NULL,
DYNAMIC_TYPE_TMP_BUFFER));
ExpectIntEQ(wc_InitRng(&rng), 0);
XMEMSET(caKeyBuf, 0, caKeySz);
ExpectNotNull(file = fopen(caKeyFile, "rb"));
ExpectIntGT(caKeySz = (word32)fread(caKeyBuf, 1, caKeySz, file), 0);
fclose(file);
ExpectIntEQ(wc_InitRsaKey_ex(&caKey, NULL, INVALID_DEVID), 0);
idx = 0;
ExpectIntEQ(wc_RsaPrivateKeyDecode(caKeyBuf, &idx, &caKey, caKeySz),
0);
XMEMSET(sapkiBuf, 0, sapkiSz);
ExpectNotNull(file = fopen(sapkiFile, "rb"));
ExpectIntGT(sapkiSz = (word32)fread(sapkiBuf, 1, sapkiSz, file), 0);
fclose(file);
XMEMSET(altPrivBuf, 0, altPrivSz);
ExpectNotNull(file = fopen(altPrivFile, "rb"));
ExpectIntGT(altPrivSz = (word32)fread(altPrivBuf, 1, altPrivSz, file), 0);
fclose(file);
wc_ecc_init(&altCaKey);
idx = 0;
ExpectIntEQ(wc_EccPrivateKeyDecode(altPrivBuf, &idx, &altCaKey,
(word32)altPrivSz), 0);
XMEMSET(altSigAlgBuf, 0, altSigAlgSz);
ExpectIntGT(altSigAlgSz = SetAlgoID(CTC_SHA256wECDSA, altSigAlgBuf,
oidSigType, 0), 0);
wc_InitCert(&newCert);
strncpy(newCert.subject.country, "US", CTC_NAME_SIZE);
strncpy(newCert.subject.state, "MT", CTC_NAME_SIZE);
strncpy(newCert.subject.locality, "Bozeman", CTC_NAME_SIZE);
strncpy(newCert.subject.org, "wolfSSL", CTC_NAME_SIZE);
strncpy(newCert.subject.unit, "Engineering", CTC_NAME_SIZE);
strncpy(newCert.subject.commonName, "www.wolfssl.com", CTC_NAME_SIZE);
strncpy(newCert.subject.email, "root@wolfssl.com", CTC_NAME_SIZE);
newCert.sigType = CTC_SHA256wRSA;
newCert.isCA = 1;
ExpectIntEQ(wc_SetCustomExtension(&newCert, 0, "1.2.3.4.5",
(const byte *)"This is NOT a critical extension", 32), 0);
ExpectIntEQ(wc_SetCustomExtension(&newCert, 0, "2.5.29.72", sapkiBuf,
sapkiSz), 0);
ExpectIntEQ(wc_SetCustomExtension(&newCert, 0, "2.5.29.73", altSigAlgBuf,
altSigAlgSz), 0);
XMEMSET(scratchBuf, 0, scratchSz);
ExpectIntGT(scratchSz = wc_MakeSelfCert(&newCert, scratchBuf, scratchSz,
&caKey, &rng), 0);
wc_InitDecodedCert(&preTBS, scratchBuf, scratchSz, 0);
ExpectIntEQ(wc_ParseCert(&preTBS, CERT_TYPE, NO_VERIFY, NULL), 0);
XMEMSET(preTbsBuf, 0, preTbsSz);
ExpectIntGT(preTbsSz = wc_GeneratePreTBS(&preTBS, preTbsBuf, preTbsSz), 0);
XMEMSET(altSigValBuf, 0, altSigValSz);
ExpectIntGT(altSigValSz = wc_MakeSigWithBitStr(altSigValBuf, altSigValSz,
CTC_SHA256wECDSA, preTbsBuf, preTbsSz, ECC_TYPE, &altCaKey,
&rng), 0);
ExpectIntEQ(wc_SetCustomExtension(&newCert, 0, "2.5.29.74", altSigValBuf,
altSigValSz), 0);
/* Finally, generate the new certificate. */
XMEMSET(outBuf, 0, outSz);
ExpectIntGT(outSz = wc_MakeSelfCert(&newCert, outBuf, outSz, &caKey, &rng),
0);
*out = outBuf;
wc_FreeRsaKey(&caKey);
wc_FreeRng(&rng);
return outSz;
}
static int do_dual_alg_server_certgen(byte **out, char *caKeyFile,
char *sapkiFile, char *altPrivFile,
char *serverKeyFile,
byte *caCertBuf, int caCertSz)
{
EXPECT_DECLS;
FILE* file = NULL;
Cert newCert;
DecodedCert preTBS;
byte serverKeyBuf[LARGE_TEMP_SZ];
word32 serverKeySz = LARGE_TEMP_SZ;
byte caKeyBuf[LARGE_TEMP_SZ];
word32 caKeySz = LARGE_TEMP_SZ;
byte sapkiBuf[LARGE_TEMP_SZ];
word32 sapkiSz = LARGE_TEMP_SZ;
byte altPrivBuf[LARGE_TEMP_SZ];
word32 altPrivSz = LARGE_TEMP_SZ;
byte altSigAlgBuf[LARGE_TEMP_SZ];
word32 altSigAlgSz = LARGE_TEMP_SZ;
byte scratchBuf[LARGE_TEMP_SZ];
word32 scratchSz = LARGE_TEMP_SZ;
byte preTbsBuf[LARGE_TEMP_SZ];
word32 preTbsSz = LARGE_TEMP_SZ;
byte altSigValBuf[LARGE_TEMP_SZ];
word32 altSigValSz = LARGE_TEMP_SZ;
byte *outBuf = NULL;
word32 outSz = LARGE_TEMP_SZ;
WC_RNG rng;
RsaKey caKey;
RsaKey serverKey;
ecc_key altCaKey;
word32 idx = 0;
ExpectNotNull(outBuf = (byte*)XMALLOC(outSz, NULL,
DYNAMIC_TYPE_TMP_BUFFER));
ExpectIntEQ(wc_InitRng(&rng), 0);
XMEMSET(serverKeyBuf, 0, serverKeySz);
ExpectNotNull(file = fopen(serverKeyFile, "rb"));
ExpectIntGT(serverKeySz = (word32)fread(serverKeyBuf, 1, serverKeySz, file),
0);
fclose(file);
ExpectIntEQ(wc_InitRsaKey_ex(&serverKey, NULL, INVALID_DEVID), 0);
idx = 0;
ExpectIntEQ(wc_RsaPrivateKeyDecode(serverKeyBuf, &idx, &serverKey,
(word32)serverKeySz), 0);
XMEMSET(caKeyBuf, 0, caKeySz);
ExpectNotNull(file = fopen(caKeyFile, "rb"));
ExpectIntGT(caKeySz = (word32)fread(caKeyBuf, 1, caKeySz, file), 0);
fclose(file);
ExpectIntEQ(wc_InitRsaKey_ex(&caKey, NULL, INVALID_DEVID), 0);
idx = 0;
ExpectIntEQ(wc_RsaPrivateKeyDecode(caKeyBuf, &idx, &caKey,
(word32)caKeySz), 0);
XMEMSET(sapkiBuf, 0, sapkiSz);
ExpectNotNull(file = fopen(sapkiFile, "rb"));
ExpectIntGT(sapkiSz = (word32)fread(sapkiBuf, 1, sapkiSz, file), 0);
fclose(file);
XMEMSET(altPrivBuf, 0, altPrivSz);
ExpectNotNull(file = fopen(altPrivFile, "rb"));
ExpectIntGT(altPrivSz = (word32)fread(altPrivBuf, 1, altPrivSz, file), 0);
fclose(file);
wc_ecc_init(&altCaKey);
idx = 0;
ExpectIntEQ(wc_EccPrivateKeyDecode(altPrivBuf, &idx, &altCaKey,
(word32)altPrivSz), 0);
XMEMSET(altSigAlgBuf, 0, altSigAlgSz);
ExpectIntGT(altSigAlgSz = SetAlgoID(CTC_SHA256wECDSA, altSigAlgBuf,
oidSigType, 0), 0);
wc_InitCert(&newCert);
strncpy(newCert.subject.country, "US", CTC_NAME_SIZE);
strncpy(newCert.subject.state, "MT", CTC_NAME_SIZE);
strncpy(newCert.subject.locality, "Bozeman", CTC_NAME_SIZE);
strncpy(newCert.subject.org, "wolfSSL", CTC_NAME_SIZE);
strncpy(newCert.subject.unit, "Engineering", CTC_NAME_SIZE);
strncpy(newCert.subject.commonName, "www.wolfssl.com", CTC_NAME_SIZE);
strncpy(newCert.subject.email, "server@wolfssl.com", CTC_NAME_SIZE);
newCert.sigType = CTC_SHA256wRSA;
newCert.isCA = 0;
ExpectIntEQ(wc_SetIssuerBuffer(&newCert, caCertBuf, caCertSz), 0);
ExpectIntEQ(wc_SetCustomExtension(&newCert, 0, "1.2.3.4.5",
(const byte *)"This is NOT a critical extension", 32), 0);
ExpectIntEQ(wc_SetCustomExtension(&newCert, 0, "2.5.29.72", sapkiBuf,
sapkiSz), 0);
ExpectIntEQ(wc_SetCustomExtension(&newCert, 0, "2.5.29.73", altSigAlgBuf,
altSigAlgSz), 0);
XMEMSET(scratchBuf, 0, scratchSz);
ExpectIntGT(wc_MakeCert(&newCert, scratchBuf, scratchSz, &serverKey, NULL,
&rng), 0);
ExpectIntGT(scratchSz = wc_SignCert(newCert.bodySz, newCert.sigType,
scratchBuf, scratchSz, &caKey, NULL, &rng), 0);
wc_InitDecodedCert(&preTBS, scratchBuf, scratchSz, 0);
ExpectIntEQ(wc_ParseCert(&preTBS, CERT_TYPE, NO_VERIFY, NULL), 0);
XMEMSET(preTbsBuf, 0, preTbsSz);
ExpectIntGT(preTbsSz = wc_GeneratePreTBS(&preTBS, preTbsBuf, preTbsSz), 0);
XMEMSET(altSigValBuf, 0, altSigValSz);
ExpectIntGT(altSigValSz = wc_MakeSigWithBitStr(altSigValBuf, altSigValSz,
CTC_SHA256wECDSA, preTbsBuf, preTbsSz, ECC_TYPE, &altCaKey,
&rng), 0);
ExpectIntEQ(wc_SetCustomExtension(&newCert, 0, "2.5.29.74",
altSigValBuf, altSigValSz), 0);
/* Finally, generate the new certificate. */
XMEMSET(outBuf, 0, outSz);
ExpectIntGT(wc_MakeCert(&newCert, outBuf, outSz, &serverKey, NULL, &rng),
0);
ExpectIntGT(outSz = wc_SignCert(newCert.bodySz, newCert.sigType, outBuf,
outSz, &caKey, NULL, &rng), 0);
*out = outBuf;
wc_FreeRsaKey(&caKey);
wc_FreeRsaKey(&serverKey);
wc_FreeRng(&rng);
return outSz;
}
static int do_dual_alg_tls13_connection(byte *caCert, word32 caCertSz,
byte *serverCert, word32 serverCertSz,
byte *serverKey, word32 serverKeySz,
int negative_test)
{
EXPECT_DECLS;
WOLFSSL_CTX *ctx_c = NULL;
WOLFSSL_CTX *ctx_s = NULL;
WOLFSSL *ssl_c = NULL;
WOLFSSL *ssl_s = NULL;
struct test_memio_ctx test_ctx;
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
ExpectIntEQ(test_memio_setup_ex(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method,
caCert, caCertSz, serverCert, serverCertSz,
serverKey, serverKeySz), 0);
if (negative_test) {
ExpectTrue(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL) != 0);
}
else {
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
}
wolfSSL_free(ssl_c);
wolfSSL_free(ssl_s);
wolfSSL_CTX_free(ctx_c);
wolfSSL_CTX_free(ctx_s);
return EXPECT_RESULT();
}
static int test_dual_alg_support(void)
{
EXPECT_DECLS;
/* Root CA and server keys will be the same. This is only appropriate for
* testing. */
char keyFile[] = "./certs/ca-key.der";
char sapkiFile[] = "./certs/ecc-keyPub.der";
char altPrivFile[] = "./certs/ecc-key.der";
char wrongPrivFile[] = "./certs/ecc-client-key.der";
byte *serverKey = NULL;
size_t serverKeySz = 0;
byte *root = NULL;
int rootSz = 0;
byte *server = NULL;
int serverSz = 0;
ExpectIntEQ(load_file(keyFile, &serverKey, &serverKeySz), 0);
/* Base normal case. */
rootSz = do_dual_alg_root_certgen(&root, keyFile, sapkiFile, altPrivFile);
ExpectNotNull(root);
ExpectIntGT(rootSz, 0);
serverSz = do_dual_alg_server_certgen(&server, keyFile, sapkiFile,
altPrivFile, keyFile, root, rootSz);
ExpectNotNull(server);
ExpectIntGT(serverSz, 0);
ExpectIntEQ(do_dual_alg_tls13_connection(root, rootSz,
server, serverSz, serverKey, (word32)serverKeySz, 0),
TEST_SUCCESS);
XFREE(root, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(server, NULL, DYNAMIC_TYPE_TMP_BUFFER);
/* 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. */
rootSz = do_dual_alg_root_certgen(&root, keyFile, sapkiFile, wrongPrivFile);
ExpectNotNull(root);
ExpectIntGT(rootSz, 0);
serverSz = do_dual_alg_server_certgen(&server, keyFile, sapkiFile,
wrongPrivFile, keyFile, root, rootSz);
ExpectNotNull(server);
ExpectIntGT(serverSz, 0);
ExpectIntEQ(do_dual_alg_tls13_connection(root, rootSz,
server, serverSz, serverKey, (word32)serverKeySz, 1),
TEST_SUCCESS);
XFREE(root, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(server, NULL, DYNAMIC_TYPE_TMP_BUFFER);
free(serverKey);
return EXPECT_RESULT();
}
#else
static int test_dual_alg_support(void)
{
return TEST_SKIPPED;
}
#endif /* WOLFSSL_DUAL_ALG_CERTS && !NO_FILESYSTEM */
/*----------------------------------------------------------------------------*
| Context
@@ -69275,6 +69583,8 @@ TEST_CASE testCases[] = {
TEST_DECL(test_wolfSSL_Init),
TEST_DECL(test_dual_alg_support),
/*********************************
* OpenSSL compatibility API tests
*********************************/

View File

@@ -155,6 +155,12 @@ int test_memio_do_handshake(WOLFSSL *ssl_c, WOLFSSL *ssl_s,
int test_memio_setup(struct test_memio_ctx *ctx,
WOLFSSL_CTX **ctx_c, WOLFSSL_CTX **ctx_s, WOLFSSL **ssl_c, WOLFSSL **ssl_s,
method_provider method_c, method_provider method_s);
int test_memio_setup_ex(struct test_memio_ctx *ctx,
WOLFSSL_CTX **ctx_c, WOLFSSL_CTX **ctx_s, WOLFSSL **ssl_c, WOLFSSL **ssl_s,
method_provider method_c, method_provider method_s,
byte *caCert, int caCertSz, byte *serverCert, int serverCertSz,
byte *serverKey, int serverKeySz);
static WC_INLINE int test_memio_write_cb(WOLFSSL *ssl, char *data, int sz,
void *ctx)
@@ -273,18 +279,32 @@ int test_memio_do_handshake(WOLFSSL *ssl_c, WOLFSSL *ssl_s,
return 0;
}
int test_memio_setup(struct test_memio_ctx *ctx,
int test_memio_setup_ex(struct test_memio_ctx *ctx,
WOLFSSL_CTX **ctx_c, WOLFSSL_CTX **ctx_s, WOLFSSL **ssl_c, WOLFSSL **ssl_s,
method_provider method_c, method_provider method_s)
method_provider method_c, method_provider method_s,
byte *caCert, int caCertSz, byte *serverCert, int serverCertSz,
byte *serverKey, int serverKeySz)
{
int ret;
(void)caCert;
(void)caCertSz;
(void)serverCert;
(void)serverCertSz;
(void)serverKey;
(void)serverKeySz;
if (ctx_c != NULL && *ctx_c == NULL) {
*ctx_c = wolfSSL_CTX_new(method_c());
if (*ctx_c == NULL)
return -1;
#ifndef NO_CERTS
ret = wolfSSL_CTX_load_verify_locations(*ctx_c, caCertFile, 0);
if (caCert == NULL) {
ret = wolfSSL_CTX_load_verify_locations(*ctx_c, caCertFile, 0);
}
else {
ret = wolfSSL_CTX_load_verify_buffer(*ctx_c, caCert, (long)caCertSz,
WOLFSSL_FILETYPE_ASN1);
}
if (ret != WOLFSSL_SUCCESS)
return -1;
#endif /* NO_CERTS */
@@ -302,15 +322,28 @@ int test_memio_setup(struct test_memio_ctx *ctx,
if (*ctx_s == NULL)
return -1;
#ifndef NO_CERTS
ret = wolfSSL_CTX_use_PrivateKey_file(*ctx_s, svrKeyFile,
WOLFSSL_FILETYPE_PEM);
if (serverKey == NULL) {
ret = wolfSSL_CTX_use_PrivateKey_file(*ctx_s, svrKeyFile,
WOLFSSL_FILETYPE_PEM);
}
else {
ret = wolfSSL_CTX_use_PrivateKey_buffer(*ctx_s, serverKey,
(long)serverKeySz, WOLFSSL_FILETYPE_ASN1);
}
if (ret != WOLFSSL_SUCCESS)
return- -1;
ret = wolfSSL_CTX_use_certificate_file(*ctx_s, svrCertFile,
WOLFSSL_FILETYPE_PEM);
if (serverCert == NULL) {
ret = wolfSSL_CTX_use_certificate_file(*ctx_s, svrCertFile,
WOLFSSL_FILETYPE_PEM);
}
else {
ret = wolfSSL_CTX_use_certificate_chain_buffer_format(*ctx_s,
serverCert, (long)serverCertSz, WOLFSSL_FILETYPE_ASN1);
}
if (ret != WOLFSSL_SUCCESS)
return -1;
#endif
#endif /* NO_CERTS */
wolfSSL_SetIORecv(*ctx_s, test_memio_read_cb);
wolfSSL_SetIOSend(*ctx_s, test_memio_write_cb);
if (ctx->s_ciphers != NULL) {
@@ -340,6 +373,14 @@ int test_memio_setup(struct test_memio_ctx *ctx,
return 0;
}
int test_memio_setup(struct test_memio_ctx *ctx,
WOLFSSL_CTX **ctx_c, WOLFSSL_CTX **ctx_s, WOLFSSL **ssl_c, WOLFSSL **ssl_s,
method_provider method_c, method_provider method_s)
{
return test_memio_setup_ex(ctx, ctx_c, ctx_s, ssl_c, ssl_s, method_c,
method_s, NULL, 0, NULL, 0, NULL, 0);
}
#endif
#if !defined(SINGLE_THREADED) && defined(WOLFSSL_COND)

View File

@@ -16432,6 +16432,7 @@ static int ConfirmSignature(SignatureCtx* sigCtx,
#if defined(HAVE_FALCON)
case FALCON_LEVEL1k:
{
word32 idx = 0;
sigCtx->verify = 0;
sigCtx->key.falcon =
(falcon_key*)XMALLOC(sizeof(falcon_key),
@@ -16447,8 +16448,8 @@ static int ConfirmSignature(SignatureCtx* sigCtx,
< 0) {
goto exit_cs;
}
if ((ret = wc_falcon_import_public(key, keySz,
sigCtx->key.falcon)) < 0) {
if ((ret = wc_Falcon_PublicKeyDecode(key, &idx,
sigCtx->key.falcon, keySz)) < 0) {
WOLFSSL_MSG("ASN Key import error Falcon Level 1");
WOLFSSL_ERROR_VERBOSE(ret);
goto exit_cs;
@@ -16457,6 +16458,7 @@ static int ConfirmSignature(SignatureCtx* sigCtx,
}
case FALCON_LEVEL5k:
{
word32 idx = 0;
sigCtx->verify = 0;
sigCtx->key.falcon =
(falcon_key*)XMALLOC(sizeof(falcon_key),
@@ -16472,8 +16474,8 @@ static int ConfirmSignature(SignatureCtx* sigCtx,
< 0) {
goto exit_cs;
}
if ((ret = wc_falcon_import_public(key, keySz,
sigCtx->key.falcon)) < 0) {
if ((ret = wc_Falcon_PublicKeyDecode(key, &idx,
sigCtx->key.falcon, keySz)) < 0) {
WOLFSSL_MSG("ASN Key import error Falcon Level 5");
WOLFSSL_ERROR_VERBOSE(ret);
goto exit_cs;
@@ -16484,6 +16486,7 @@ static int ConfirmSignature(SignatureCtx* sigCtx,
#if defined(HAVE_DILITHIUM)
case DILITHIUM_LEVEL2k:
{
word32 idx = 0;
sigCtx->verify = 0;
sigCtx->key.dilithium =
(dilithium_key*)XMALLOC(sizeof(dilithium_key),
@@ -16500,8 +16503,8 @@ static int ConfirmSignature(SignatureCtx* sigCtx,
< 0) {
goto exit_cs;
}
if ((ret = wc_dilithium_import_public(key, keySz,
sigCtx->key.dilithium)) < 0) {
if ((ret = wc_Dilithium_PublicKeyDecode(key, &idx,
sigCtx->key.dilithium, keySz)) < 0) {
WOLFSSL_MSG("ASN Key import error Dilithium Level 2");
goto exit_cs;
}
@@ -16509,6 +16512,7 @@ static int ConfirmSignature(SignatureCtx* sigCtx,
}
case DILITHIUM_LEVEL3k:
{
word32 idx = 0;
sigCtx->verify = 0;
sigCtx->key.dilithium =
(dilithium_key*)XMALLOC(sizeof(dilithium_key),
@@ -16525,15 +16529,16 @@ static int ConfirmSignature(SignatureCtx* sigCtx,
< 0) {
goto exit_cs;
}
if ((ret = wc_dilithium_import_public(key, keySz,
sigCtx->key.dilithium)) < 0) {
WOLFSSL_MSG("ASN Key import error Dilithium Level 5");
if ((ret = wc_Dilithium_PublicKeyDecode(key, &idx,
sigCtx->key.dilithium, keySz)) < 0) {
WOLFSSL_MSG("ASN Key import error Dilithium Level 3");
goto exit_cs;
}
break;
}
case DILITHIUM_LEVEL5k:
{
word32 idx = 0;
sigCtx->verify = 0;
sigCtx->key.dilithium =
(dilithium_key*)XMALLOC(sizeof(dilithium_key),
@@ -16550,8 +16555,8 @@ static int ConfirmSignature(SignatureCtx* sigCtx,
< 0) {
goto exit_cs;
}
if ((ret = wc_dilithium_import_public(key, keySz,
sigCtx->key.dilithium)) < 0) {
if ((ret = wc_Dilithium_PublicKeyDecode(key, &idx,
sigCtx->key.dilithium, keySz)) < 0) {
WOLFSSL_MSG("ASN Key import error Dilithium Level 5");
goto exit_cs;
}
@@ -16561,6 +16566,7 @@ static int ConfirmSignature(SignatureCtx* sigCtx,
#if defined(HAVE_SPHINCS)
case SPHINCS_FAST_LEVEL1k:
{
word32 idx = 0;
sigCtx->verify = 0;
sigCtx->key.sphincs =
(sphincs_key*)XMALLOC(sizeof(sphincs_key),
@@ -16577,8 +16583,8 @@ static int ConfirmSignature(SignatureCtx* sigCtx,
< 0) {
goto exit_cs;
}
if ((ret = wc_sphincs_import_public(key, keySz,
sigCtx->key.sphincs)) < 0) {
if ((ret = wc_Sphincs_PublicKeyDecode(key, &idx,
sigCtx->key.sphincs, keySz)) < 0) {
WOLFSSL_MSG("ASN Key import err: Sphincs-fast Level1");
goto exit_cs;
}
@@ -16586,6 +16592,7 @@ static int ConfirmSignature(SignatureCtx* sigCtx,
}
case SPHINCS_FAST_LEVEL3k:
{
word32 idx = 0;
sigCtx->verify = 0;
sigCtx->key.sphincs =
(sphincs_key*)XMALLOC(sizeof(sphincs_key),
@@ -16602,8 +16609,8 @@ static int ConfirmSignature(SignatureCtx* sigCtx,
< 0) {
goto exit_cs;
}
if ((ret = wc_sphincs_import_public(key, keySz,
sigCtx->key.sphincs)) < 0) {
if ((ret = wc_Sphincs_PublicKeyDecode(key, &idx,
sigCtx->key.sphincs, keySz)) < 0) {
WOLFSSL_MSG("ASN Key import err: Sphincs-fast Level3");
goto exit_cs;
}
@@ -16611,6 +16618,7 @@ static int ConfirmSignature(SignatureCtx* sigCtx,
}
case SPHINCS_FAST_LEVEL5k:
{
word32 idx = 0;
sigCtx->verify = 0;
sigCtx->key.sphincs =
(sphincs_key*)XMALLOC(sizeof(sphincs_key),
@@ -16627,16 +16635,16 @@ static int ConfirmSignature(SignatureCtx* sigCtx,
< 0) {
goto exit_cs;
}
if ((ret = wc_sphincs_import_public(key, keySz,
sigCtx->key.sphincs)) < 0) {
if ((ret = wc_Sphincs_PublicKeyDecode(key, &idx,
sigCtx->key.sphincs, keySz)) < 0) {
WOLFSSL_MSG("ASN Key import err: Sphincs-fast Level5");
goto exit_cs;
}
break;
}
case SPHINCS_SMALL_LEVEL1k:
{
word32 idx = 0;
sigCtx->verify = 0;
sigCtx->key.sphincs =
(sphincs_key*)XMALLOC(sizeof(sphincs_key),
@@ -16653,8 +16661,8 @@ static int ConfirmSignature(SignatureCtx* sigCtx,
< 0) {
goto exit_cs;
}
if ((ret = wc_sphincs_import_public(key, keySz,
sigCtx->key.sphincs)) < 0) {
if ((ret = wc_Sphincs_PublicKeyDecode(key, &idx,
sigCtx->key.sphincs, keySz)) < 0) {
WOLFSSL_MSG("ASN Key import err: Sphincs-fast Level1");
goto exit_cs;
}
@@ -16662,6 +16670,7 @@ static int ConfirmSignature(SignatureCtx* sigCtx,
}
case SPHINCS_SMALL_LEVEL3k:
{
word32 idx = 0;
sigCtx->verify = 0;
sigCtx->key.sphincs =
(sphincs_key*)XMALLOC(sizeof(sphincs_key),
@@ -16678,8 +16687,8 @@ static int ConfirmSignature(SignatureCtx* sigCtx,
< 0) {
goto exit_cs;
}
if ((ret = wc_sphincs_import_public(key, keySz,
sigCtx->key.sphincs)) < 0) {
if ((ret = wc_Sphincs_PublicKeyDecode(key, &idx,
sigCtx->key.sphincs, keySz)) < 0) {
WOLFSSL_MSG("ASN Key import err: Sphincs-fast Level3");
goto exit_cs;
}
@@ -16687,6 +16696,7 @@ static int ConfirmSignature(SignatureCtx* sigCtx,
}
case SPHINCS_SMALL_LEVEL5k:
{
word32 idx = 0;
sigCtx->verify = 0;
sigCtx->key.sphincs =
(sphincs_key*)XMALLOC(sizeof(sphincs_key),
@@ -16703,8 +16713,8 @@ static int ConfirmSignature(SignatureCtx* sigCtx,
< 0) {
goto exit_cs;
}
if ((ret = wc_sphincs_import_public(key, keySz,
sigCtx->key.sphincs)) < 0) {
if ((ret = wc_Sphincs_PublicKeyDecode(key, &idx,
sigCtx->key.sphincs, keySz)) < 0) {
WOLFSSL_MSG("ASN Key import err: Sphincs-fast Level5");
goto exit_cs;
}
@@ -17215,6 +17225,41 @@ exit_cs:
return ret;
}
#ifdef WOLFSSL_DUAL_ALG_CERTS
int wc_ConfirmAltSignature(
const byte* buf, word32 bufSz,
const byte* key, word32 keySz, word32 keyOID,
const byte* sig, word32 sigSz, word32 sigOID,
void *heap)
{
int ret = 0;
#ifdef WOLFSSL_SMALL_STACK
SignatureCtx* sigCtx = (SignatureCtx*)XMALLOC(sizeof(*sigCtx), heap,
DYNAMIC_TYPE_SIGNATURE);
if (sigCtx == NULL) {
ret = MEMORY_E;
}
#else
SignatureCtx sigCtx[1];
(void)heap;
#endif
if (ret == 0) {
InitSignatureCtx(sigCtx, heap, INVALID_DEVID);
ret = ConfirmSignature(sigCtx, buf, bufSz, key, keySz,
keyOID, sig, sigSz, sigOID, NULL, 0, NULL);
FreeSignatureCtx(sigCtx);
}
#ifdef WOLFSSL_SMALL_STACK
if (sigCtx != NULL)
XFREE(sigCtx, heap, DYNAMIC_TYPE_SIGNATURE);
#endif
return ret;
}
#endif /* WOLFSSL_DUAL_ALG_CERTS */
#ifndef IGNORE_NAME_CONSTRAINTS
@@ -20322,6 +20367,161 @@ static int DecodeSubjInfoAcc(const byte* input, word32 sz, DecodedCert* cert)
}
#endif /* WOLFSSL_SUBJ_INFO_ACC */
#ifdef WOLFSSL_DUAL_ALG_CERTS
/* The subject alternative public key is an extension that holds the same thing
* as a subject public key. */
static const ASNItem subjAltPubKeyInfoASN[] = {
/* subjectPublicKeyInfo SubjectPublicKeyInfo */
/* ALT_SPUBKEYINFO_SEQ */ { 0, ASN_SEQUENCE, 1, 1, 0 },
/* algorithm AlgorithmIdentifier */
/* AlgorithmIdentifier ::= SEQUENCE */
/* ALT_SPUBKEYINFO_ALGO_SEQ */ { 1, ASN_SEQUENCE, 1, 1, 0 },
/* Algorithm OBJECT IDENTIFIER */
/* ALT_SPUBKEYINFO_ALGO_OID */ { 2, ASN_OBJECT_ID, 0, 0, 0 },
/* parameters ANY defined by algorithm OPTIONAL */
/* ALT_SPUBKEYINFO_ALGO_NULL */ { 2, ASN_TAG_NULL, 0, 0, 1 },
/* ALT_SPUBKEYINFO_ALGO_CURVEID */ { 2, ASN_OBJECT_ID, 0, 0, 1 },
#ifdef WC_RSA_PSS
/* ALT_SPUBKEYINFO_ALGO_P_SEQ */ { 2, ASN_SEQUENCE, 1, 0, 1 },
#endif
/* subjectPublicKey BIT STRING */
/* ALT_SPUBKEYINFO_PUBKEY */ { 1, ASN_BIT_STRING, 0, 0, 0 }
};
#define subjAltPubKeyInfoASN_Length (sizeof(subjAltPubKeyInfoASN) / \
sizeof(ASNItem))
enum {
ALT_SPUBKEYINFO_SEQ = 0,
ALT_SPUBKEYINFO_ALGO_SEQ,
ALT_SPUBKEYINFO_ALGO_OID,
ALT_SPUBKEYINFO_ALGO_NULL,
ALT_SPUBKEYINFO_ALGO_CURVEID,
#ifdef WC_RSA_PSS
ALT_SPUBKEYINFO_ALGO_P_SEQ,
#endif
ALT_SPUBKEYINFO_PUBKEY
};
static int DecodeSubjAltPubKeyInfo(const byte* input, int sz, DecodedCert* cert)
{
int ret = 0;
word32 idx = 0;
DECL_ASNGETDATA(dataASN, subjAltPubKeyInfoASN_Length);
WOLFSSL_ENTER("DecodeSubjAltPubKeyInfo");
if (ret == 0) {
CALLOC_ASNGETDATA(dataASN, subjAltPubKeyInfoASN_Length, ret,
cert->heap);
(void)cert;
}
if (ret == 0) {
GetASN_OID(&dataASN[ALT_SPUBKEYINFO_ALGO_OID], oidKeyType);
GetASN_OID(&dataASN[ALT_SPUBKEYINFO_ALGO_CURVEID], oidCurveType);
ret = GetASN_Items(subjAltPubKeyInfoASN, dataASN,
subjAltPubKeyInfoASN_Length, 1, input, &idx,
(word32)sz);
}
if (ret == 0) {
/* dataASN[ALT_SPUBKEYINFO_SEQ].data.u8 */
cert->sapkiDer = (byte *)input;
/* dataASN[ALT_SPUBKEYINFO_SEQ].length */
cert->sapkiLen = sz;
cert->sapkiOID = dataASN[ALT_SPUBKEYINFO_ALGO_OID].data.oid.sum;
}
FREE_ASNGETDATA(dataASN, cert->heap);
WOLFSSL_LEAVE("DecodeSubjAltPubKeyInfo", ret);
return ret;
}
/* The alternative signature algorithm extension holds the same thing as a
* as a signature algorithm identifier. */
static const ASNItem altSigAlgASN[] = {
/* AltSigAlg AlgorithmIdentifier */
/* AlgorithmIdentifier ::= SEQUENCE */
/* ALTSIG_ALGOID_SEQ */ { 0, ASN_SEQUENCE, 1, 1, 0 },
/* Algorithm OBJECT IDENTIFIER */
/* ALTSIG_ALGOID_OID */ { 1, ASN_OBJECT_ID, 0, 0, 0 },
/* parameters ANY defined by algorithm OPTIONAL */
/* ALTSIG_ALGOID_PARAMS_NULL */ { 1, ASN_TAG_NULL, 0, 0, 1 },
#ifdef WC_RSA_PSS
/* ALTSIG_ALGOID_PARAMS */ { 1, ASN_SEQUENCE, 1, 0, 1 },
#endif
};
#define altSigAlgASN_Length (sizeof(altSigAlgASN) / sizeof(ASNItem))
enum {
ALTSIG_ALGOID_SEQ = 0,
ALTSIG_ALGOID_OID,
ALTSIG_ALGOID_PARAMS_NULL,
#ifdef WC_RSA_PSS
ALTSIG_ALGOID_PARAMS,
#endif
};
static int DecodeAltSigAlg(const byte* input, int sz, DecodedCert* cert)
{
int ret = 0;
word32 idx = 0;
DECL_ASNGETDATA(dataASN, altSigAlgASN_Length);
WOLFSSL_ENTER("DecodeAltSigAlg");
if (ret == 0) {
CALLOC_ASNGETDATA(dataASN, altSigAlgASN_Length, ret, cert->heap);
(void)cert;
}
if (ret == 0) {
GetASN_OID(&dataASN[ALTSIG_ALGOID_OID], oidSigType);
ret = GetASN_Items(altSigAlgASN, dataASN,
altSigAlgASN_Length, 1, input, &idx,
(word32)sz);
}
if (ret == 0) {
cert->altSigAlgDer = dataASN[ALTSIG_ALGOID_SEQ].data.u8;
cert->altSigAlgLen = dataASN[ALTSIG_ALGOID_SEQ].length;
cert->altSigAlgOID = dataASN[ALTSIG_ALGOID_OID].data.oid.sum;
}
FREE_ASNGETDATA(dataASN, cert->heap);
WOLFSSL_LEAVE("DecodeAltSigAlg", ret);
return ret;
}
/* The alternative signature value extension holds an ASN.1 bitstring just
* like a traditional signature in the certificate. */
static int DecodeAltSigVal(const byte* input, int sz, DecodedCert* cert)
{
(void)cert;
int ret = 0;
word32 idx = 0;
int len = 0;
WOLFSSL_ENTER("DecodeAltSigVal");
if (ret == 0) {
ret = CheckBitString(input, &idx, &len, sz, 1, NULL);
}
if (ret == 0) {
cert->altSigValDer = (byte *)input + idx;
cert->altSigValLen = len;
}
WOLFSSL_LEAVE("DecodeAltSigVal", ret);
return ret;
}
#endif /* WOLFSSL_DUAL_ALG_CERTS */
/* Macro to check if bit is set, if not sets and return success.
Otherwise returns failure */
/* Macro required here because bit-field operation */
@@ -20569,6 +20769,23 @@ static int DecodeExtensionType(const byte* input, word32 length, word32 oid,
return ASN_PARSE_E;
break;
#endif
#ifdef WOLFSSL_DUAL_ALG_CERTS
case SUBJ_ALT_PUB_KEY_INFO_OID:
VERIFY_AND_SET_OID(cert->extSapkiSet);
if (DecodeSubjAltPubKeyInfo(&input[idx], length, cert) < 0)
return ASN_PARSE_E;
break;
case ALT_SIG_ALG_OID:
VERIFY_AND_SET_OID(cert->extAltSigAlgSet);
if (DecodeAltSigAlg(&input[idx], length, cert) < 0)
return ASN_PARSE_E;
break;
case ALT_SIG_VAL_OID:
VERIFY_AND_SET_OID(cert->extAltSigValSet);
if (DecodeAltSigVal(&input[idx], length, cert) < 0)
return ASN_PARSE_E;
break;
#endif /* WOLFSSL_DUAL_ALG_CERTS */
default:
if (isUnknownExt != NULL)
*isUnknownExt = 1;
@@ -23688,6 +23905,9 @@ int wc_PemGetHeaderFooter(int type, const char** header, const char** footer)
#endif
case RSA_TYPE:
case PRIVATEKEY_TYPE:
#ifdef WOLFSSL_DUAL_ALG_CERTS
case ALT_PRIVATEKEY_TYPE:
#endif
if (header) *header = BEGIN_RSA_PRIV;
if (footer) *footer = END_RSA_PRIV;
ret = 0;
@@ -24195,7 +24415,11 @@ int PemToDer(const unsigned char* buff, long longSz, int type,
break;
}
if (type == PRIVATEKEY_TYPE) {
if (type == PRIVATEKEY_TYPE
#ifdef WOLFSSL_DUAL_ALG_CERTS
|| type == ALT_PRIVATEKEY_TYPE
#endif
) {
if (header == BEGIN_RSA_PRIV) {
header = BEGIN_PRIV_KEY;
footer = END_PRIV_KEY;
@@ -24268,7 +24492,11 @@ int PemToDer(const unsigned char* buff, long longSz, int type,
if (!headerEnd) {
#ifdef OPENSSL_EXTRA
if (type == PRIVATEKEY_TYPE) {
if (type == PRIVATEKEY_TYPE
#ifdef WOLFSSL_DUAL_ALG_CERTS
|| type == ALT_PRIVATEKEY_TYPE
#endif
) {
/* see if there is a -----BEGIN * PRIVATE KEY----- header */
headerEnd = XSTRNSTR((char*)buff, PRIV_KEY_SUFFIX, sz);
if (headerEnd) {
@@ -24347,7 +24575,11 @@ int PemToDer(const unsigned char* buff, long longSz, int type,
if (keyFormat) {
/* keyFormat is Key_Sum enum */
if (type == PRIVATEKEY_TYPE) {
if (type == PRIVATEKEY_TYPE
#ifdef WOLFSSL_DUAL_ALG_CERTS
|| type == ALT_PRIVATEKEY_TYPE
#endif
) {
#ifndef NO_RSA
if (header == BEGIN_RSA_PRIV)
*keyFormat = RSAk;
@@ -27627,6 +27859,17 @@ static const ASNItem static_certExtsASN[] = {
/* CRLINFO_SEQ */ { 0, ASN_SEQUENCE, 1, 1, 0 },
/* CRLINFO_OID */ { 1, ASN_OBJECT_ID, 0, 0, 0 },
/* CRLINFO_STR */ { 1, ASN_OCTET_STRING, 0, 0, 0 },
#ifdef WOLFSSL_DUAL_ALG_CERTS
/* SAPKI_SEQ */ { 0, ASN_SEQUENCE, 1, 1, 0 },
/* SAPKI_OID */ { 1, ASN_OBJECT_ID, 0, 0, 0 },
/* SAPKI_STR */ { 1, ASN_OCTET_STRING, 0, 0, 0 },
/* ALTSIGALG_SEQ */ { 0, ASN_SEQUENCE, 1, 1, 0 },
/* ALTSIGALG_OID */ { 1, ASN_OBJECT_ID, 0, 0, 0 },
/* ALTSIGALG_STR */ { 1, ASN_OCTET_STRING, 0, 0, 0 },
/* ALTSIGVAL_SEQ */ { 0, ASN_SEQUENCE, 1, 1, 0 },
/* ALTSIGVAL_OID */ { 1, ASN_OBJECT_ID, 0, 0, 0 },
/* ALTSIGVAL_STR */ { 1, ASN_OCTET_STRING, 0, 0, 0 },
#endif /* WOLFSSL_DUAL_ALG_CERTS */
/* CUSTOM_SEQ */ { 0, ASN_SEQUENCE, 1, 1, 0 },
/* CUSTOM_OID */ { 1, ASN_OBJECT_ID, 0, 0, 0 },
/* CUSTOM_STR */ { 1, ASN_OCTET_STRING, 0, 0, 0 },
@@ -27670,6 +27913,17 @@ enum {
CERTEXTSASN_IDX_CRLINFO_SEQ,
CERTEXTSASN_IDX_CRLINFO_OID,
CERTEXTSASN_IDX_CRLINFO_STR,
#ifdef WOLFSSL_DUAL_ALG_CERTS
CERTEXTSASN_IDX_SAPKI_SEQ,
CERTEXTSASN_IDX_SAPKI_OID,
CERTEXTSASN_IDX_SAPKI_STR,
CERTEXTSASN_IDX_ALTSIGALG_SEQ,
CERTEXTSASN_IDX_ALTSIGALG_OID,
CERTEXTSASN_IDX_ALTSIGALG_STR,
CERTEXTSASN_IDX_ALTSIGVAL_SEQ,
CERTEXTSASN_IDX_ALTSIGVAL_OID,
CERTEXTSASN_IDX_ALTSIGVAL_STR,
#endif /* WOLFSSL_DUAL_ALG_CERTS */
CERTEXTSASN_IDX_CUSTOM_SEQ,
CERTEXTSASN_IDX_CUSTOM_OID,
CERTEXTSASN_IDX_CUSTOM_STR,
@@ -27708,7 +27962,12 @@ static int EncodeExtensions(Cert* cert, byte* output, word32 maxSz,
static const byte nsCertOID[] = { 0x60, 0x86, 0x48, 0x01,
0x86, 0xF8, 0x42, 0x01, 0x01 };
static const byte crlInfoOID[] = { 0x55, 0x1D, 0x1F };
#endif
#ifdef WOLFSSL_DUAL_ALG_CERTS
static const byte sapkiOID[] = { 0x55, 0x1d, 0x48 };
static const byte altSigAlgOID[] = { 0x55, 0x1d, 0x49 };
static const byte altSigValOID[] = { 0x55, 0x1d, 0x4a };
#endif /* WOLFSSL_DUAL_ALG_CERTS */
#endif /* WOLFSSL_CERT_EXT */
#ifdef WOLFSSL_SMALL_STACK
#if defined(WOLFSSL_CUSTOM_OID) && defined(WOLFSSL_CERT_EXT)
@@ -27940,6 +28199,47 @@ static int EncodeExtensions(Cert* cert, byte* output, word32 maxSz,
CERTEXTSASN_IDX_CRLINFO_STR);
}
#ifdef WOLFSSL_DUAL_ALG_CERTS
if (cert->sapkiDer != NULL) {
/* Set subject alternative public key info OID and data. */
SetASN_Buffer(&dataASN[CERTEXTSASN_IDX_SAPKI_OID], sapkiOID,
sizeof(sapkiOID));
SetASN_Buffer(&dataASN[CERTEXTSASN_IDX_SAPKI_STR], cert->sapkiDer,
cert->sapkiLen);
}
else {
/* Don't write out subject alternative public key info. */
SetASNItem_NoOut(dataASN, CERTEXTSASN_IDX_SAPKI_SEQ,
CERTEXTSASN_IDX_SAPKI_STR);
}
if (cert->altSigAlgDer != NULL) {
/* Set alternative signature algorithm OID and data. */
SetASN_Buffer(&dataASN[CERTEXTSASN_IDX_ALTSIGALG_OID], altSigAlgOID,
sizeof(altSigAlgOID));
SetASN_Buffer(&dataASN[CERTEXTSASN_IDX_ALTSIGALG_STR],
cert->altSigAlgDer, cert->altSigAlgLen);
}
else {
/* Don't write out alternative signature algorithm. */
SetASNItem_NoOut(dataASN, CERTEXTSASN_IDX_ALTSIGALG_SEQ,
CERTEXTSASN_IDX_ALTSIGALG_STR);
}
if (cert->altSigValDer != NULL) {
/* Set alternative signature value OID and data. */
SetASN_Buffer(&dataASN[CERTEXTSASN_IDX_ALTSIGVAL_OID], altSigValOID,
sizeof(altSigValOID));
SetASN_Buffer(&dataASN[CERTEXTSASN_IDX_ALTSIGVAL_STR],
cert->altSigValDer, cert->altSigValLen);
}
else {
/* Don't write out alternative signature value. */
SetASNItem_NoOut(dataASN, CERTEXTSASN_IDX_ALTSIGVAL_SEQ,
CERTEXTSASN_IDX_ALTSIGVAL_STR);
}
#endif /* WOLFSSL_DUAL_ALG_CERTS */
#if defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_CUSTOM_OID)
/* encode a custom oid and value */
if (cert->extCustom.oidSz > 0) {
@@ -29280,8 +29580,24 @@ static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz,
(byte)cert->version);
SetASN_Buffer(&dataASN[X509CERTASN_IDX_TBS_SERIAL], cert->serial,
(word32)cert->serialSz);
SetASN_OID(&dataASN[X509CERTASN_IDX_TBS_ALGOID_OID],
(word32)cert->sigType, oidSigType);
#ifdef WOLFSSL_DUAL_ALG_CERTS
if (cert->sigType == 0) {
/* sigOID being 0 indicates preTBS. Do not encode signature. */
dataASN[X509CERTASN_IDX_TBS_ALGOID_SEQ].noOut = 1;
dataASN[X509CERTASN_IDX_TBS_ALGOID_OID].noOut = 1;
dataASN[X509CERTASN_IDX_TBS_ALGOID_PARAMS_NULL].noOut = 1;
#ifdef WC_RSA_PSS
dataASN[X509CERTASN_IDX_TBS_ALGOID_PARAMS].noOut = 1;
#endif
}
else
#endif /* WOLFSSL_DUAL_ALG_CERTS */
{
SetASN_OID(&dataASN[X509CERTASN_IDX_TBS_ALGOID_OID],
(word32)cert->sigType, oidSigType);
}
if (IsSigAlgoECC((word32)cert->sigType)) {
/* No NULL tagged item with ECDSA and EdDSA signature OIDs. */
dataASN[X509CERTASN_IDX_TBS_ALGOID_PARAMS_NULL].noOut = 1;
@@ -30560,6 +30876,126 @@ static int SignCert(int requestSz, int sType, byte* buf, word32 buffSz,
return sigSz;
}
#ifdef WOLFSSL_DUAL_ALG_CERTS
int wc_MakeSigWithBitStr(byte *sig, int sigSz, int sType, byte* buf,
word32 bufSz, int keyType, void* key, WC_RNG* rng)
{
RsaKey* rsaKey = NULL;
ecc_key* eccKey = NULL;
ed25519_key* ed25519Key = NULL;
ed448_key* ed448Key = NULL;
falcon_key* falconKey = NULL;
dilithium_key* dilithiumKey = NULL;
sphincs_key* sphincsKey = NULL;
int ret = 0;
int headerSz;
void* heap = NULL;
CertSignCtx certSignCtx_lcl;
CertSignCtx* certSignCtx = &certSignCtx_lcl;
if ((sig == NULL) || (sigSz <= 0)) {
return BAD_FUNC_ARG;
}
XMEMSET(certSignCtx, 0, sizeof(*certSignCtx));
switch (keyType)
{
case RSA_TYPE:
rsaKey = (RsaKey*)key;
break;
case ECC_TYPE:
eccKey = (ecc_key*)key;
break;
case ED25519_TYPE:
ed25519Key = (ed25519_key*)key;
break;
case ED448_TYPE:
ed448Key = (ed448_key*)key;
break;
case FALCON_LEVEL1_TYPE:
case FALCON_LEVEL5_TYPE:
falconKey = (falcon_key*)key;
break;
case DILITHIUM_LEVEL2_TYPE:
case DILITHIUM_LEVEL3_TYPE:
case DILITHIUM_LEVEL5_TYPE:
dilithiumKey = (dilithium_key*)key;
break;
case SPHINCS_FAST_LEVEL1_TYPE:
case SPHINCS_FAST_LEVEL3_TYPE:
case SPHINCS_FAST_LEVEL5_TYPE:
case SPHINCS_SMALL_LEVEL1_TYPE:
case SPHINCS_SMALL_LEVEL3_TYPE:
case SPHINCS_SMALL_LEVEL5_TYPE:
sphincsKey = (sphincs_key*)key;
break;
default:
return BAD_FUNC_ARG;
}
/* locate ctx */
if (rsaKey) {
#ifndef NO_RSA
#ifdef WOLFSSL_ASYNC_CRYPT
certSignCtx = &rsaKey->certSignCtx;
#endif
heap = rsaKey->heap;
#else
return NOT_COMPILED_IN;
#endif /* NO_RSA */
}
else if (eccKey) {
#ifdef HAVE_ECC
#ifdef WOLFSSL_ASYNC_CRYPT
certSignCtx = &eccKey->certSignCtx;
#endif
heap = eccKey->heap;
#else
return NOT_COMPILED_IN;
#endif /* HAVE_ECC */
}
if (certSignCtx->sig == NULL) {
certSignCtx->sig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, heap,
DYNAMIC_TYPE_TMP_BUFFER);
if (certSignCtx->sig == NULL)
return MEMORY_E;
}
ret = MakeSignature(certSignCtx, buf, (word32)bufSz, certSignCtx->sig,
MAX_ENCODED_SIG_SZ, rsaKey, eccKey, ed25519Key, ed448Key,
falconKey, dilithiumKey, sphincsKey, rng, (word32)sType, heap);
#ifdef WOLFSSL_ASYNC_CRYPT
if (ret == WC_PENDING_E) {
/* Not free'ing certSignCtx->sig here because it could still be in use
* with async operations. */
return ret;
}
#endif
if (ret <= 0) {
return ret;
}
headerSz = SetBitString(ret, 0, NULL);
if (headerSz + ret > sigSz) {
ret = BUFFER_E;
}
if (ret > 0) {
sig += SetBitString(ret, 0, sig);
XMEMCPY(sig, certSignCtx->sig, ret);
ret += headerSz;
}
XFREE(certSignCtx->sig, heap, DYNAMIC_TYPE_TMP_BUFFER);
certSignCtx->sig = NULL;
return ret;
}
#endif /* WOLFSSL_DUAL_ALG_CERTS */
int wc_SignCert_ex(int requestSz, int sType, byte* buf, word32 buffSz,
int keyType, void* key, WC_RNG* rng)
{

View File

@@ -815,6 +815,11 @@ int wc_Dilithium_PublicKeyDecode(const byte* input, word32* inOutIdx,
return BAD_FUNC_ARG;
}
ret = wc_dilithium_import_public(input, inSz, key);
if (ret == 0) {
return 0;
}
if (key->level == 2) {
keytype = DILITHIUM_LEVEL2k;
}

View File

@@ -747,6 +747,11 @@ int wc_Falcon_PublicKeyDecode(const byte* input, word32* inOutIdx,
return BAD_FUNC_ARG;
}
ret = wc_falcon_import_public(input, inSz, key);
if (ret == 0) {
return 0;
}
if (key->level == 1) {
keytype = FALCON_LEVEL1k;
}

View File

@@ -896,6 +896,11 @@ int wc_Sphincs_PublicKeyDecode(const byte* input, word32* inOutIdx,
return BAD_FUNC_ARG;
}
ret = wc_sphincs_import_public(input, inSz, key);
if (ret == 0) {
return 0;
}
if ((key->level == 1) && (key->optim == FAST_VARIANT)) {
keytype = SPHINCS_FAST_LEVEL1k;
}

View File

@@ -1549,7 +1549,8 @@ enum Misc {
#endif
#endif
#ifdef HAVE_PQC
ENCRYPT_LEN = 4600, /* allow 4600 byte buffer for dilithium. */
ENCRYPT_LEN = 5120, /* Allow 5k byte buffer for dilithium and
* hybridization with other algs. */
#else
#ifndef NO_PSK
ENCRYPT_LEN = (ENCRYPT_BASE_BITS / 8) + MAX_PSK_ID_LEN + 2,
@@ -1797,6 +1798,8 @@ enum Misc {
#if defined(HAVE_PQC)
MAX_CERT_VERIFY_SZ = 6000, /* For Dilithium */
#elif defined(WOLFSSL_CERT_EXT)
MAX_CERT_VERIFY_SZ = 2048, /* For larger extensions */
#elif !defined(NO_RSA) && defined(WOLFSSL_MAX_RSA_BITS)
MAX_CERT_VERIFY_SZ = WOLFSSL_MAX_RSA_BITS / 8, /* max RSA bytes */
#elif defined(HAVE_ECC)
@@ -2172,6 +2175,9 @@ WOLFSSL_LOCAL int CreateDevPrivateKey(void** pkey, byte* data, word32 length,
void* heap, int devId);
#endif
WOLFSSL_LOCAL int DecodePrivateKey(WOLFSSL *ssl, word16* length);
#ifdef WOLFSSL_DUAL_ALG_CERTS
WOLFSSL_LOCAL int DecodeAltPrivateKey(WOLFSSL *ssl, word16* length);
#endif
#ifdef WOLF_PRIVATE_KEY_ID
WOLFSSL_LOCAL int GetPrivateKeySigSize(WOLFSSL* ssl);
#ifndef NO_ASN
@@ -2849,6 +2855,10 @@ typedef enum {
#ifdef WOLFSSL_QUIC
TLSX_KEY_QUIC_TP_PARAMS = 0x0039, /* RFC 9001, ch. 8.2 */
#endif
#ifdef WOLFSSL_DUAL_ALG_CERTS
TLSX_CKS = 0xff92, /* X9.146; ff indcates personal
* use and 92 is hex for 146. */
#endif
#endif
TLSX_RENEGOTIATION_INFO = 0xff01,
#ifdef WOLFSSL_QUIC
@@ -3376,8 +3386,11 @@ WOLFSSL_LOCAL int TLSX_KeyShare_Parse(WOLFSSL* ssl, const byte* input,
word16 length, byte msgType);
WOLFSSL_LOCAL int TLSX_KeyShare_Parse_ClientHello(const WOLFSSL* ssl,
const byte* input, word16 length, TLSX** extensions);
#ifdef WOLFSSL_DUAL_ALG_CERTS
WOLFSSL_LOCAL int TLSX_CKS_Parse(WOLFSSL* ssl, byte* input,
word16 length, TLSX** extensions);
WOLFSSL_LOCAL int TLSX_CKS_Set(WOLFSSL* ssl, TLSX** extensions);
#endif
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
enum PskDecryptReturn {
@@ -3558,6 +3571,12 @@ struct WOLFSSL_CTX {
byte privateKeyLabel:1;
int privateKeySz;
int privateKeyDevId;
#ifdef WOLFSSL_DUAL_ALG_CERTS
DerBuffer* altPrivateKey;
byte altPrivateKeyType;
int altPrivateKeySz;
#endif /* WOLFSSL_DUAL_ALG_CERTS */
#ifdef OPENSSL_ALL
WOLFSSL_EVP_PKEY* privateKeyPKey;
#endif
@@ -3934,6 +3953,10 @@ struct WOLFSSL_CTX {
#if defined(__APPLE__) && defined(WOLFSSL_SYS_CA_CERTS)
byte doAppleNativeCertValidationFlag:1;
#endif /* defined(__APPLE__) && defined(WOLFSSL_SYS_CA_CERTS) */
#ifdef WOLFSSL_DUAL_ALG_CERTS
byte *sigSpec;
word16 sigSpecSz;
#endif
};
WOLFSSL_LOCAL
@@ -4501,7 +4524,10 @@ typedef struct Buffers {
when got WANT_WRITE */
byte weOwnCert; /* SSL own cert flag */
byte weOwnCertChain; /* SSL own cert chain flag */
byte weOwnKey; /* SSL own key flag */
byte weOwnKey; /* SSL own key flag */
#ifdef WOLFSSL_DUAL_ALG_CERTS
byte weOwnAltKey; /* SSL own alt key flag */
#endif
byte weOwnDH; /* SSL own dh (p,g) flag */
#ifndef NO_DH
buffer serverDH_P; /* WOLFSSL_CTX owns, unless we own */
@@ -4518,6 +4544,11 @@ typedef struct Buffers {
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 */
#endif
DerBuffer* certChain; /* WOLFSSL_CTX owns, unless we own */
/* chain after self, in DER, with leading size for each cert */
#ifdef WOLFSSL_TLS13
@@ -5096,6 +5127,17 @@ struct WOLFSSL_X509 {
byte notBeforeData[CTC_DATE_SIZE];
byte notAfterData[CTC_DATE_SIZE];
#endif
#ifdef WOLFSSL_DUAL_ALG_CERTS
/* Subject Alternative Public Key Info */
byte *sapkiDer;
int sapkiLen;
/* Alternative Signature Algorithm */
byte *altSigAlgDer;
int altSigAlgLen;
/* Alternative Signature Value */
byte *altSigValDer;
int altSigValLen;
#endif /* WOLFSSL_DUAL_ALG_CERTS */
};
@@ -5462,6 +5504,11 @@ struct WOLFSSL {
* allocated from heap */
word32 hsType; /* Type of Handshake key (hsKey) */
WOLFSSL_CIPHER cipher;
#ifdef WOLFSSL_DUAL_ALG_CERTS
void* hsAltKey; /* Handshake key (dilithium, falcon)
* allocated from heap */
word32 hsAltType; /* Type of Handshake key (hsAltKey) */
#endif
#ifndef WOLFSSL_AEAD_ONLY
hmacfp hmac;
#endif
@@ -5883,7 +5930,12 @@ struct WOLFSSL {
#if defined(WOLFSSL_SNIFFER) && defined(WOLFSSL_SNIFFER_KEYLOGFILE)
SSLSnifferSecretCb snifferSecretCb;
#endif /* WOLFSSL_SNIFFER && WOLFSSL_SNIFFER_KEYLOGFILE */
#ifdef WOLFSSL_DUAL_ALG_CERTS
byte *sigSpec; /* This pointer never owns the memory. */
word16 sigSpecSz;
byte *peerSigSpec; /* This pointer always owns the memory. */
word16 peerSigSpecSz;
#endif
};
/*

View File

@@ -1056,8 +1056,11 @@ WOLFSSL_ABI WOLFSSL_API int wolfSSL_CTX_use_certificate_file(
WOLFSSL_CTX* ctx, const char* file, int format);
WOLFSSL_ABI WOLFSSL_API int wolfSSL_CTX_use_PrivateKey_file(
WOLFSSL_CTX* ctx, const char* file, int format);
#endif
#ifdef WOLFSSL_DUAL_ALG_CERTS
WOLFSSL_API int wolfSSL_CTX_use_AltPrivateKey_file(
WOLFSSL_CTX* ctx, const char* file, int format);
#endif /* WOLFSSL_DUAL_ALG_CERTS */
#endif /* !NO_FILESYSTEM && !NO_CERTS */
#ifndef NO_CERTS
#define WOLFSSL_LOAD_FLAG_NONE 0x00000000
@@ -4008,6 +4011,16 @@ WOLFSSL_API int wolfSSL_UseKeyShare(WOLFSSL* ssl, word16 group);
WOLFSSL_API int wolfSSL_NoKeyShares(WOLFSSL* ssl);
#endif
#ifdef WOLFSSL_DUAL_ALG_CERTS
#define WOLFSSL_CKS_SIGSPEC_NATIVE 0x0001
#define WOLFSSL_CKS_SIGSPEC_ALTERNATIVE 0x0002
#define WOLFSSL_CKS_SIGSPEC_BOTH 0x0003
#define WOLFSSL_CKS_SIGSPEC_EXTERNAL 0x0004
WOLFSSL_API int wolfSSL_UseCKS(WOLFSSL* ssl, byte *sigSpec, word16 sigSpecSz);
WOLFSSL_API int wolfSSL_CTX_UseCKS(WOLFSSL_CTX* ctx, byte *sigSpec,
word16 sigSpecSz);
#endif /* WOLFSSL_DUAL_ALG_CERTS */
/* Secure Renegotiation */
#if defined(HAVE_SECURE_RENEGOTIATION) || defined(HAVE_SERVER_RENEGOTIATION_INFO)

View File

@@ -932,7 +932,11 @@ enum Misc_ASN {
MIN_DATE_SIZE = 12,
MAX_DATE_SIZE = 32,
ASN_GEN_TIME_SZ = 15, /* 7 numbers * 2 + Zulu tag */
#ifndef NO_RSA
#ifdef HAVE_SPHINCS
MAX_ENCODED_SIG_SZ = 51200,
#elif defined(HAVE_PQC)
MAX_ENCODED_SIG_SZ = 5120;
#elif !defined(NO_RSA)
#ifdef WOLFSSL_HAPROXY
MAX_ENCODED_SIG_SZ = 1024, /* Supports 8192 bit keys */
#else
@@ -1221,7 +1225,12 @@ enum Extensions_Sum {
AKEY_PACKAGE_OID = 1048, /* 2.16.840.1.101.2.1.2.78.5
RFC 5958 - Asymmetric Key Packages */
FASCN_OID = 419, /* 2.16.840.1.101.3.6.6 Federal PKI Policy FASC-N */
UPN_OID = 265 /* 1.3.6.1.4.1.311.20.2.3 UPN */
UPN_OID = 265, /* 1.3.6.1.4.1.311.20.2.3 UPN */
#ifdef WOLFSSL_DUAL_ALG_CERTS
SUBJ_ALT_PUB_KEY_INFO_OID = 186, /* 2.5.29.72 subject alt public key info */
ALT_SIG_ALG_OID = 187, /* 2.5.29.73 alt sig alg */
ALT_SIG_VAL_OID = 188 /* 2.5.29.74 alt sig val */
#endif
};
enum CertificatePolicy_Sum {
@@ -1926,6 +1935,11 @@ struct DecodedCert {
#ifdef WOLFSSL_SUBJ_INFO_ACC
byte extSubjInfoAccSet : 1;
#endif
#ifdef WOLFSSL_DUAL_ALG_CERTS
byte extSapkiSet : 1;
byte extAltSigAlgSet : 1;
byte extAltSigValSet : 1;
#endif /* WOLFSSL_DUAL_ALG_CERTS */
#if defined(WOLFSSL_SEP) || defined(WOLFSSL_QT)
byte extCertPolicyCrit : 1;
#endif
@@ -1939,6 +1953,19 @@ struct DecodedCert {
&& defined(HAVE_OID_DECODING)
wc_UnknownExtCallback unknownExtCallback;
#endif
#ifdef WOLFSSL_DUAL_ALG_CERTS
/* Subject Alternative Public Key Info */
byte *sapkiDer;
int sapkiLen;
word32 sapkiOID;
/* Alternative Signature Algorithm */
byte *altSigAlgDer;
int altSigAlgLen;
word32 altSigAlgOID;
/* Alternative Signature Value */
byte *altSigValDer;
int altSigValLen;
#endif /* WOLFSSL_DUAL_ALG_CERTS */
};
#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
@@ -1988,6 +2015,13 @@ struct Signer {
#if defined(WOLFSSL_RENESAS_TSIP_TLS) || defined(WOLFSSL_RENESAS_FSPSM_TLS)
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;
#endif /* WOLFSSL_DUAL_ALG_CERTS */
Signer* next;
};
@@ -2098,6 +2132,13 @@ WOLFSSL_API int wc_CheckCertSigPubKey(const byte* cert, word32 certSz,
void* heap, const byte* pubKey,
word32 pubKeySz, int pubKeyOID);
#endif
#ifdef WOLFSSL_DUAL_ALG_CERTS
WOLFSSL_LOCAL int wc_ConfirmAltSignature(
const byte* buf, word32 bufSz,
const byte* key, word32 keySz, word32 keyOID,
const byte* sig, word32 sigSz, word32 sigOID,
void *heap);
#endif /* WOLFSSL_DUAL_ALG_CERTS */
#if (defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_IMPORT) || \
(defined(HAVE_ED448) && defined(HAVE_ED448_KEY_IMPORT)))
WOLFSSL_LOCAL int wc_CertGetPubKey(const byte* cert, word32 certSz,
@@ -2240,7 +2281,7 @@ WOLFSSL_LOCAL word32 SetBitString(word32 len, byte unusedBits, byte* output);
WOLFSSL_LOCAL word32 SetImplicit(byte tag,byte number,word32 len,byte* output);
WOLFSSL_LOCAL word32 SetExplicit(byte number, word32 len, byte* output);
WOLFSSL_LOCAL word32 SetSet(word32 len, byte* output);
WOLFSSL_LOCAL word32 SetAlgoID(int algoOID,byte* output,int type,int curveSz);
WOLFSSL_API word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz);
WOLFSSL_LOCAL int SetMyVersion(word32 version, byte* output, int header);
WOLFSSL_LOCAL int SetSerialNumber(const byte* sn, word32 snSz, byte* output,
word32 outputSz, int maxSnSz);

View File

@@ -141,6 +141,7 @@ enum EncPkcs8Types {
enum CertType {
CERT_TYPE = 0,
PRIVATEKEY_TYPE,
ALT_PRIVATEKEY_TYPE,
DH_PARAM_TYPE,
DSA_PARAM_TYPE,
CRL_TYPE,
@@ -513,6 +514,19 @@ typedef struct Cert {
byte issRaw[sizeof(CertName)]; /* raw issuer info */
byte sbjRaw[sizeof(CertName)]; /* raw subject info */
#endif
#ifdef WOLFSSL_DUAL_ALG_CERTS
/* These will not point to managed buffers. They will point to buffers that
* are managed by others. No cleanup neccessary. */
/* Subject Alternative Public Key Info */
byte *sapkiDer;
int sapkiLen;
/* Alternative Signature Algorithm */
byte *altSigAlgDer;
int altSigAlgLen;
/* Alternative Signature Value */
byte *altSigValDer;
int altSigValLen;
#endif /* WOLFSSL_DUAL_ALG_CERTS */
#ifdef WOLFSSL_CERT_REQ
char challengePw[CTC_NAME_SIZE];
char unstructuredName[CTC_NAME_SIZE];
@@ -572,6 +586,11 @@ WOLFSSL_API int wc_SignCert_ex(int requestSz, int sType, byte* buf,
WC_RNG* rng);
WOLFSSL_API int wc_SignCert(int requestSz, int sType, byte* buf, word32 buffSz,
RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng);
#ifdef WOLFSSL_DUAL_ALG_CERTS
WOLFSSL_API int wc_MakeSigWithBitStr(byte *sig, int sigSz, int sType, byte* buf,
word32 bufSz, int keyType, void* key,
WC_RNG* rng);
#endif
WOLFSSL_ABI
WOLFSSL_API int wc_MakeSelfCert(Cert* cert, byte* buf, word32 buffSz,
RsaKey* key, WC_RNG* rng);
@@ -941,6 +960,11 @@ WOLFSSL_API int wc_GetFASCNFromCert(struct DecodedCert* cert,
byte* fascn, word32* fascnSz);
#endif /* WOLFSSL_FPKI */
#ifdef WOLFSSL_DUAL_ALG_CERTS
WOLFSSL_API int wc_GeneratePreTBS(struct DecodedCert* cert, byte *der,
int derSz);
#endif
#if !defined(XFPRINTF) || defined(NO_FILESYSTEM) || \
defined(NO_STDIO_FILESYSTEM) && defined(WOLFSSL_ASN_PRINT)
#undef WOLFSSL_ASN_PRINT

View File

@@ -316,7 +316,44 @@
#endif
#endif
/* OpenSSL compat layer */
/* ---------------------------------------------------------------------------
* Dual Algorithm Certificate Required Features.
* ---------------------------------------------------------------------------
*/
#ifdef WOLFSSL_DUAL_ALG_CERTS
#ifndef WOLFSSL_ASN_TEMPLATE
#error "Dual alg cert support requires the ASN.1 template feature."
#endif
#ifdef NO_RSA
#error "Need RSA or else dual alg cert example will not work."
#endif
#ifndef HAVE_ECC
#error "Need ECDSA or else dual alg cert example will not work."
#endif
#undef WOLFSSL_CERT_GEN
#define WOLFSSL_CERT_GEN
#undef WOLFSSL_CUSTOM_OID
#define WOLFSSL_CUSTOM_OID
#undef HAVE_OID_ENCODING
#define HAVE_OID_ENCODING
#undef WOLFSSL_CERT_EXT
#define WOLFSSL_CERT_EXT
#undef OPENSSL_EXTRA
#define OPENSSL_EXTRA
#endif /* WOLFSSL_DUAL_ALG_CERTS */
/* ---------------------------------------------------------------------------
* OpenSSL compat layer
* ---------------------------------------------------------------------------
*/
#if defined(OPENSSL_EXTRA) && !defined(OPENSSL_COEXIST)
#undef WOLFSSL_ALWAYS_VERIFY_CB
#define WOLFSSL_ALWAYS_VERIFY_CB
@@ -343,7 +380,10 @@
#define WOLFSSL_SESSION_ID_CTX
#endif /* OPENSSL_EXTRA && !OPENSSL_COEXIST */
/* Special small OpenSSL compat layer for certs */
/* ---------------------------------------------------------------------------
* Special small OpenSSL compat layer for certs
* ---------------------------------------------------------------------------
*/
#ifdef OPENSSL_EXTRA_X509_SMALL
#undef WOLFSSL_EKU_OID
#define WOLFSSL_EKU_OID