mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-08-23 20:03:23 +02:00
Implement SLH-DSA (SPHINCS+, FIPS 205) as an entity authentication algorithm for the TLS 1.3 and DTLS 1.3 handshake, following draft-reddy-tls-slhdsa. All twelve parameter sets (SHAKE and SHA2 families, 128/192/256 in the f and s variants) are wired into the handshake for signing and verifying the CertificateVerify message; test certificates and configs cover the 128f and 128s sets. Handshake integration: - Map the SLH-DSA signature schemes to and from the wire in the signature_algorithms extension and CertificateVerify. The mapping, advertisement, and OID handling are gated per parameter set so a build only offers, accepts, and maps the variants actually compiled in (including partial SHA2 builds). - Sign and verify the CertificateVerify with an SLH-DSA entity key, and load SLH-DSA private keys and certificates (ssl_load.c, ssl.c, ssl_api_pk.c, asn.c). - Preserve the verify return code on a failed SLH-DSA CertificateVerify rather than flattening every non-zero result to SIG_VERIFY_E. wc_SlhDsaKey_Verify already returns SIG_VERIFY_E on a real mismatch, so the failure semantics are unchanged while WC_PENDING_E (async crypto callbacks) and hard errors now propagate, matching ML-DSA and Falcon. Protocol version gating: - SLH-DSA is defined for TLS 1.3 only, so the schemes are no longer offered to a TLS 1.2 peer, and MatchSigAlgo and PickHashSigAlgo pin an SLH-DSA certificate both to the scheme for its exact parameter set and to TLS 1.3. - Reject a Falcon, ML-DSA or SLH-DSA key in the TLS 1.2 CertificateVerify with SIG_TYPE_E. No signature scheme below TLS 1.3 covers a post-quantum key, the record is reserved for a classic signature, and the signing switches have no post-quantum case, so continuing would have sent the reserved buffer's uninitialized tail. Streamed CertificateVerify send: - SLH-DSA signatures are large (up to ~50 KB). When the CertificateVerify body exceeds a single record, generate the signature into a connection-level buffer and emit it one record at a time so the output buffer never has to hold the whole signature. This keeps peak memory near one signature plus a single fragment and resumes correctly across a non-blocking WANT_WRITE without recomputing the randomized signature. Gated by WOLFSSL_TLS13_STREAM_CERT_VERIFY (TLS 1.3, non-async, PQC signatures); DTLS and WOLFSSL_ASYNC_CRYPT keep the existing in-place fragmented path. - Drop a half-sent streamed CertificateVerify in wolfSSL_clear. Left in place, the resume guard would fire on the next handshake and re-send the previous one's signature into a different transcript. - Dual-algorithm (WOLFSSL_DUAL_ALG_CERTS, BOTH) CertificateVerify bodies are streamed as well. The combined two-signature body may include a variable-length signature, so the body buffer is sized from the per-signature upper bounds and the exact length is recorded after signing; the small trailing slack is never sent. Buffer sizing: - Keep MAX_X509_SIZE a fixed 9 KB for post-quantum builds. It sizes a static per-certificate slot embedded by value in every cached session, so it must not scale with a post-quantum signature; nor may it derive from the enabled ML-DSA level, or a level-restricted build would silently drop certificates that a full build keeps. - Add MAX_CERT_WIRE_SZ for the largest certificate that may appear in a handshake message, sized from the enabled post-quantum signatures, and derive MAX_CERTIFICATE_SZ from it instead of from MAX_X509_SIZE. - Add MAX_CERT_MSG_DEPTH for the chain depth assumed when sizing the certificate message. MAX_CHAIN_DEPTH bounds how deep a chain may be verified, while this sizes a buffer an unauthenticated peer can make us allocate, so it is trimmed to 5 when a post-quantum certificate has inflated the per-certificate size. Classic builds are unchanged. - Size the CertificateVerify buffers from the actual signature length instead of the worst-case WC_MAX_CERT_VERIFY_SZ, which balloons with SLH-DSA. WC_MAX_CERT_VERIFY_SZ is retained for API compatibility and its growth is documented in README.md. - Order Scv13Args widest member first so it carries no interior padding and still fits ssl->async->args under WOLFSSL_ASYNC_CRYPT together with WOLFSSL_DUAL_ALG_CERTS. Dual-algorithm certificates: - Reserve the two signature length prefixes in the in-place CertificateVerify sizing that the streamed path already accounted for. - Build the PreTBS for an alternative signature check from the certificate size minus both signatures, and retry once at a size the canonical re-encode cannot exceed when that estimate turns out short. The estimate keeps the allocation small on constrained targets, and wc_GeneratePreTBS reports an encoder failure as WOLFSSL_FAILURE, which is zero, so a non-positive result is now an error instead of silently skipping ConfirmSignature and reading as a verified signature. Device held private keys: - Support an SLH-DSA private key that lives in a device and is referenced by id or label. The parameter set cannot be recovered from a device side identifier, so it is carried from the key type down to wc_SlhDsaKey_Init_id and wc_SlhDsaKey_Init_label, and the key is released with wc_SlhDsaKey_Free once the certificate and key pair is checked. Robustness: - Check the SlhDsaParamToType, wc_SlhDsaKey_PublicSizeFromParam and wc_SlhDsaParamToOid results in the certificate and key load paths. - Zeroize an SLH-DSA key before wc_SlhDsaKey_Init, which can return NOT_COMPILED_IN before it clears the object, in both the certificate load path and AllocKey. - Take the alternative key's parameter set from the certificate's sapkiOID rather than keyOID, which describes the native key. - Re-initialise across hash families in wc_SlhDsaKey_PublicKeyDecode as wc_SlhDsaKey_PrivateKeyDecode already does. The hash objects share a union selected by family, so importing across families writes the new family's state over the old one's and orphans it. - Copy pkCurveOID in SetSSL_CTX when only SLH-DSA is enabled, matching the struct member guard. Without it the field stayed zero and the signature scheme matching above was dead in exactly that build. - Derive the per parameter set WOLFSSL_SLHDSA_PARAM_NO_* macros from the group level exclusions, and select WC_SLHDSA_DEFAULT_PARAM with those same macros, so the parameter table and the TLS mappings cannot disagree. - Add SLH-DSA to the lean build WOLFSSL_MAX_SIGALGO carve-out, since twelve more entries no longer fit the small list. - Prefix the new SLHDSA_ALL_NO_* macros in the installed header with WC_. Tests and certificates: - Add SLH-DSA entity (client and server) certificates for the SHAKE and SHA2 128f and 128s parameter sets, and update the generation script. - Add TLS 1.3 and DTLS 1.3 entity-cert CertificateVerify test configs covering the fragmented (128f) and single-record (128s) send paths for both hash families, wired into suites.c. These sign with the entity key, so they are excluded from verify-only builds. - Interrupt the streamed CertificateVerify with one WANT_WRITE and with several on the same record, and assert the handshake still completes and re-emits identical bytes, which the blocking .conf handshakes never exercise. The record to interrupt is counted first, because the server's record batching differs between builds. Where the flight is flushed as a single write the send is retried below SendTls13CertificateVerify, so these do not by themselves cover the fragOffset resume path. - Drive the streamed path with an ML-DSA leaf under a negotiated max_fragment_length, covering it for a non SLH-DSA algorithm. - Reject a TLS 1.2 handshake that presents an SLH-DSA client certificate. - Map every compiled-in scheme from its wire code point to the key OID, and extend the exhaustive SaToNid coverage with the twelve new algorithms. - Accept an SLH-DSA private key referenced by id and by label. Build configuration: - configure.ac: --enable-slhdsa now keeps the certificate/ASN code enabled (as --enable-mldsa does), so an SLH-DSA-only build with RSA, ECC and DH disabled configures instead of erroring that ASN is off. - Guard the WOLFSSL, WOLFSSL_CTX and WOLFSSL_X509 pkCurveOID members for WOLFSSL_HAVE_SLHDSA, so an SLH-DSA-only build declares the field the handshake and CopyDecodedToX509 already reference under an SLH-DSA guard. - Mark checkKeySz used in the SLH-DSA branch of ProcessBufferCertPublicKey; SLH-DSA is the only certificate signature algorithm with no minimum-size check, so an SLH-DSA-only build otherwise tripped -Wunused-parameter. - Propagate haveSlhDsaSig in wolfSSL_set_SSL_CTX, which copied the Falcon and ML-DSA flags but not the SLH-DSA one. - CI: add a SHA2-only SLH-DSA build (--enable-slhdsa=sha2) so the SHAKE-disabled combined-maxima guards are exercised, and an async crypto build with dual-algorithm certificates, which is the only configuration that compiles the in-place fragmented CertificateVerify send.
576 lines
19 KiB
C
576 lines
19 KiB
C
/* test_ssl_pk.c
|
|
*
|
|
* Copyright (C) 2006-2026 wolfSSL Inc.
|
|
*
|
|
* This file is part of wolfSSL.
|
|
*
|
|
* wolfSSL is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* wolfSSL is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
|
*/
|
|
|
|
#include <tests/unit.h>
|
|
|
|
#ifdef NO_INLINE
|
|
#include <wolfssl/wolfcrypt/misc.h>
|
|
#else
|
|
#define WOLFSSL_MISC_INCLUDED
|
|
#include <wolfcrypt/src/misc.c>
|
|
#endif
|
|
|
|
#include <wolfssl/ssl.h>
|
|
#include <wolfssl/internal.h>
|
|
#include <wolfssl/openssl/ec.h>
|
|
|
|
#include <tests/utils.h>
|
|
#include <tests/api/test_ssl_pk.h>
|
|
|
|
/* Tests for the public-key APIs in src/ssl_api_pk.c (moved from ssl.c). */
|
|
|
|
int test_wolfSSL_CTX_SetMinEccKey_Sz(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(HAVE_ECC) && !defined(NO_WOLFSSL_SERVER) && !defined(NO_TLS)
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method()));
|
|
|
|
/* NULL context and negative size are rejected. */
|
|
ExpectIntEQ(wolfSSL_CTX_SetMinEccKey_Sz(NULL, 256),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wolfSSL_CTX_SetMinEccKey_Sz(ctx, -1),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
/* Multiple-of-8 and non-multiple-of-8 bit sizes both succeed. */
|
|
ExpectIntEQ(wolfSSL_CTX_SetMinEccKey_Sz(ctx, 256), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_CTX_SetMinEccKey_Sz(ctx, 255), WOLFSSL_SUCCESS);
|
|
|
|
wolfSSL_CTX_free(ctx);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
int test_wolfSSL_SetMinEccKey_Sz(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(HAVE_ECC) && !defined(NO_WOLFSSL_SERVER) && \
|
|
(defined(NO_CERTS) || !defined(NO_RSA)) && !defined(NO_TLS)
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL* ssl = NULL;
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method()));
|
|
#ifndef NO_CERTS
|
|
/* A server WOLFSSL needs a key and certificate set on the context. */
|
|
ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, CERT_FILETYPE),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile,
|
|
CERT_FILETYPE), WOLFSSL_SUCCESS);
|
|
#endif
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
|
|
/* NULL object and negative size are rejected. */
|
|
ExpectIntEQ(wolfSSL_SetMinEccKey_Sz(NULL, 256),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wolfSSL_SetMinEccKey_Sz(ssl, -1),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
/* Multiple-of-8 and non-multiple-of-8 bit sizes both succeed. */
|
|
ExpectIntEQ(wolfSSL_SetMinEccKey_Sz(ssl, 256), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_SetMinEccKey_Sz(ssl, 255), WOLFSSL_SUCCESS);
|
|
|
|
wolfSSL_free(ssl);
|
|
wolfSSL_CTX_free(ctx);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
int test_wolfSSL_CTX_SetMinRsaKey_Sz(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if !defined(NO_RSA) && !defined(NO_WOLFSSL_SERVER) && !defined(NO_TLS)
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method()));
|
|
|
|
/* NULL context, negative size and non-multiple-of-8 size are rejected. */
|
|
ExpectIntEQ(wolfSSL_CTX_SetMinRsaKey_Sz(NULL, 2048),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wolfSSL_CTX_SetMinRsaKey_Sz(ctx, -8),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wolfSSL_CTX_SetMinRsaKey_Sz(ctx, 1001),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
ExpectIntEQ(wolfSSL_CTX_SetMinRsaKey_Sz(ctx, 2048), WOLFSSL_SUCCESS);
|
|
|
|
wolfSSL_CTX_free(ctx);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
int test_wolfSSL_SetMinRsaKey_Sz(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if !defined(NO_RSA) && !defined(NO_WOLFSSL_SERVER) && !defined(NO_TLS)
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL* ssl = NULL;
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method()));
|
|
#ifndef NO_CERTS
|
|
/* A server WOLFSSL needs a key and certificate set on the context. */
|
|
ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, CERT_FILETYPE),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile,
|
|
CERT_FILETYPE), WOLFSSL_SUCCESS);
|
|
#endif
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
|
|
/* NULL object, negative size and non-multiple-of-8 size are rejected. */
|
|
ExpectIntEQ(wolfSSL_SetMinRsaKey_Sz(NULL, 2048),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wolfSSL_SetMinRsaKey_Sz(ssl, -8),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wolfSSL_SetMinRsaKey_Sz(ssl, 1001),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
ExpectIntEQ(wolfSSL_SetMinRsaKey_Sz(ssl, 2048), WOLFSSL_SUCCESS);
|
|
|
|
wolfSSL_free(ssl);
|
|
wolfSSL_CTX_free(ctx);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
int test_wolfSSL_SetEnableDhKeyTest(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if !defined(NO_DH) && !defined(WOLFSSL_OLD_PRIME_CHECK) && \
|
|
!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) && \
|
|
!defined(NO_WOLFSSL_SERVER) && (defined(NO_CERTS) || !defined(NO_RSA)) && \
|
|
!defined(NO_TLS)
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL* ssl = NULL;
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method()));
|
|
#ifndef NO_CERTS
|
|
/* A server WOLFSSL needs a key and certificate set on the context. */
|
|
ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, CERT_FILETYPE),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile,
|
|
CERT_FILETYPE), WOLFSSL_SUCCESS);
|
|
#endif
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
|
|
/* NULL object is rejected. */
|
|
ExpectIntEQ(wolfSSL_SetEnableDhKeyTest(NULL, 1),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
/* Disable then enable the prime test. */
|
|
ExpectIntEQ(wolfSSL_SetEnableDhKeyTest(ssl, 0), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_SetEnableDhKeyTest(ssl, 1), WOLFSSL_SUCCESS);
|
|
|
|
wolfSSL_free(ssl);
|
|
wolfSSL_CTX_free(ctx);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
int test_wolfSSL_CTX_SetMinDhKey_Sz(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if !defined(NO_DH) && !defined(NO_WOLFSSL_SERVER) && \
|
|
(defined(NO_CERTS) || !defined(NO_RSA)) && !defined(NO_TLS)
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method()));
|
|
|
|
/* NULL context, oversized and non-multiple-of-8 sizes are rejected. */
|
|
ExpectIntEQ(wolfSSL_CTX_SetMinDhKey_Sz(NULL, 1024),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wolfSSL_CTX_SetMinDhKey_Sz(ctx, 16008),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wolfSSL_CTX_SetMinDhKey_Sz(ctx, 1001),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
ExpectIntEQ(wolfSSL_CTX_SetMinDhKey_Sz(ctx, 1024), WOLFSSL_SUCCESS);
|
|
|
|
wolfSSL_CTX_free(ctx);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
int test_wolfSSL_SetMinDhKey_Sz(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if !defined(NO_DH) && !defined(NO_WOLFSSL_SERVER) && \
|
|
(defined(NO_CERTS) || !defined(NO_RSA)) && !defined(NO_TLS)
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL* ssl = NULL;
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method()));
|
|
#ifndef NO_CERTS
|
|
/* A server WOLFSSL needs a key and certificate set on the context. */
|
|
ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, CERT_FILETYPE),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile,
|
|
CERT_FILETYPE), WOLFSSL_SUCCESS);
|
|
#endif
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
|
|
/* NULL object, oversized and non-multiple-of-8 sizes are rejected. */
|
|
ExpectIntEQ(wolfSSL_SetMinDhKey_Sz(NULL, 1024),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wolfSSL_SetMinDhKey_Sz(ssl, 16008),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wolfSSL_SetMinDhKey_Sz(ssl, 1001),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
ExpectIntEQ(wolfSSL_SetMinDhKey_Sz(ssl, 1024), WOLFSSL_SUCCESS);
|
|
|
|
wolfSSL_free(ssl);
|
|
wolfSSL_CTX_free(ctx);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
int test_wolfSSL_CTX_SetMaxDhKey_Sz(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if !defined(NO_DH) && !defined(NO_WOLFSSL_SERVER) && !defined(NO_TLS)
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method()));
|
|
|
|
/* NULL context, oversized and non-multiple-of-8 sizes are rejected. */
|
|
ExpectIntEQ(wolfSSL_CTX_SetMaxDhKey_Sz(NULL, 4096),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wolfSSL_CTX_SetMaxDhKey_Sz(ctx, 16008),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wolfSSL_CTX_SetMaxDhKey_Sz(ctx, 1001),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
ExpectIntEQ(wolfSSL_CTX_SetMaxDhKey_Sz(ctx, 4096), WOLFSSL_SUCCESS);
|
|
|
|
wolfSSL_CTX_free(ctx);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
int test_wolfSSL_SetMaxDhKey_Sz(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if !defined(NO_DH) && !defined(NO_WOLFSSL_SERVER) && \
|
|
(defined(NO_CERTS) || !defined(NO_RSA)) && !defined(NO_TLS)
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL* ssl = NULL;
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method()));
|
|
#ifndef NO_CERTS
|
|
/* A server WOLFSSL needs a key and certificate set on the context. */
|
|
ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, CERT_FILETYPE),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile,
|
|
CERT_FILETYPE), WOLFSSL_SUCCESS);
|
|
#endif
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
|
|
/* NULL object, oversized and non-multiple-of-8 sizes are rejected. */
|
|
ExpectIntEQ(wolfSSL_SetMaxDhKey_Sz(NULL, 4096),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wolfSSL_SetMaxDhKey_Sz(ssl, 16008),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wolfSSL_SetMaxDhKey_Sz(ssl, 1001),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
ExpectIntEQ(wolfSSL_SetMaxDhKey_Sz(ssl, 4096), WOLFSSL_SUCCESS);
|
|
|
|
wolfSSL_free(ssl);
|
|
wolfSSL_CTX_free(ctx);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
int test_wolfSSL_GetDhKey_Sz(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if !defined(NO_DH) && !defined(NO_WOLFSSL_SERVER) && \
|
|
(defined(NO_CERTS) || !defined(NO_RSA)) && !defined(NO_TLS)
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL* ssl = NULL;
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method()));
|
|
#ifndef NO_CERTS
|
|
/* A server WOLFSSL needs a key and certificate set on the context. */
|
|
ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, CERT_FILETYPE),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile,
|
|
CERT_FILETYPE), WOLFSSL_SUCCESS);
|
|
#endif
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
|
|
/* NULL object is rejected. */
|
|
ExpectIntEQ(wolfSSL_GetDhKey_Sz(NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
/* Valid object returns the negotiated size (0 before a handshake). */
|
|
ExpectIntGE(wolfSSL_GetDhKey_Sz(ssl), 0);
|
|
|
|
wolfSSL_free(ssl);
|
|
wolfSSL_CTX_free(ctx);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
int test_wolfSSL_get_privatekey(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(OPENSSL_EXTRA) && !defined(NO_WOLFSSL_STUB)
|
|
/* Stub for OpenSSL compatibility - always returns NULL. */
|
|
ExpectNull(wolfSSL_get_privatekey(NULL));
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
int test_wolfSSL_get_signature_nid(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(OPENSSL_EXTRA) && !defined(NO_WOLFSSL_SERVER) && \
|
|
(defined(NO_CERTS) || !defined(NO_RSA)) && !defined(NO_TLS)
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL* ssl = NULL;
|
|
int nid = 0;
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method()));
|
|
#ifndef NO_CERTS
|
|
/* A server WOLFSSL needs a key and certificate set on the context. */
|
|
ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, CERT_FILETYPE),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile,
|
|
CERT_FILETYPE), WOLFSSL_SUCCESS);
|
|
#endif
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
|
|
/* NULL object or output pointer is rejected. */
|
|
ExpectIntEQ(wolfSSL_get_signature_nid(NULL, &nid), WOLFSSL_FAILURE);
|
|
ExpectIntEQ(wolfSSL_get_signature_nid(ssl, NULL), WOLFSSL_FAILURE);
|
|
|
|
/* Valid object maps the hash algorithm to a NID. */
|
|
ExpectIntEQ(wolfSSL_get_signature_nid(ssl, &nid), WOLFSSL_SUCCESS);
|
|
|
|
/* Drive every hash-algorithm case (HashToNid). */
|
|
if (EXPECT_SUCCESS()) {
|
|
static const byte hashAlgos[] = {
|
|
no_mac, md5_mac, sha_mac, sha224_mac, sha256_mac, sha384_mac,
|
|
sha512_mac, rmd_mac, blake2b_mac, sm3_mac
|
|
};
|
|
size_t i;
|
|
|
|
for (i = 0; i < sizeof(hashAlgos) / sizeof(hashAlgos[0]); i++) {
|
|
ssl->options.hashAlgo = hashAlgos[i];
|
|
ExpectIntEQ(wolfSSL_get_signature_nid(ssl, &nid), WOLFSSL_SUCCESS);
|
|
}
|
|
/* An unknown hash algorithm is rejected. */
|
|
ssl->options.hashAlgo = 0xFF;
|
|
ExpectIntEQ(wolfSSL_get_signature_nid(ssl, &nid), WOLFSSL_FAILURE);
|
|
}
|
|
|
|
wolfSSL_free(ssl);
|
|
wolfSSL_CTX_free(ctx);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
int test_wolfSSL_get_signature_type_nid(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(OPENSSL_EXTRA) && !defined(NO_WOLFSSL_SERVER) && \
|
|
(defined(NO_CERTS) || !defined(NO_RSA)) && !defined(NO_TLS)
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL* ssl = NULL;
|
|
int nid = 0;
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method()));
|
|
#ifndef NO_CERTS
|
|
/* A server WOLFSSL needs a key and certificate set on the context. */
|
|
ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, CERT_FILETYPE),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile,
|
|
CERT_FILETYPE), WOLFSSL_SUCCESS);
|
|
#endif
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
|
|
/* NULL object or output pointer is rejected. */
|
|
ExpectIntEQ(wolfSSL_get_signature_type_nid(NULL, &nid), WOLFSSL_FAILURE);
|
|
ExpectIntEQ(wolfSSL_get_signature_type_nid(ssl, NULL), WOLFSSL_FAILURE);
|
|
|
|
/* Valid object maps the signature algorithm to a NID. */
|
|
ExpectIntEQ(wolfSSL_get_signature_type_nid(ssl, &nid), WOLFSSL_SUCCESS);
|
|
|
|
/* Drive every signature-algorithm case (SaToNid). */
|
|
if (EXPECT_SUCCESS()) {
|
|
static const byte okAlgos[] = {
|
|
anonymous_sa_algo, rsa_sa_algo, dsa_sa_algo, ecc_dsa_sa_algo,
|
|
ecc_brainpool_sa_algo, rsa_pss_sa_algo, rsa_pss_pss_algo,
|
|
falcon_level1_sa_algo, falcon_level5_sa_algo, mldsa_44_sa_algo,
|
|
mldsa_65_sa_algo, mldsa_87_sa_algo,
|
|
slhdsa_sha2_128s_sa_algo, slhdsa_sha2_128f_sa_algo,
|
|
slhdsa_sha2_192s_sa_algo, slhdsa_sha2_192f_sa_algo,
|
|
slhdsa_sha2_256s_sa_algo, slhdsa_sha2_256f_sa_algo,
|
|
slhdsa_shake_128s_sa_algo, slhdsa_shake_128f_sa_algo,
|
|
slhdsa_shake_192s_sa_algo, slhdsa_shake_192f_sa_algo,
|
|
slhdsa_shake_256s_sa_algo, slhdsa_shake_256f_sa_algo,
|
|
sm2_sa_algo
|
|
};
|
|
static const byte failAlgos[] = { invalid_sa_algo, any_sa_algo };
|
|
size_t i;
|
|
|
|
for (i = 0; i < sizeof(okAlgos) / sizeof(okAlgos[0]); i++) {
|
|
ssl->options.sigAlgo = okAlgos[i];
|
|
ExpectIntEQ(wolfSSL_get_signature_type_nid(ssl, &nid),
|
|
WOLFSSL_SUCCESS);
|
|
}
|
|
/* Ed25519/Ed448 mappings depend on build configuration. */
|
|
ssl->options.sigAlgo = ed25519_sa_algo;
|
|
#ifdef HAVE_ED25519
|
|
ExpectIntEQ(wolfSSL_get_signature_type_nid(ssl, &nid), WOLFSSL_SUCCESS);
|
|
#else
|
|
ExpectIntEQ(wolfSSL_get_signature_type_nid(ssl, &nid), WOLFSSL_FAILURE);
|
|
#endif
|
|
ssl->options.sigAlgo = ed448_sa_algo;
|
|
#ifdef HAVE_ED448
|
|
ExpectIntEQ(wolfSSL_get_signature_type_nid(ssl, &nid), WOLFSSL_SUCCESS);
|
|
#else
|
|
ExpectIntEQ(wolfSSL_get_signature_type_nid(ssl, &nid), WOLFSSL_FAILURE);
|
|
#endif
|
|
/* Unknown/placeholder algorithms are rejected. */
|
|
for (i = 0; i < sizeof(failAlgos) / sizeof(failAlgos[0]); i++) {
|
|
ssl->options.sigAlgo = failAlgos[i];
|
|
ExpectIntEQ(wolfSSL_get_signature_type_nid(ssl, &nid),
|
|
WOLFSSL_FAILURE);
|
|
}
|
|
}
|
|
|
|
wolfSSL_free(ssl);
|
|
wolfSSL_CTX_free(ctx);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
int test_wolfSSL_get_peer_signature_nid(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(OPENSSL_EXTRA) && !defined(NO_WOLFSSL_SERVER) && \
|
|
(defined(NO_CERTS) || !defined(NO_RSA)) && !defined(NO_TLS)
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL* ssl = NULL;
|
|
int nid = 0;
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method()));
|
|
#ifndef NO_CERTS
|
|
/* A server WOLFSSL needs a key and certificate set on the context. */
|
|
ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, CERT_FILETYPE),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile,
|
|
CERT_FILETYPE), WOLFSSL_SUCCESS);
|
|
#endif
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
|
|
/* NULL object or output pointer is rejected. */
|
|
ExpectIntEQ(wolfSSL_get_peer_signature_nid(NULL, &nid), WOLFSSL_FAILURE);
|
|
ExpectIntEQ(wolfSSL_get_peer_signature_nid(ssl, NULL), WOLFSSL_FAILURE);
|
|
|
|
/* Valid object maps the peer's hash algorithm to a NID. */
|
|
ExpectIntEQ(wolfSSL_get_peer_signature_nid(ssl, &nid), WOLFSSL_SUCCESS);
|
|
|
|
wolfSSL_free(ssl);
|
|
wolfSSL_CTX_free(ctx);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
int test_wolfSSL_get_peer_signature_type_nid(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(OPENSSL_EXTRA) && !defined(NO_WOLFSSL_SERVER) && \
|
|
(defined(NO_CERTS) || !defined(NO_RSA)) && !defined(NO_TLS)
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL* ssl = NULL;
|
|
int nid = 0;
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method()));
|
|
#ifndef NO_CERTS
|
|
/* A server WOLFSSL needs a key and certificate set on the context. */
|
|
ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, CERT_FILETYPE),
|
|
WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile,
|
|
CERT_FILETYPE), WOLFSSL_SUCCESS);
|
|
#endif
|
|
ExpectNotNull(ssl = wolfSSL_new(ctx));
|
|
|
|
/* NULL object or output pointer is rejected. */
|
|
ExpectIntEQ(wolfSSL_get_peer_signature_type_nid(NULL, &nid),
|
|
WOLFSSL_FAILURE);
|
|
ExpectIntEQ(wolfSSL_get_peer_signature_type_nid(ssl, NULL),
|
|
WOLFSSL_FAILURE);
|
|
|
|
/* Valid object maps the peer's signature algorithm to a NID. */
|
|
ExpectIntEQ(wolfSSL_get_peer_signature_type_nid(ssl, &nid),
|
|
WOLFSSL_SUCCESS);
|
|
|
|
wolfSSL_free(ssl);
|
|
wolfSSL_CTX_free(ctx);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
int test_wolfSSL_SSL_CTX_set_tmp_ecdh(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(OPENSSL_EXTRA) && defined(HAVE_ECC) && !defined(NO_WOLFSSL_SERVER) \
|
|
&& !defined(NO_TLS)
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
WOLFSSL_EC_KEY* ecdh = NULL;
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method()));
|
|
ExpectNotNull(ecdh = wolfSSL_EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
|
|
|
|
/* NULL context or key is rejected. */
|
|
ExpectIntEQ(wolfSSL_SSL_CTX_set_tmp_ecdh(NULL, ecdh),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
ExpectIntEQ(wolfSSL_SSL_CTX_set_tmp_ecdh(ctx, NULL),
|
|
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
|
|
|
/* Valid key sets the curve. */
|
|
ExpectIntEQ(wolfSSL_SSL_CTX_set_tmp_ecdh(ctx, ecdh), WOLFSSL_SUCCESS);
|
|
|
|
wolfSSL_EC_KEY_free(ecdh);
|
|
wolfSSL_CTX_free(ctx);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|
|
|
|
int test_wolfSSL_CTX_set_dh_auto(void)
|
|
{
|
|
EXPECT_DECLS;
|
|
#if defined(OPENSSL_EXTRA) && !defined(NO_WOLFSSL_SERVER) && !defined(NO_TLS)
|
|
WOLFSSL_CTX* ctx = NULL;
|
|
|
|
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method()));
|
|
|
|
/* Compatibility stub - always succeeds. */
|
|
ExpectIntEQ(wolfSSL_CTX_set_dh_auto(ctx, 0), WOLFSSL_SUCCESS);
|
|
ExpectIntEQ(wolfSSL_CTX_set_dh_auto(ctx, 1), WOLFSSL_SUCCESS);
|
|
|
|
wolfSSL_CTX_free(ctx);
|
|
#endif
|
|
return EXPECT_RESULT();
|
|
}
|