diff --git a/tests/api.c b/tests/api.c index eed600c040..bbd11f17c9 100644 --- a/tests/api.c +++ b/tests/api.c @@ -33,6 +33,9 @@ #include #include +#ifdef WOLF_CRYPTO_CB + #include +#endif #if defined(WOLFSSL_STATIC_MEMORY) #include @@ -4575,6 +4578,247 @@ static int test_wolfSSL_CTX_ticket_API(void) return EXPECT_RESULT(); } +static int test_wolfSSL_session_cache_api_direct(void) +{ + EXPECT_DECLS; +#if !defined(NO_SESSION_CACHE) && !defined(NO_TLS) && \ + (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) + WOLFSSL_CTX* ctx = NULL; + WOLFSSL* ssl = NULL; + byte shortId[] = "server-id"; + byte longId[SERVER_ID_LEN + 8]; + long mode = 0; + + XMEMSET(longId, 0xA5, sizeof(longId)); + + ExpectIntEQ(wolfSSL_CTX_set_session_cache_mode(NULL, + WOLFSSL_SESS_CACHE_OFF), WOLFSSL_FAILURE); +#ifdef OPENSSL_EXTRA + ExpectIntEQ(wolfSSL_CTX_get_session_cache_mode(NULL), 0); +#endif + ExpectIntEQ(wolfSSL_set_session(NULL, NULL), WOLFSSL_FAILURE); + ExpectIntEQ(wolfSSL_SetServerID(NULL, shortId, sizeof(shortId), 0), + BAD_FUNC_ARG); + +#ifndef NO_WOLFSSL_CLIENT + ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); +#elif !defined(NO_WOLFSSL_SERVER) + ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); +#endif + ExpectNotNull(ssl = wolfSSL_new(ctx)); + +#ifdef OPENSSL_EXTRA + mode = wolfSSL_CTX_get_session_cache_mode(ctx); + ExpectIntEQ(mode & WOLFSSL_SESS_CACHE_SERVER, WOLFSSL_SESS_CACHE_SERVER); +#endif + + ExpectIntEQ(wolfSSL_CTX_set_session_cache_mode(ctx, + WOLFSSL_SESS_CACHE_NO_AUTO_CLEAR | + WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE | + WOLFSSL_SESS_CACHE_NO_INTERNAL_LOOKUP), WOLFSSL_SUCCESS); +#ifdef OPENSSL_EXTRA + mode = wolfSSL_CTX_get_session_cache_mode(ctx); + ExpectIntEQ(mode & WOLFSSL_SESS_CACHE_NO_AUTO_CLEAR, + WOLFSSL_SESS_CACHE_NO_AUTO_CLEAR); + ExpectIntEQ(mode & WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE, + WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE); + ExpectIntEQ(mode & WOLFSSL_SESS_CACHE_NO_INTERNAL_LOOKUP, + WOLFSSL_SESS_CACHE_NO_INTERNAL_LOOKUP); +#endif + + ExpectIntEQ(wolfSSL_CTX_set_session_cache_mode(ctx, + WOLFSSL_SESS_CACHE_OFF), WOLFSSL_SUCCESS); +#ifdef OPENSSL_EXTRA + mode = wolfSSL_CTX_get_session_cache_mode(ctx); + ExpectIntEQ(mode & WOLFSSL_SESS_CACHE_SERVER, 0); + ExpectIntEQ(mode & WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE, + WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE); + ExpectIntEQ(mode & WOLFSSL_SESS_CACHE_NO_INTERNAL_LOOKUP, + WOLFSSL_SESS_CACHE_NO_INTERNAL_LOOKUP); +#endif + + ExpectIntEQ(wolfSSL_set_session(ssl, NULL), WOLFSSL_FAILURE); + ExpectIntEQ(wolfSSL_SetServerID(ssl, NULL, sizeof(shortId), 0), + BAD_FUNC_ARG); + ExpectIntEQ(wolfSSL_SetServerID(ssl, shortId, 0, 0), BAD_FUNC_ARG); +#ifndef NO_CLIENT_CACHE + ExpectIntEQ(wolfSSL_SetServerID(ssl, shortId, (int)sizeof(shortId), 1), + WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_SetServerID(ssl, longId, (int)sizeof(longId), 1), + WOLFSSL_SUCCESS); +#endif + + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); +#endif + return EXPECT_RESULT(); +} + +static int test_wolfSSL_crl_ocsp_object_api(void) +{ + EXPECT_DECLS; +#if !defined(NO_CERTS) && !defined(NO_TLS) && \ + (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) + WOLFSSL_CTX* clientCtx = NULL; + WOLFSSL_CTX* serverCtx = NULL; + WOLFSSL* clientSsl = NULL; + WOLFSSL* serverSsl = NULL; + +#ifndef NO_WOLFSSL_CLIENT + ExpectNotNull(clientCtx = wolfSSL_CTX_new(wolfSSLv23_client_method())); + ExpectNotNull(clientSsl = wolfSSL_new(clientCtx)); +#endif +#ifndef NO_WOLFSSL_SERVER + ExpectNotNull(serverCtx = wolfSSL_CTX_new(wolfSSLv23_server_method())); + serverSsl = wolfSSL_new(serverCtx); +#endif + +#ifdef HAVE_CRL + ExpectIntEQ(wolfSSL_CTX_LoadCRLBuffer(NULL, (const unsigned char*)"x", 1, + WOLFSSL_FILETYPE_PEM), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wolfSSL_CTX_EnableCRL(NULL, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wolfSSL_CTX_DisableCRL(NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wolfSSL_CTX_SetCRL_Cb(NULL, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wolfSSL_CTX_SetCRL_ErrorCb(NULL, NULL, NULL), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); +#ifdef HAVE_CRL_IO + ExpectIntEQ(wolfSSL_CTX_SetCRL_IOCb(NULL, NULL), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); +#endif + ExpectIntEQ(wolfSSL_EnableCRL(NULL, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wolfSSL_DisableCRL(NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wolfSSL_SetCRL_Cb(NULL, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wolfSSL_SetCRL_ErrorCb(NULL, NULL, NULL), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wolfSSL_LoadCRLBuffer(NULL, (const unsigned char*)"x", 1, + WOLFSSL_FILETYPE_PEM), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); +#ifndef NO_FILESYSTEM + ExpectIntEQ(wolfSSL_LoadCRL(NULL, "./certs/crl", WOLFSSL_FILETYPE_PEM, 0), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wolfSSL_LoadCRLFile(NULL, "./certs/crl/cliCrl.pem", + WOLFSSL_FILETYPE_PEM), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); +#endif +#ifndef NO_WOLFSSL_CLIENT + ExpectIntNE(wolfSSL_CTX_LoadCRLBuffer(clientCtx, (const unsigned char*)"x", + 0, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); + ExpectIntNE(wolfSSL_CTX_LoadCRLBuffer(clientCtx, (const unsigned char*)"x", + 1, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CTX_EnableCRL(clientCtx, 0), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CTX_DisableCRL(clientCtx), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CTX_SetCRL_Cb(clientCtx, NULL), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CTX_SetCRL_ErrorCb(clientCtx, NULL, NULL), + WOLFSSL_SUCCESS); +#ifdef HAVE_CRL_IO + ExpectIntEQ(wolfSSL_CTX_SetCRL_IOCb(clientCtx, NULL), WOLFSSL_SUCCESS); +#endif + ExpectIntEQ(wolfSSL_EnableCRL(clientSsl, 0), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_DisableCRL(clientSsl), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_SetCRL_Cb(clientSsl, NULL), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_SetCRL_ErrorCb(clientSsl, NULL, NULL), WOLFSSL_SUCCESS); + ExpectIntNE(wolfSSL_LoadCRLBuffer(clientSsl, (const unsigned char*)"x", 0, + WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); + ExpectIntNE(wolfSSL_LoadCRLBuffer(clientSsl, (const unsigned char*)"x", 1, + WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); +#ifdef HAVE_CRL_IO + ExpectIntEQ(wolfSSL_SetCRL_IOCb(NULL, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wolfSSL_SetCRL_IOCb(clientSsl, NULL), WOLFSSL_SUCCESS); +#endif +#endif +#endif + +#ifdef HAVE_OCSP + ExpectIntEQ(wolfSSL_CTX_EnableOCSP(NULL, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wolfSSL_CTX_DisableOCSP(NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wolfSSL_CTX_SetOCSP_OverrideURL(NULL, "http://dummy.test"), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wolfSSL_CTX_SetOCSP_Cb(NULL, NULL, NULL, NULL), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wolfSSL_CTX_EnableOCSPStapling(NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wolfSSL_CTX_DisableOCSPStapling(NULL), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wolfSSL_EnableOCSP(NULL, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wolfSSL_DisableOCSP(NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wolfSSL_EnableOCSPStapling(NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wolfSSL_DisableOCSPStapling(NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wolfSSL_SetOCSP_OverrideURL(NULL, "http://dummy.test"), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wolfSSL_SetOCSP_Cb(NULL, NULL, NULL, NULL), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); +#ifndef NO_WOLFSSL_CLIENT + ExpectIntEQ(wolfSSL_CTX_EnableOCSP(clientCtx, WOLFSSL_OCSP_NO_NONCE), + WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CTX_DisableOCSP(clientCtx), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CTX_EnableOCSPStapling(clientCtx), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CTX_DisableOCSPStapling(clientCtx), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CTX_SetOCSP_OverrideURL(clientCtx, "http://dummy.test"), + WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CTX_SetOCSP_OverrideURL(clientCtx, ""), + WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CTX_SetOCSP_OverrideURL(clientCtx, NULL), + WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CTX_SetOCSP_Cb(clientCtx, NULL, NULL, clientCtx), + WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_EnableOCSP(clientSsl, WOLFSSL_OCSP_NO_NONCE), + WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_DisableOCSP(clientSsl), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_EnableOCSPStapling(clientSsl), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_DisableOCSPStapling(clientSsl), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_SetOCSP_OverrideURL(clientSsl, "http://dummy.test"), + WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_SetOCSP_OverrideURL(clientSsl, ""), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_SetOCSP_OverrideURL(clientSsl, NULL), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_SetOCSP_Cb(clientSsl, NULL, NULL, clientCtx), + WOLFSSL_SUCCESS); + ExpectPtrEq(clientSsl->ocspIOCtx, clientCtx); +#endif +#endif + +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST + ExpectIntEQ(wolfSSL_UseOCSPStapling(NULL, WOLFSSL_CSR_OCSP, 0), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); +#ifndef NO_WOLFSSL_SERVER + ExpectIntEQ(wolfSSL_CTX_UseOCSPStapling(serverCtx, WOLFSSL_CSR_OCSP, 0), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + if (serverSsl != NULL) { + ExpectIntEQ(wolfSSL_UseOCSPStapling(serverSsl, WOLFSSL_CSR_OCSP, 0), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + } +#endif +#ifndef NO_WOLFSSL_CLIENT + ExpectIntEQ(wolfSSL_UseOCSPStapling(clientSsl, WOLFSSL_CSR_OCSP, 0), + WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CTX_UseOCSPStapling(clientCtx, WOLFSSL_CSR_OCSP, 0), + WOLFSSL_SUCCESS); +#endif +#endif + +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + ExpectIntEQ(wolfSSL_UseOCSPStaplingV2(NULL, WOLFSSL_CSR2_OCSP, 0), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); +#ifndef NO_WOLFSSL_SERVER + ExpectIntEQ(wolfSSL_CTX_UseOCSPStaplingV2(serverCtx, WOLFSSL_CSR2_OCSP, 0), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + if (serverSsl != NULL) { + ExpectIntEQ(wolfSSL_UseOCSPStaplingV2(serverSsl, WOLFSSL_CSR2_OCSP, 0), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + } +#endif +#ifndef NO_WOLFSSL_CLIENT + ExpectIntEQ(wolfSSL_UseOCSPStaplingV2(clientSsl, WOLFSSL_CSR2_OCSP, 0), + WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CTX_UseOCSPStaplingV2(clientCtx, WOLFSSL_CSR2_OCSP, 0), + WOLFSSL_SUCCESS); +#endif +#endif + + wolfSSL_free(clientSsl); + wolfSSL_free(serverSsl); + wolfSSL_CTX_free(clientCtx); + wolfSSL_CTX_free(serverCtx); +#endif + return EXPECT_RESULT(); +} + static int test_wolfSSL_set_minmax_proto_version(void) { EXPECT_DECLS; @@ -21187,7 +21431,8 @@ static int TXT_DB_cmp(const WOLFSSL_STRING *a, const WOLFSSL_STRING *b) static int test_wolfSSL_TXT_DB(void) { EXPECT_DECLS; -#if !defined(NO_FILESYSTEM) && !defined(NO_BIO) +#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && \ + !defined(NO_FILESYSTEM) && !defined(NO_BIO) BIO *bio = NULL; TXT_DB *db = NULL; const int columns = 6; @@ -21265,6 +21510,46 @@ static int test_wolfSSL_NCONF(void) #endif return EXPECT_RESULT(); } + +static int test_wolfSSL_NCONF_negative_paths(void) +{ + EXPECT_DECLS; +#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && !defined(NO_BIO) + const char* confFile = "./tests/NCONF_test.cnf"; + const char* missingFile = "./tests/NCONF_missing.cnf"; + const char* value = NULL; + CONF* conf = NULL; + long eline = 0; + long num = 0; + + ExpectIntEQ(NCONF_load(NULL, confFile, &eline), WOLFSSL_FAILURE); + ExpectIntEQ(NCONF_get_number(NULL, NULL, "port", &num), WOLFSSL_FAILURE); + ExpectNull(NCONF_get_section(NULL, "default")); + + ExpectNotNull(conf = NCONF_new(NULL)); + ExpectIntEQ(NCONF_load(conf, missingFile, &eline), WOLFSSL_FAILURE); + ExpectIntEQ(NCONF_get_number(conf, NULL, NULL, &num), WOLFSSL_FAILURE); + ExpectIntEQ(NCONF_get_number(conf, NULL, "port", NULL), WOLFSSL_FAILURE); + + ExpectIntEQ(NCONF_load(conf, confFile, &eline), 1); + value = NCONF_get_string(conf, "missing", "port"); + ExpectTrue(value == NULL || XSTRCMP(value, "1234") == 0); + ExpectNull(NCONF_get_string(conf, NULL, "missing-name")); + if (NCONF_get_number(conf, "missing", "port", &num) == 1) { + ExpectIntEQ(num, 1234); + } + else { + ExpectIntEQ(NCONF_get_number(conf, "missing", "port", &num), + WOLFSSL_FAILURE); + } + ExpectNull(NCONF_get_section(conf, NULL)); + ExpectNull(NCONF_get_section(conf, "missing")); + ExpectNotNull(NCONF_get_section(conf, "default")); + + NCONF_free(conf); +#endif + return EXPECT_RESULT(); +} #endif /* OPENSSL_ALL */ static int test_wolfSSL_d2i_and_i2d_PublicKey(void) @@ -28559,26 +28844,37 @@ static int test_wolfSSL_OpenSSL_version(void) static int test_CONF_CTX_CMDLINE(void) { EXPECT_DECLS; -#if defined(OPENSSL_ALL) && !defined(NO_TLS) && !defined(NO_WOLFSSL_SERVER) +#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && !defined(NO_TLS) && \ + !defined(NO_WOLFSSL_SERVER) SSL_CTX* ctx = NULL; SSL_CONF_CTX* cctx = NULL; + SSL_CONF_CTX* noCertCtx = NULL; ExpectNotNull(cctx = SSL_CONF_CTX_new()); + ExpectNotNull(noCertCtx = SSL_CONF_CTX_new()); ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); SSL_CONF_CTX_set_ssl_ctx(cctx, ctx); + SSL_CONF_CTX_set_ssl_ctx(noCertCtx, ctx); /* set flags */ ExpectIntEQ(SSL_CONF_CTX_set_flags(cctx, WOLFSSL_CONF_FLAG_CMDLINE), WOLFSSL_CONF_FLAG_CMDLINE); ExpectIntEQ(SSL_CONF_CTX_set_flags(cctx, WOLFSSL_CONF_FLAG_CERTIFICATE), WOLFSSL_CONF_FLAG_CMDLINE | WOLFSSL_CONF_FLAG_CERTIFICATE); + ExpectIntEQ(SSL_CONF_CTX_set_flags(noCertCtx, WOLFSSL_CONF_FLAG_CMDLINE), + WOLFSSL_CONF_FLAG_CMDLINE); + ExpectIntEQ(SSL_CONF_cmd_value_type(cctx, "-cipher"), + WOLFSSL_CONF_TYPE_STRING); + ExpectIntEQ(SSL_CONF_cmd_value_type(cctx, "-missing"), + WOLFSSL_CONF_TYPE_UNKNOWN); /* cmd invalid command */ ExpectIntEQ(SSL_CONF_cmd(cctx, "foo", "foobar"), -2); ExpectIntEQ(SSL_CONF_cmd(cctx, "foo", NULL), -2); ExpectIntEQ(SSL_CONF_cmd(cctx, NULL, NULL), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(SSL_CONF_cmd(cctx, NULL, "foobar"), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(SSL_CONF_cmd(NULL, "-curves", "foobar"), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); + ExpectIntEQ(SSL_CONF_cmd(cctx, "-sigalgs", "RSA+SHA256"), -2); /* cmd Certificate and Private Key*/ { @@ -28590,6 +28886,8 @@ static int test_CONF_CTX_CMDLINE(void) ExpectIntEQ(SSL_CONF_cmd(cctx, "-cert", ourCert), WOLFSSL_SUCCESS); ExpectIntEQ(SSL_CONF_cmd(cctx, "-key", NULL), -3); ExpectIntEQ(SSL_CONF_cmd(cctx, "-key", ourKey), WOLFSSL_SUCCESS); + ExpectIntEQ(SSL_CONF_cmd(noCertCtx, "-cert", ourCert), -2); + ExpectIntEQ(SSL_CONF_cmd(noCertCtx, "-key", ourKey), -2); ExpectIntEQ(SSL_CONF_CTX_finish(cctx), WOLFSSL_SUCCESS); #endif } @@ -28601,6 +28899,8 @@ static int test_CONF_CTX_CMDLINE(void) ExpectIntEQ(SSL_CONF_cmd(cctx, "-curves", NULL), -3); ExpectIntEQ(SSL_CONF_cmd(cctx, "-curves", curve), WOLFSSL_SUCCESS); + ExpectIntNE(SSL_CONF_cmd(cctx, "-curves", "invalidcurve"), + WOLFSSL_SUCCESS); ExpectIntEQ(SSL_CONF_CTX_finish(cctx), WOLFSSL_SUCCESS); #endif } @@ -28611,6 +28911,8 @@ static int test_CONF_CTX_CMDLINE(void) ExpectIntEQ(SSL_CONF_cmd(cctx, "-cipher", NULL), -3); ExpectIntEQ(SSL_CONF_cmd(cctx, "-cipher", cipher), WOLFSSL_SUCCESS); + ExpectIntNE(SSL_CONF_cmd(cctx, "-cipher", "wolfssl-invalid-cipher"), + WOLFSSL_SUCCESS); ExpectIntEQ(SSL_CONF_CTX_finish(cctx), WOLFSSL_SUCCESS); } @@ -28627,6 +28929,7 @@ static int test_CONF_CTX_CMDLINE(void) } SSL_CTX_free(ctx); + SSL_CONF_CTX_free(noCertCtx); SSL_CONF_CTX_free(cctx); #endif /* OPENSSL_EXTRA */ return EXPECT_RESULT(); @@ -28635,25 +28938,36 @@ static int test_CONF_CTX_CMDLINE(void) static int test_CONF_CTX_FILE(void) { EXPECT_DECLS; -#if defined(OPENSSL_ALL) && !defined(NO_TLS) && !defined(NO_WOLFSSL_SERVER) +#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && !defined(NO_TLS) && \ + !defined(NO_WOLFSSL_SERVER) SSL_CTX* ctx = NULL; SSL_CONF_CTX* cctx = NULL; + SSL_CONF_CTX* noCertCtx = NULL; ExpectNotNull(cctx = SSL_CONF_CTX_new()); + ExpectNotNull(noCertCtx = SSL_CONF_CTX_new()); ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); SSL_CONF_CTX_set_ssl_ctx(cctx, ctx); + SSL_CONF_CTX_set_ssl_ctx(noCertCtx, ctx); /* set flags */ ExpectIntEQ(SSL_CONF_CTX_set_flags(cctx, WOLFSSL_CONF_FLAG_FILE), WOLFSSL_CONF_FLAG_FILE); ExpectIntEQ(SSL_CONF_CTX_set_flags(cctx, WOLFSSL_CONF_FLAG_CERTIFICATE), WOLFSSL_CONF_FLAG_FILE | WOLFSSL_CONF_FLAG_CERTIFICATE); + ExpectIntEQ(SSL_CONF_CTX_set_flags(noCertCtx, WOLFSSL_CONF_FLAG_FILE), + WOLFSSL_CONF_FLAG_FILE); + ExpectIntEQ(SSL_CONF_cmd_value_type(cctx, "CipherString"), + WOLFSSL_CONF_TYPE_STRING); + ExpectIntEQ(SSL_CONF_cmd_value_type(cctx, "missing"), + WOLFSSL_CONF_TYPE_UNKNOWN); /* sanity check */ ExpectIntEQ(SSL_CONF_cmd(cctx, "foo", "foobar"), -2); ExpectIntEQ(SSL_CONF_cmd(cctx, "foo", NULL), -2); ExpectIntEQ(SSL_CONF_cmd(cctx, NULL, NULL), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(SSL_CONF_cmd(cctx, NULL, "foobar"), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); ExpectIntEQ(SSL_CONF_cmd(NULL, "-curves", "foobar"), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); + ExpectIntEQ(SSL_CONF_cmd(cctx, "SignatureAlgorithms", "RSA+SHA256"), -2); /* cmd Certificate and Private Key*/ { @@ -28667,6 +28981,8 @@ static int test_CONF_CTX_FILE(void) ExpectIntEQ(SSL_CONF_cmd(cctx, "Certificate", ourCert), WOLFSSL_SUCCESS); ExpectIntEQ(SSL_CONF_cmd(cctx, "PrivateKey", ourKey), WOLFSSL_SUCCESS); + ExpectIntEQ(SSL_CONF_cmd(noCertCtx, "Certificate", ourCert), -2); + ExpectIntEQ(SSL_CONF_cmd(noCertCtx, "PrivateKey", ourKey), -2); ExpectIntEQ(SSL_CONF_CTX_finish(cctx), WOLFSSL_SUCCESS); #endif } @@ -28678,6 +28994,8 @@ static int test_CONF_CTX_FILE(void) ExpectIntEQ(SSL_CONF_cmd(cctx, "Curves", NULL), -3); ExpectIntEQ(SSL_CONF_cmd(cctx, "Curves", curve), WOLFSSL_SUCCESS); + ExpectIntNE(SSL_CONF_cmd(cctx, "Curves", "invalidcurve"), + WOLFSSL_SUCCESS); ExpectIntEQ(SSL_CONF_CTX_finish(cctx), WOLFSSL_SUCCESS); #endif } @@ -28689,6 +29007,8 @@ static int test_CONF_CTX_FILE(void) ExpectIntEQ(SSL_CONF_cmd(cctx, "CipherString", NULL), -3); ExpectIntEQ(SSL_CONF_cmd(cctx, "CipherString", cipher), WOLFSSL_SUCCESS); + ExpectIntNE(SSL_CONF_cmd(cctx, "CipherString", "wolfssl-invalid-cipher"), + WOLFSSL_SUCCESS); ExpectIntEQ(SSL_CONF_CTX_finish(cctx), WOLFSSL_SUCCESS); } @@ -28706,6 +29026,7 @@ static int test_CONF_CTX_FILE(void) } SSL_CTX_free(ctx); + SSL_CONF_CTX_free(noCertCtx); SSL_CONF_CTX_free(cctx); #endif /* OPENSSL_EXTRA */ return EXPECT_RESULT(); @@ -30038,6 +30359,96 @@ static int test_CryptoCb_Func(int thisDevId, wc_CryptoInfo* info, void* ctx) return ret; } +/* tlsVer: WOLFSSL_TLSV1_2 or WOLFSSL_TLSV1_3 */ +static int test_CryptoCb_NoOp_Func(int devId, wc_CryptoInfo* info, void* ctx) +{ + (void)devId; + (void)info; + (void)ctx; + + return WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); +} + +#ifdef WOLF_CRYPTO_CB_CMD +static int test_CryptoCb_RegisterUnavailable_Func(int devId, wc_CryptoInfo* info, + void* ctx) +{ + (void)devId; + (void)ctx; + + if (info != NULL && info->algo_type == WC_ALGO_TYPE_NONE && + info->cmd.type == WC_CRYPTOCB_CMD_TYPE_REGISTER) { + return WC_NO_ERR_TRACE(NOT_COMPILED_IN); + } + + return WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); +} + +static int test_CryptoCb_RegisterFail_Func(int devId, wc_CryptoInfo* info, + void* ctx) +{ + (void)devId; + (void)ctx; + + if (info != NULL && info->algo_type == WC_ALGO_TYPE_NONE && + info->cmd.type == WC_CRYPTOCB_CMD_TYPE_REGISTER) { + return BAD_FUNC_ARG; + } + + return WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); +} +#endif + +static int test_wc_CryptoCb_registry(void) +{ + EXPECT_DECLS; +#ifdef WOLF_CRYPTO_CB + int rc = 0; + int devId = 41; + int added = 0; + + wc_CryptoCb_Init(); + ExpectIntEQ(wc_CryptoCb_GetDevIdAtIndex(0), INVALID_DEVID); + + ExpectIntEQ(wc_CryptoCb_RegisterDevice(devId, test_CryptoCb_NoOp_Func, + NULL), 0); + ExpectIntEQ(wc_CryptoCb_GetDevIdAtIndex(0), devId); + + /* Re-registering the same device id updates the entry instead of growing + * the device table. */ + ExpectIntEQ(wc_CryptoCb_RegisterDevice(devId, NULL, (void*)1), 0); + ExpectIntEQ(wc_CryptoCb_GetDevIdAtIndex(0), devId); + + wc_CryptoCb_UnRegisterDevice(INVALID_DEVID); + ExpectIntEQ(wc_CryptoCb_GetDevIdAtIndex(0), devId); + +#ifdef WOLF_CRYPTO_CB_CMD + ExpectIntEQ(wc_CryptoCb_RegisterDevice(devId + 1, + test_CryptoCb_RegisterUnavailable_Func, NULL), 0); + ExpectIntEQ(wc_CryptoCb_GetDevIdAtIndex(1), devId + 1); + + ExpectIntEQ(wc_CryptoCb_RegisterDevice(devId + 2, + test_CryptoCb_RegisterFail_Func, NULL), BAD_FUNC_ARG); + ExpectIntEQ(wc_CryptoCb_GetDevIdAtIndex(2), INVALID_DEVID); +#endif + + /* Fill the remaining registration table until it reports full. */ + for (devId += 3; devId < 64; devId++) { + rc = wc_CryptoCb_RegisterDevice(devId, test_CryptoCb_NoOp_Func, NULL); + if (rc != 0) { + break; + } + added++; + } + ExpectIntGT(added, 0); + ExpectIntEQ(rc, BUFFER_E); + + wc_CryptoCb_Cleanup(); + ExpectIntEQ(wc_CryptoCb_GetDevIdAtIndex(0), INVALID_DEVID); +#endif + return EXPECT_RESULT(); +} + /* tlsVer: WOLFSSL_TLSV1_2 or WOLFSSL_TLSV1_3 */ static int test_wc_CryptoCb_TLS(int tlsVer, const char* cliCaPemFile, const char* cliCertPemFile, @@ -34351,6 +34762,19 @@ static int test_ocsp_callback_fails_cb(void* ctx, const char* url, int urlSz, (void)ocspRespBuf; return WOLFSSL_CBIO_ERR_GENERAL; } +static int test_ocsp_callback_missing_resp_cb(void* ctx, const char* url, + int urlSz, byte* ocspReqBuf, int ocspReqSz, + byte** ocspRespBuf) +{ + (void)ctx; + (void)url; + (void)urlSz; + (void)ocspReqBuf; + (void)ocspReqSz; + if (ocspRespBuf != NULL) + *ocspRespBuf = NULL; + return 0; +} static int test_ocsp_callback_fails(void) { WOLFSSL_CTX *ctx_c = NULL; @@ -34381,11 +34805,51 @@ static int test_ocsp_callback_fails(void) return EXPECT_RESULT(); } + +static int test_ocsp_callback_missing_resp(void) +{ + WOLFSSL_CTX *ctx_c = NULL; + WOLFSSL_CTX *ctx_s = NULL; + WOLFSSL *ssl_c = NULL; + WOLFSSL *ssl_s = NULL; + struct test_memio_ctx test_ctx; + EXPECT_DECLS; + + XMEMSET(&test_ctx, 0, sizeof(test_ctx)); + ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, + wolfTLSv1_2_client_method, wolfTLSv1_2_server_method), 0); + ExpectIntEQ(wolfSSL_CTX_EnableOCSPStapling(ctx_c), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CTX_EnableOCSPStapling(ctx_s), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_UseOCSPStapling(ssl_c, WOLFSSL_CSR_OCSP, 0), + WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CTX_SetOCSP_OverrideURL(ctx_s, "http://dummy.test"), + WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CTX_EnableOCSP(ctx_s, WOLFSSL_OCSP_NO_NONCE | + WOLFSSL_OCSP_URL_OVERRIDE), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx_s, caCertFile, 0), + WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_SetOCSP_Cb(ssl_s, test_ocsp_callback_missing_resp_cb, + NULL, NULL), WOLFSSL_SUCCESS); + ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), -1); + ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), + WC_NO_ERR_TRACE(OCSP_INVALID_STATUS)); + + wolfSSL_free(ssl_c); + wolfSSL_free(ssl_s); + wolfSSL_CTX_free(ctx_c); + wolfSSL_CTX_free(ctx_s); + + return EXPECT_RESULT(); +} #else static int test_ocsp_callback_fails(void) { return TEST_SKIPPED; } +static int test_ocsp_callback_missing_resp(void) +{ + return TEST_SKIPPED; +} #endif /* defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \ defined(HAVE_OCSP) && \ defined(HAVE_CERTIFICATE_STATUS_REQUEST) */ @@ -34410,9 +34874,29 @@ static int test_wolfSSL_SSLDisableRead(void) XMEMSET(&test_ctx, 0, sizeof(test_ctx)); + wolfSSL_SSLSetIORecv(NULL, test_wolfSSL_SSLDisableRead_recv); + wolfSSL_SSLSetIOSend(NULL, test_memio_write_cb); + wolfSSL_CTX_SetIORecv(NULL, test_wolfSSL_SSLDisableRead_recv); + wolfSSL_CTX_SetIOSend(NULL, test_memio_write_cb); + wolfSSL_SetIOReadCtx(NULL, &test_ctx); + wolfSSL_SetIOWriteCtx(NULL, &test_ctx); + wolfSSL_SSLDisableRead(NULL); + wolfSSL_SSLEnableRead(NULL); + ExpectNull(wolfSSL_GetIOReadCtx(NULL)); + ExpectNull(wolfSSL_GetIOWriteCtx(NULL)); + ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, NULL, &ssl_c, NULL, wolfTLS_client_method, NULL), 0); + wolfSSL_CTX_SetIORecv(ctx_c, test_wolfSSL_SSLDisableRead_recv); + wolfSSL_CTX_SetIOSend(ctx_c, test_memio_write_cb); + ExpectPtrEq(ctx_c->CBIORecv, test_wolfSSL_SSLDisableRead_recv); + ExpectPtrEq(ctx_c->CBIOSend, test_memio_write_cb); wolfSSL_SSLSetIORecv(ssl_c, test_wolfSSL_SSLDisableRead_recv); + wolfSSL_SSLSetIOSend(ssl_c, test_memio_write_cb); + wolfSSL_SetIOReadCtx(ssl_c, &test_ctx); + wolfSSL_SetIOWriteCtx(ssl_c, &test_ctx); + ExpectPtrEq(wolfSSL_GetIOReadCtx(ssl_c), &test_ctx); + ExpectPtrEq(wolfSSL_GetIOWriteCtx(ssl_c), &test_ctx); wolfSSL_SSLDisableRead(ssl_c); /* Disabling reading should not even go into the IO layer */ @@ -36103,6 +36587,7 @@ TEST_CASE testCases[] = { #ifdef OPENSSL_ALL TEST_DECL(test_wolfSSL_TXT_DB), TEST_DECL(test_wolfSSL_NCONF), + TEST_DECL(test_wolfSSL_NCONF_negative_paths), #endif TEST_DECL(test_wolfSSL_CRYPTO_memcmp), @@ -36195,6 +36680,7 @@ TEST_CASE testCases[] = { TEST_DECL(test_wolfSSL_crypto_policy_ciphers), TEST_DECL(test_wolfSSL_SSL_in_init), TEST_DECL(test_wolfSSL_CTX_set_timeout), + TEST_DECL(test_wolfSSL_session_cache_api_direct), TEST_DECL(test_wolfSSL_set_psk_use_session_callback), TEST_DECL(test_CONF_CTX_FILE), @@ -36263,6 +36749,7 @@ TEST_CASE testCases[] = { TEST_DECL(test_wolfSSL_CTX_trust_peer_cert), TEST_DECL(test_wolfSSL_CTX_LoadCRL), TEST_DECL(test_wolfSSL_CTX_LoadCRL_largeCRLnum), + TEST_DECL(test_wolfSSL_crl_ocsp_object_api), TEST_DECL(test_wolfSSL_crl_update_cb), TEST_DECL(test_wolfSSL_CTX_SetTmpDH_file), TEST_DECL(test_wolfSSL_CTX_SetTmpDH_buffer), @@ -36413,6 +36900,7 @@ TEST_CASE testCases[] = { TEST_DECL(test_wolfSSL_UseOCSPStaplingV2), TEST_DECL(test_self_signed_stapling), TEST_DECL(test_ocsp_callback_fails), + TEST_DECL(test_ocsp_callback_missing_resp), /* Multicast */ TEST_DECL(test_wolfSSL_mcast), @@ -36444,8 +36932,12 @@ TEST_CASE testCases[] = { /* Can't memory test as client/server Asserts in thread. */ TEST_DECL(test_prioritize_psk), +#ifdef WOLF_CRYPTO_CB + /* Can't memory test as client/server hangs. */ + TEST_DECL(test_wc_CryptoCb_registry), /* Can't memory test as client/server hangs. */ TEST_DECL(test_wc_CryptoCb), +#endif /* Can't memory test as client/server hangs. */ TEST_DECL(test_wolfSSL_CTX_StaticMemory), #if !defined(NO_FILESYSTEM) && \ diff --git a/tests/api/test_aes.c b/tests/api/test_aes.c index ef03c20ce4..d6d5dda5be 100644 --- a/tests/api/test_aes.c +++ b/tests/api/test_aes.c @@ -8018,6 +8018,474 @@ int test_wc_AesEaxStream(void) * (!HAVE_FIPS || FIPS_VERSION_GE(5, 3)) && !HAVE_SELFTEST */ +#if !defined(NO_AES) && defined(HAVE_AES_KEYWRAP) && !defined(HAVE_FIPS) && \ + !defined(HAVE_SELFTEST) +typedef struct test_aes_keywrap_vector { + const byte* key; + word32 keySz; + const byte* msg; + word32 msgSz; + const byte* ct; + word32 ctSz; +} test_aes_keywrap_vector; +#endif + +int test_wc_AesKeyWrapVectors(void) +{ + EXPECT_DECLS; +#if !defined(NO_AES) && defined(HAVE_AES_KEYWRAP) && !defined(HAVE_FIPS) && \ + !defined(HAVE_SELFTEST) + static const byte key1[] = { + 0x6f, 0x67, 0x48, 0x6d, 0x1e, 0x91, 0x44, 0x19, + 0xcb, 0x43, 0xc2, 0x85, 0x09, 0xc7, 0xc1, 0xea + }; + static const byte msg1[] = { + 0x8d, 0xc0, 0x63, 0x2d, 0x92, 0xee, 0x0b, 0xe4, + 0xf7, 0x40, 0x02, 0x84, 0x10, 0xb0, 0x82, 0x70 + }; + static const byte ct1[] = { + 0x9d, 0xe4, 0x53, 0xce, 0xd5, 0xd4, 0xab, 0x46, + 0xa5, 0x60, 0x17, 0x08, 0xee, 0xef, 0xef, 0xb5, + 0xe5, 0x93, 0xe6, 0xae, 0x8e, 0x86, 0xb2, 0x6b + }; + static const byte key2[] = { + 0xa0, 0xb1, 0x71, 0x72, 0xbb, 0x29, 0x6d, 0xb7, + 0xf5, 0xc8, 0x69, 0xe9, 0xa3, 0x6b, 0x5c, 0xe3 + }; + static const byte msg2[] = { + 0x61, 0x5d, 0xd0, 0x22, 0xd6, 0x07, 0xc9, 0x10, + 0xf2, 0x01, 0x78, 0xcb, 0xdf, 0x42, 0x06, 0x0f + }; + static const byte ct2[] = { + 0x8c, 0x3a, 0xba, 0x85, 0xcc, 0x0a, 0xe1, 0xae, + 0x10, 0xb3, 0x66, 0x58, 0xb0, 0x68, 0xf5, 0x95, + 0xba, 0xf8, 0xca, 0xaf, 0xb7, 0x45, 0xef, 0x3c + }; + static const byte key3[] = { + 0x0e, 0x49, 0xd5, 0x71, 0xc1, 0x9b, 0x52, 0x50, + 0xef, 0xfd, 0x41, 0xd9, 0x4b, 0xde, 0x39, 0xd6 + }; + static const byte msg3[] = { + 0xf2, 0x5e, 0x4d, 0xe8, 0xca, 0xca, 0x36, 0x3f, + 0xd5, 0xf2, 0x94, 0x42, 0xeb, 0x14, 0x7b, 0x55 + }; + static const byte ct3[] = { + 0x1d, 0xe0, 0x93, 0x65, 0x48, 0x26, 0xf1, 0x8f, + 0xcd, 0x0f, 0x3f, 0xd4, 0x99, 0x41, 0x6f, 0xf2, + 0x2e, 0xd7, 0x5e, 0xe1, 0x2f, 0xe0, 0xb6, 0x24 + }; + static const byte key4[] = { + 0xe0, 0xe1, 0x29, 0x59, 0x10, 0x91, 0x03, 0xe3, + 0x0a, 0xe8, 0xb5, 0x68, 0x4a, 0x22, 0xe6, 0x62 + }; + static const byte msg4[] = { + 0xdb, 0xb0, 0xf2, 0xbb, 0x2b, 0xe9, 0x12, 0xa2, + 0x04, 0x30, 0x97, 0x2d, 0x98, 0x42, 0xce, 0x3f, + 0xd3, 0xb9, 0x28, 0xe5, 0x73, 0xe1, 0xac, 0x8e + }; + static const byte ct4[] = { + 0x9c, 0x3d, 0xdc, 0x23, 0x82, 0x7b, 0x7b, 0x3c, + 0x13, 0x10, 0x5f, 0x9e, 0x8b, 0x11, 0x52, 0x3b, + 0xac, 0xcd, 0xfb, 0x6c, 0x8b, 0x7e, 0x78, 0x25, + 0x49, 0x6e, 0x7a, 0x84, 0x0b, 0xd3, 0x2a, 0xec + }; + static const test_aes_keywrap_vector vectors[] = { + { key1, sizeof(key1), msg1, sizeof(msg1), ct1, sizeof(ct1) }, + { key2, sizeof(key2), msg2, sizeof(msg2), ct2, sizeof(ct2) }, + { key3, sizeof(key3), msg3, sizeof(msg3), ct3, sizeof(ct3) }, + { key4, sizeof(key4), msg4, sizeof(msg4), ct4, sizeof(ct4) } + }; + byte wrapped[40]; + byte unwrapped[32]; + byte tampered[sizeof(ct1)]; + word32 i; + int wrapSz; + int unwrapSz; + + for (i = 0; i < (word32)XELEM_CNT(vectors); i++) { + XMEMSET(wrapped, 0, sizeof(wrapped)); + XMEMSET(unwrapped, 0, sizeof(unwrapped)); + + wrapSz = wc_AesKeyWrap(vectors[i].key, vectors[i].keySz, vectors[i].msg, + vectors[i].msgSz, wrapped, vectors[i].ctSz, NULL); + ExpectIntEQ(wrapSz, (int)vectors[i].ctSz); + ExpectBufEQ(wrapped, vectors[i].ct, vectors[i].ctSz); + + unwrapSz = wc_AesKeyUnWrap(vectors[i].key, vectors[i].keySz, + vectors[i].ct, vectors[i].ctSz, unwrapped, vectors[i].msgSz, NULL); + ExpectIntEQ(unwrapSz, (int)vectors[i].msgSz); + ExpectBufEQ(unwrapped, vectors[i].msg, vectors[i].msgSz); + } + + XMEMCPY(tampered, ct1, sizeof(tampered)); + tampered[sizeof(tampered) - 1] ^= 0x01; + ExpectIntLT(wc_AesKeyUnWrap(key1, sizeof(key1), tampered, sizeof(tampered), + unwrapped, sizeof(msg1), NULL), 0); +#endif + + return EXPECT_RESULT(); +} + +/* + * MC/DC wave 2 — decision-targeted negative paths for AES KeyWrap. + * Existing vector coverage above does not exercise the argument-check, + * short-output-buffer, or misaligned-length decision branches in the + * RFC 3394 wrap/unwrap implementation inside wolfcrypt/src/aes.c. + */ +int test_wc_AesKeyWrapDecisionCoverage(void) +{ + EXPECT_DECLS; +#if !defined(NO_AES) && defined(HAVE_AES_KEYWRAP) && !defined(HAVE_FIPS) && \ + !defined(HAVE_SELFTEST) + static const byte kek[16] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F + }; + static const byte plain[16] = { + 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77, + 0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF + }; + /* Non-multiple-of-8 length to exercise the length-alignment branch. */ + static const byte badLenPlain[15] = { + 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77, + 0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE + }; + byte wrapped[24]; + byte unwrapped[16]; + + /* wc_AesKeyWrap: null key, null in, null out decision branches. */ + ExpectIntEQ(wc_AesKeyWrap(NULL, sizeof(kek), plain, sizeof(plain), + wrapped, sizeof(wrapped), NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wc_AesKeyWrap(kek, sizeof(kek), NULL, sizeof(plain), + wrapped, sizeof(wrapped), NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wc_AesKeyWrap(kek, sizeof(kek), plain, sizeof(plain), + NULL, sizeof(wrapped), NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + /* Output buffer smaller than inSz + KEYWRAP_BLOCK_SIZE: short-buffer + * decision branch. */ + ExpectIntEQ(wc_AesKeyWrap(kek, sizeof(kek), plain, sizeof(plain), + wrapped, sizeof(plain), NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + /* inSz is not a multiple of KEYWRAP_BLOCK_SIZE (8): alignment branch. */ + ExpectIntLT(wc_AesKeyWrap(kek, sizeof(kek), badLenPlain, + sizeof(badLenPlain), wrapped, sizeof(wrapped), NULL), 0); + + /* wc_AesKeyUnWrap: null key, null in, null out decision branches. */ + ExpectIntEQ(wc_AesKeyUnWrap(NULL, sizeof(kek), wrapped, sizeof(wrapped), + unwrapped, sizeof(unwrapped), NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wc_AesKeyUnWrap(kek, sizeof(kek), NULL, sizeof(wrapped), + unwrapped, sizeof(unwrapped), NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wc_AesKeyUnWrap(kek, sizeof(kek), wrapped, sizeof(wrapped), + NULL, sizeof(unwrapped), NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + /* Output buffer smaller than unwrapped size: short-buffer branch. */ + ExpectIntEQ(wc_AesKeyUnWrap(kek, sizeof(kek), wrapped, sizeof(wrapped), + unwrapped, sizeof(wrapped) - 9, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + /* inSz not a multiple of KEYWRAP_BLOCK_SIZE: alignment branch. */ + ExpectIntLT(wc_AesKeyUnWrap(kek, sizeof(kek), wrapped, sizeof(wrapped) - 1, + unwrapped, sizeof(unwrapped), NULL), 0); + +#ifdef WOLFSSL_AES_DIRECT + /* wc_AesKeyWrap_ex / wc_AesKeyUnWrap_ex argument-check branches. */ + { + Aes aes; + XMEMSET(&aes, 0, sizeof(aes)); + ExpectIntEQ(wc_AesInit(&aes, NULL, INVALID_DEVID), 0); + ExpectIntEQ(wc_AesSetKey(&aes, kek, sizeof(kek), NULL, AES_ENCRYPTION), + 0); + + ExpectIntEQ(wc_AesKeyWrap_ex(NULL, plain, sizeof(plain), + wrapped, sizeof(wrapped), NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wc_AesKeyWrap_ex(&aes, NULL, sizeof(plain), + wrapped, sizeof(wrapped), NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wc_AesKeyWrap_ex(&aes, plain, sizeof(plain), + NULL, sizeof(wrapped), NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + + ExpectIntEQ(wc_AesKeyUnWrap_ex(NULL, wrapped, sizeof(wrapped), + unwrapped, sizeof(unwrapped), NULL), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wc_AesKeyUnWrap_ex(&aes, NULL, sizeof(wrapped), + unwrapped, sizeof(unwrapped), NULL), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wc_AesKeyUnWrap_ex(&aes, wrapped, sizeof(wrapped), + NULL, sizeof(unwrapped), NULL), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + + wc_AesFree(&aes); + } +#endif /* WOLFSSL_AES_DIRECT */ +#endif /* !NO_AES && HAVE_AES_KEYWRAP && !HAVE_FIPS && !HAVE_SELFTEST */ + return EXPECT_RESULT(); +} + +/* + * MC/DC wave 2 — decision-targeted negative paths for AES-GCM SetExtIV + * and the short-buffer / bad-length branches left uncovered by the existing + * GCM tests. + */ +int test_wc_AesGcmDecisionCoverage(void) +{ + EXPECT_DECLS; +#if !defined(NO_AES) && defined(HAVE_AESGCM) + static const byte key[16] = { + 0xFE,0xFF,0xE9,0x92,0x86,0x65,0x73,0x1C, + 0x6D,0x6A,0x8F,0x94,0x67,0x30,0x83,0x08 + }; + static const byte iv[GCM_NONCE_MID_SZ] = { + 0xCA,0xFE,0xBA,0xBE,0xFA,0xCE,0xDB,0xAD, + 0xDE,0xCA,0xF8,0x88 + }; + Aes aes; + int initDone = 0; + + XMEMSET(&aes, 0, sizeof(aes)); + ExpectIntEQ(wc_AesInit(&aes, NULL, INVALID_DEVID), 0); + if (EXPECT_SUCCESS()) initDone = 1; + ExpectIntEQ(wc_AesGcmSetKey(&aes, key, sizeof(key)), 0); + + /* wc_AesGcmSetExtIV null-argument decision branches. */ + ExpectIntEQ(wc_AesGcmSetExtIV(NULL, iv, sizeof(iv)), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wc_AesGcmSetExtIV(&aes, NULL, sizeof(iv)), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + /* Zero-length IV branch: should reject. */ + ExpectIntEQ(wc_AesGcmSetExtIV(&aes, iv, 0), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + + /* wc_AesGcmSetKey invalid key-length decision branch. */ + { + static const byte badKey[15] = {0}; + ExpectIntEQ(wc_AesGcmSetKey(&aes, badKey, sizeof(badKey)), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + } + + if (initDone) wc_AesFree(&aes); +#endif + return EXPECT_RESULT(); +} + +/* + * MC/DC wave 2 — feature-oriented positive paths to lift aes.c MC/DC by + * exercising real GCM stream / CCM / GMAC / key-wrap-ex code paths that the + * existing tests skip. + */ +int test_wc_AesFeatureCoverage(void) +{ + EXPECT_DECLS; +#if !defined(NO_AES) && defined(HAVE_AESGCM) + /* ---- AES-GCM streaming API: multi-chunk AAD and data ---- */ +#ifdef WOLFSSL_AESGCM_STREAM + { + static const byte key[32] = { + 0xfe,0xff,0xe9,0x92,0x86,0x65,0x73,0x1c, + 0x6d,0x6a,0x8f,0x94,0x67,0x30,0x83,0x08, + 0xfe,0xff,0xe9,0x92,0x86,0x65,0x73,0x1c, + 0x6d,0x6a,0x8f,0x94,0x67,0x30,0x83,0x08 + }; + static const byte iv[GCM_NONCE_MID_SZ] = { + 0xca,0xfe,0xba,0xbe,0xfa,0xce,0xdb,0xad, + 0xde,0xca,0xf8,0x88 + }; + static const byte aad1[5] = { 0xa1,0xa2,0xa3,0xa4,0xa5 }; + static const byte aad2[7] = { 0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7 }; + static const byte plain[40] = { + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, + 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, + 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27, + 0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f, + 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37 + }; + Aes aes; + byte cipher[sizeof(plain)]; + byte recovered[sizeof(plain)]; + byte tag[AES_BLOCK_SIZE]; + int initDone = 0; + + XMEMSET(&aes, 0, sizeof(aes)); + ExpectIntEQ(wc_AesInit(&aes, NULL, INVALID_DEVID), 0); + if (EXPECT_SUCCESS()) initDone = 1; + + /* Encrypt: feed AAD across two updates, then plaintext across three. */ + ExpectIntEQ(wc_AesGcmEncryptInit(&aes, key, sizeof(key), iv, + sizeof(iv)), 0); + ExpectIntEQ(wc_AesGcmEncryptUpdate(&aes, NULL, NULL, 0, aad1, + sizeof(aad1)), 0); + ExpectIntEQ(wc_AesGcmEncryptUpdate(&aes, cipher, plain, 16, aad2, + sizeof(aad2)), 0); + ExpectIntEQ(wc_AesGcmEncryptUpdate(&aes, cipher + 16, plain + 16, 16, + NULL, 0), 0); + ExpectIntEQ(wc_AesGcmEncryptUpdate(&aes, cipher + 32, plain + 32, 8, + NULL, 0), 0); + ExpectIntEQ(wc_AesGcmEncryptFinal(&aes, tag, sizeof(tag)), 0); + + /* Decrypt: same chunking, must recover plaintext and tag must match. */ + ExpectIntEQ(wc_AesGcmDecryptInit(&aes, key, sizeof(key), iv, + sizeof(iv)), 0); + ExpectIntEQ(wc_AesGcmDecryptUpdate(&aes, NULL, NULL, 0, aad1, + sizeof(aad1)), 0); + ExpectIntEQ(wc_AesGcmDecryptUpdate(&aes, recovered, cipher, 16, aad2, + sizeof(aad2)), 0); + ExpectIntEQ(wc_AesGcmDecryptUpdate(&aes, recovered + 16, cipher + 16, + 16, NULL, 0), 0); + ExpectIntEQ(wc_AesGcmDecryptUpdate(&aes, recovered + 32, cipher + 32, + 8, NULL, 0), 0); + ExpectIntEQ(wc_AesGcmDecryptFinal(&aes, tag, sizeof(tag)), 0); + ExpectBufEQ(recovered, plain, sizeof(plain)); + + /* Tampered tag must be rejected. */ + ExpectIntEQ(wc_AesGcmDecryptInit(&aes, key, sizeof(key), iv, + sizeof(iv)), 0); + ExpectIntEQ(wc_AesGcmDecryptUpdate(&aes, recovered, cipher, + sizeof(plain), aad1, sizeof(aad1)), 0); + ExpectIntEQ(wc_AesGcmDecryptUpdate(&aes, NULL, NULL, 0, aad2, + sizeof(aad2)), 0); + { + byte badTag[AES_BLOCK_SIZE]; + XMEMCPY(badTag, tag, sizeof(badTag)); + badTag[0] ^= 0x01; + ExpectIntLT(wc_AesGcmDecryptFinal(&aes, badTag, sizeof(badTag)), + 0); + } + + if (initDone) wc_AesFree(&aes); + } +#endif /* WOLFSSL_AESGCM_STREAM */ + + /* ---- GMAC: multi-call setup with non-trivial AAD/IV ---- */ + { + Gmac gmac; + static const byte gmacKey[16] = { + 0x77,0xbe,0x63,0x70,0x89,0x71,0xc4,0xe2, + 0x40,0xd1,0xcb,0x79,0xe8,0xd7,0x7f,0xeb + }; + static const byte gmacIv[12] = { + 0xe0,0xe0,0x0f,0x19,0xfe,0xd7,0xba,0x01, + 0x36,0xa7,0x97,0xf3 + }; + static const byte gmacAad[20] = { + 0x7a,0x43,0xec,0x1d,0x9c,0x0a,0x5a,0x78, + 0xa0,0xb1,0x65,0x33,0xa6,0x21,0x3c,0xab, + 0x10,0x11,0x12,0x13 + }; + byte gmacTag[16]; + + XMEMSET(&gmac, 0, sizeof(gmac)); + ExpectIntEQ(wc_AesInit(&gmac.aes, NULL, INVALID_DEVID), 0); + ExpectIntEQ(wc_GmacSetKey(&gmac, gmacKey, sizeof(gmacKey)), 0); + ExpectIntEQ(wc_GmacUpdate(&gmac, gmacIv, sizeof(gmacIv), gmacAad, + sizeof(gmacAad), gmacTag, sizeof(gmacTag)), 0); + wc_AesFree(&gmac.aes); + } +#endif /* !NO_AES && HAVE_AESGCM */ + +#if !defined(NO_AES) && defined(HAVE_AESCCM) + /* ---- AES-CCM round trips with varied AAD / nonce / tag sizes ---- */ + { + static const byte ccmKey[16] = { + 0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7, + 0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf + }; + static const byte ccmNonce13[13] = { + 0x00,0x00,0x00,0x03,0x02,0x01,0x00,0xa0, + 0xa1,0xa2,0xa3,0xa4,0xa5 + }; + static const byte ccmNonce7[7] = { + 0x10,0x11,0x12,0x13,0x14,0x15,0x16 + }; + static const byte ccmAad[8] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 + }; + static const byte ccmPlain[23] = { + 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27, + 0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f, + 0x30,0x31,0x32,0x33,0x34,0x35,0x36 + }; + Aes aes; + byte ccmCipher[sizeof(ccmPlain)]; + byte ccmTag[16]; + byte ccmRecovered[sizeof(ccmPlain)]; + int initDone = 0; + + XMEMSET(&aes, 0, sizeof(aes)); + ExpectIntEQ(wc_AesInit(&aes, NULL, INVALID_DEVID), 0); + if (EXPECT_SUCCESS()) initDone = 1; + ExpectIntEQ(wc_AesCcmSetKey(&aes, ccmKey, sizeof(ccmKey)), 0); + + /* 13-byte nonce, 16-byte tag, 8-byte AAD. */ + ExpectIntEQ(wc_AesCcmEncrypt(&aes, ccmCipher, ccmPlain, + sizeof(ccmPlain), ccmNonce13, sizeof(ccmNonce13), + ccmTag, 16, ccmAad, sizeof(ccmAad)), 0); + ExpectIntEQ(wc_AesCcmDecrypt(&aes, ccmRecovered, ccmCipher, + sizeof(ccmPlain), ccmNonce13, sizeof(ccmNonce13), + ccmTag, 16, ccmAad, sizeof(ccmAad)), 0); + ExpectBufEQ(ccmRecovered, ccmPlain, sizeof(ccmPlain)); + + /* 7-byte nonce, 8-byte tag, no AAD. */ + ExpectIntEQ(wc_AesCcmEncrypt(&aes, ccmCipher, ccmPlain, + sizeof(ccmPlain), ccmNonce7, sizeof(ccmNonce7), + ccmTag, 8, NULL, 0), 0); + ExpectIntEQ(wc_AesCcmDecrypt(&aes, ccmRecovered, ccmCipher, + sizeof(ccmPlain), ccmNonce7, sizeof(ccmNonce7), + ccmTag, 8, NULL, 0), 0); + ExpectBufEQ(ccmRecovered, ccmPlain, sizeof(ccmPlain)); + + /* Tampered tag rejected. */ + ccmTag[0] ^= 0x01; + ExpectIntLT(wc_AesCcmDecrypt(&aes, ccmRecovered, ccmCipher, + sizeof(ccmPlain), ccmNonce7, sizeof(ccmNonce7), + ccmTag, 8, NULL, 0), 0); + + /* Empty plaintext: AAD-only authentication. */ + ExpectIntEQ(wc_AesCcmEncrypt(&aes, NULL, NULL, 0, + ccmNonce13, sizeof(ccmNonce13), + ccmTag, 16, ccmAad, sizeof(ccmAad)), 0); + ExpectIntEQ(wc_AesCcmDecrypt(&aes, NULL, NULL, 0, + ccmNonce13, sizeof(ccmNonce13), + ccmTag, 16, ccmAad, sizeof(ccmAad)), 0); + + if (initDone) wc_AesFree(&aes); + } +#endif /* !NO_AES && HAVE_AESCCM */ + +#if !defined(NO_AES) && defined(HAVE_AES_KEYWRAP) && \ + !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) + /* ---- AES-KeyWrap with explicit non-default IV ---- */ + { + static const byte kwKey[24] = { + 0x8e,0x73,0xb0,0xf7,0xda,0x0e,0x64,0x52, + 0xc8,0x10,0xf3,0x2b,0x80,0x90,0x79,0xe5, + 0x62,0xf8,0xea,0xd2,0x52,0x2c,0x6b,0x7b + }; + static const byte kwPlain[16] = { + 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77, + 0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff + }; + static const byte altIv[8] = { + 0xa6,0xa6,0xa6,0xa6,0xa6,0xa6,0xa6,0xa6 + }; + byte wrapped[sizeof(kwPlain) + KEYWRAP_BLOCK_SIZE]; + byte unwrapped[sizeof(kwPlain)]; + int wrapSz; + + wrapSz = wc_AesKeyWrap(kwKey, sizeof(kwKey), kwPlain, sizeof(kwPlain), + wrapped, sizeof(wrapped), altIv); + ExpectIntEQ(wrapSz, sizeof(wrapped)); + ExpectIntEQ(wc_AesKeyUnWrap(kwKey, sizeof(kwKey), wrapped, + sizeof(wrapped), unwrapped, sizeof(unwrapped), altIv), + sizeof(unwrapped)); + ExpectBufEQ(unwrapped, kwPlain, sizeof(kwPlain)); + + /* Default-IV path: NULL iv selects RFC 3394 default. */ + wrapSz = wc_AesKeyWrap(kwKey, sizeof(kwKey), kwPlain, sizeof(kwPlain), + wrapped, sizeof(wrapped), NULL); + ExpectIntEQ(wrapSz, sizeof(wrapped)); + ExpectIntEQ(wc_AesKeyUnWrap(kwKey, sizeof(kwKey), wrapped, + sizeof(wrapped), unwrapped, sizeof(unwrapped), NULL), + sizeof(unwrapped)); + ExpectBufEQ(unwrapped, kwPlain, sizeof(kwPlain)); + } +#endif /* !NO_AES && HAVE_AES_KEYWRAP && !HAVE_FIPS && !HAVE_SELFTEST */ + + return EXPECT_RESULT(); +} + /*----------------------------------------------------------------------------* | AES-SIV Test *----------------------------------------------------------------------------*/ @@ -8456,6 +8924,14 @@ int test_wc_CryptoCb_AesSetKey(void) ExpectIntEQ(ret, 0); ExpectIntEQ(aes->devId, TEST_CRYPTOCB_AES_DEVID); + /* Direct callback entry guardrails. */ + ExpectIntEQ(wc_CryptoCb_AesSetKey(NULL, key, sizeof(key)), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wc_CryptoCb_AesSetKey(aes, NULL, sizeof(key)), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wc_CryptoCb_AesSetKey(aes, key, 0), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + /* Set key - should trigger CryptoCB and "import" to mock SE */ ret = wc_AesGcmSetKey(aes, key, sizeof(key)); ExpectIntEQ(ret, 0); @@ -8480,6 +8956,18 @@ int test_wc_CryptoCb_AesSetKey(void) ExpectIntEQ(XMEMCMP(aes->devKey, zeroKey, sizeof(key)), 0); } + /* Missing device context should fail in the callback instead of falling + * through as a successful offload path. */ + aes->devCtx = NULL; + ExpectIntEQ(wc_AesGcmEncrypt(aes, cipher, plain, sizeof(plain), + iv, sizeof(iv), authTag, sizeof(authTag), NULL, 0), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + + /* Restore callback-owned state for the rest of the test. */ + ret = wc_AesGcmSetKey(aes, key, sizeof(key)); + ExpectIntEQ(ret, 0); + ExpectPtrEq(aes->devCtx, cryptoCbAesMockHandle); + /* Test encrypt - callback performs crypto using stored key */ ret = wc_AesGcmEncrypt(aes, cipher, plain, sizeof(plain), iv, sizeof(iv), authTag, sizeof(authTag), @@ -8514,6 +9002,8 @@ int test_wc_CryptoCb_AesSetKey(void) /* Cleanup */ wc_CryptoCb_UnRegisterDevice(TEST_CRYPTOCB_AES_DEVID); + ExpectIntEQ(wc_CryptoCb_AesSetKey(aes, key, sizeof(key)), + WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)); /* Test software path (no devId) still works */ XMEMSET(aes, 0, sizeof(Aes)); diff --git a/tests/api/test_aes.h b/tests/api/test_aes.h index 27d15ee602..42893da805 100644 --- a/tests/api/test_aes.h +++ b/tests/api/test_aes.h @@ -56,6 +56,10 @@ int test_wc_AesGcmStream(void); int test_wc_AesGcmStream_MidStreamState(void); int test_wc_AesGcmStream_ReinitAfterFinal(void); int test_wc_AesGcmStream_BadAuthTag(void); +int test_wc_AesKeyWrapVectors(void); +int test_wc_AesKeyWrapDecisionCoverage(void); +int test_wc_AesGcmDecisionCoverage(void); +int test_wc_AesFeatureCoverage(void); int test_wc_AesCcmSetKey(void); int test_wc_AesCcmEncryptDecrypt(void); int test_wc_AesCcmEncryptDecrypt_InPlace(void); @@ -179,6 +183,10 @@ int test_wc_CryptoCb_Tls13_Key_No_Zero_Without_Offload(void); TEST_DECL_GROUP("aes", test_wc_AesGcmStream_MidStreamState), \ TEST_DECL_GROUP("aes", test_wc_AesGcmStream_ReinitAfterFinal), \ TEST_DECL_GROUP("aes", test_wc_AesGcmStream_BadAuthTag), \ + TEST_DECL_GROUP("aes", test_wc_AesKeyWrapVectors), \ + TEST_DECL_GROUP("aes", test_wc_AesKeyWrapDecisionCoverage), \ + TEST_DECL_GROUP("aes", test_wc_AesGcmDecisionCoverage), \ + TEST_DECL_GROUP("aes", test_wc_AesFeatureCoverage), \ TEST_DECL_GROUP("aes", test_wc_AesCcmSetKey), \ TEST_DECL_GROUP("aes", test_wc_AesCcmEncryptDecrypt), \ TEST_DECL_GROUP("aes", test_wc_AesCcmEncryptDecrypt_InPlace), \ diff --git a/tests/api/test_asn.c b/tests/api/test_asn.c index 7e74c03cca..e127e51a84 100644 --- a/tests/api/test_asn.c +++ b/tests/api/test_asn.c @@ -34,6 +34,9 @@ #ifdef HAVE_ED448 #include #endif +#ifdef HAVE_ECC + #include +#endif #ifdef HAVE_DILITHIUM #include #endif @@ -2214,3 +2217,267 @@ int test_ToTraditional_ex_mldsa_bad_params(void) #endif return EXPECT_RESULT(); } + +/* + * MC/DC wave 2 — decision-targeted negative paths for PKCS#8 wrap/parse + * and RSA key decode. Targets argument-check, short-buffer, and + * truncated-DER decision branches in wolfcrypt/src/asn.c without touching + * the library source. + */ +int test_wc_AsnDecisionCoverage(void) +{ + EXPECT_DECLS; + +#if !defined(NO_ASN) && !defined(NO_RSA) && \ + (defined(USE_CERT_BUFFERS_1024) || defined(USE_CERT_BUFFERS_2048)) && \ + !defined(HAVE_FIPS) + /* ---- wc_RsaPublicKeyDecode: truncated / bad-arg decision branches ---- */ + { + RsaKey key; + const byte* derKey; + word32 derKeySz; + word32 idx; + + XMEMSET(&key, 0, sizeof(key)); + ExpectIntEQ(wc_InitRsaKey(&key, HEAP_HINT), 0); + + #ifdef USE_CERT_BUFFERS_2048 + derKey = client_keypub_der_2048; + derKeySz = (word32)sizeof_client_keypub_der_2048; + #else + derKey = client_keypub_der_1024; + derKeySz = (word32)sizeof_client_keypub_der_1024; + #endif + + /* Null arg branches. */ + idx = 0; + ExpectIntEQ(wc_RsaPublicKeyDecode(NULL, &idx, &key, derKeySz), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wc_RsaPublicKeyDecode(derKey, NULL, &key, derKeySz), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wc_RsaPublicKeyDecode(derKey, &idx, NULL, derKeySz), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + + /* Truncated input: header says more data than buffer length. */ + idx = 0; + ExpectIntLT(wc_RsaPublicKeyDecode(derKey, &idx, &key, 4), 0); + + /* wc_RsaPublicKeyDecodeRaw null-arg branches. */ + { + static const byte nBuf[] = { 0xC0 }; + static const byte eBuf[] = { 0x01, 0x00, 0x01 }; + ExpectIntEQ(wc_RsaPublicKeyDecodeRaw(NULL, sizeof(nBuf), + eBuf, sizeof(eBuf), &key), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wc_RsaPublicKeyDecodeRaw(nBuf, sizeof(nBuf), + NULL, sizeof(eBuf), &key), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wc_RsaPublicKeyDecodeRaw(nBuf, sizeof(nBuf), + eBuf, sizeof(eBuf), NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + } + + DoExpectIntEQ(wc_FreeRsaKey(&key), 0); + } + + /* ---- wc_GetPkcs8TraditionalOffset: argument-check branches ---- */ + { + byte buf[8] = { 0x30, 0x82, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00 }; + word32 idx; + + idx = 0; + ExpectIntEQ(wc_GetPkcs8TraditionalOffset(NULL, &idx, sizeof(buf)), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wc_GetPkcs8TraditionalOffset(buf, NULL, sizeof(buf)), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + /* idx >= sz decision branch — any negative return exercises the + * short-input guard (BUFFER_E in current code, but we do not pin + * the exact code here). */ + idx = sizeof(buf); + ExpectIntLT(wc_GetPkcs8TraditionalOffset(buf, &idx, sizeof(buf)), 0); + /* Non-PKCS#8 blob: malformed DER decision branch. */ + { + byte bogus[4] = { 0x00, 0x00, 0x00, 0x00 }; + idx = 0; + ExpectIntLT(wc_GetPkcs8TraditionalOffset(bogus, &idx, + sizeof(bogus)), 0); + } + } + + /* ---- wc_CreatePKCS8Key: size-query and bad-arg branches ---- + * Uses the existing RSA private key DER from certs_test.h to avoid + * runtime key generation (which requires WOLFSSL_KEY_GEN and a usable + * RNG and is not available in every retained lane). */ + { + #ifdef USE_CERT_BUFFERS_2048 + const byte* rsaDer = client_key_der_2048; + word32 rsaDerSz = (word32)sizeof_client_key_der_2048; + #else + const byte* rsaDer = client_key_der_1024; + word32 rsaDerSz = (word32)sizeof_client_key_der_1024; + #endif + byte pkcs8[2048]; + word32 pkcs8Sz; + + /* Size-query: out == NULL should return LENGTH_ONLY_E and set + * outSz. */ + pkcs8Sz = 0; + ExpectIntEQ(wc_CreatePKCS8Key(NULL, &pkcs8Sz, (byte*)rsaDer, + rsaDerSz, RSAk, NULL, 0), + WC_NO_ERR_TRACE(LENGTH_ONLY_E)); + ExpectIntGT(pkcs8Sz, 0); + + /* Null outSz branch. */ + ExpectIntEQ(wc_CreatePKCS8Key(pkcs8, NULL, (byte*)rsaDer, rsaDerSz, + RSAk, NULL, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + } +#endif /* !NO_ASN && !NO_RSA && cert-buffers && !HAVE_FIPS */ + + return EXPECT_RESULT(); +} + +/* + * MC/DC wave 2 — feature-oriented positive paths to lift asn.c MC/DC by + * exercising real cert parsing, PKCS#8 round trips, ECC key decoding, and + * PEM↔DER conversions on the static cert buffers (no new fixtures). + */ +int test_wc_AsnFeatureCoverage(void) +{ + EXPECT_DECLS; +#if !defined(NO_ASN) && !defined(NO_RSA) && \ + defined(USE_CERT_BUFFERS_2048) && !defined(HAVE_FIPS) + /* ---- DecodedCert: full client cert parse, with subject + pubkey ---- */ + { + struct DecodedCert cert; + byte pubKey[512]; + word32 pubKeySz = sizeof(pubKey); + char subject[256]; + word32 subjectSz = sizeof(subject); + + wc_InitDecodedCert(&cert, client_cert_der_2048, + sizeof_client_cert_der_2048, NULL); + ExpectIntEQ(wc_ParseCert(&cert, CERT_TYPE, NO_VERIFY, NULL), 0); + ExpectIntEQ(wc_GetPubKeyDerFromCert(&cert, pubKey, &pubKeySz), 0); + ExpectIntGT(pubKeySz, 0); + ExpectIntEQ(wc_GetDecodedCertSubject(&cert, subject, &subjectSz), 0); + wc_FreeDecodedCert(&cert); + } + + /* ---- DecodedCert: server cert parse and SubjectPublicKeyInfo extract -- */ + { + struct DecodedCert cert; + byte spki[1024]; + word32 spkiSz = sizeof(spki); + + wc_InitDecodedCert(&cert, server_cert_der_2048, + sizeof_server_cert_der_2048, NULL); + ExpectIntEQ(wc_ParseCert(&cert, CERT_TYPE, NO_VERIFY, NULL), 0); + wc_FreeDecodedCert(&cert); + + /* Some retained builds return 0 on success and write spkiSz; others + * return spkiSz directly. Accept any non-negative result and require + * a non-zero output size. */ + ExpectIntGE(wc_GetSubjectPubKeyInfoDerFromCert(server_cert_der_2048, + sizeof_server_cert_der_2048, spki, &spkiSz), 0); + ExpectIntGT(spkiSz, 0); + } + + /* ---- PKCS#8: round trip wrap then offset extract ---- */ + { + byte pkcs8[2048]; + word32 pkcs8Sz = 0; + word32 idx; + int wrapSz; + + /* Size query first. */ + ExpectIntEQ(wc_CreatePKCS8Key(NULL, &pkcs8Sz, + (byte*)client_key_der_2048, sizeof_client_key_der_2048, RSAk, + NULL, 0), WC_NO_ERR_TRACE(LENGTH_ONLY_E)); + ExpectIntGT(pkcs8Sz, 0); + + wrapSz = wc_CreatePKCS8Key(pkcs8, &pkcs8Sz, + (byte*)client_key_der_2048, sizeof_client_key_der_2048, RSAk, + NULL, 0); + ExpectIntGT(wrapSz, 0); + + if (wrapSz > 0) { + idx = 0; + ExpectIntGE(wc_GetPkcs8TraditionalOffset(pkcs8, &idx, + (word32)wrapSz), 0); + ExpectIntGT(idx, 0); + } + } + + /* ---- CA cert parse: exercises CA-specific decision branches ---- */ + { + struct DecodedCert caCert; + wc_InitDecodedCert(&caCert, ca_cert_der_2048, sizeof_ca_cert_der_2048, + NULL); + ExpectIntEQ(wc_ParseCert(&caCert, CA_TYPE, NO_VERIFY, NULL), 0); + wc_FreeDecodedCert(&caCert); + } + + /* ---- Parse server cert a second time with CERT_TYPE + verify off ---- + * to touch ParseCertRelative decision branches that the first pass skips. + */ + { + struct DecodedCert cert2; + wc_InitDecodedCert(&cert2, server_cert_der_2048, + sizeof_server_cert_der_2048, NULL); + ExpectIntEQ(wc_ParseCert(&cert2, CERT_TYPE, NO_VERIFY, NULL), 0); + wc_FreeDecodedCert(&cert2); + } + + /* ---- PEM↔DER conversion round trip on the client cert ---- */ + #ifdef WOLFSSL_DER_TO_PEM + { + byte pem[4096]; + int pemSz; + + pemSz = wc_DerToPem(client_cert_der_2048, sizeof_client_cert_der_2048, + pem, sizeof(pem), CERT_TYPE); + ExpectIntGT(pemSz, 0); + + #ifdef WOLFSSL_PEM_TO_DER + if (pemSz > 0) { + byte der[2048]; + int derSz; + derSz = wc_CertPemToDer(pem, pemSz, der, sizeof(der), CERT_TYPE); + ExpectIntGT(derSz, 0); + if (derSz > 0) + ExpectBufEQ(der, client_cert_der_2048, + sizeof_client_cert_der_2048); + } + #endif + } + #endif /* WOLFSSL_DER_TO_PEM */ +#endif /* !NO_ASN && !NO_RSA && USE_CERT_BUFFERS_2048 && !HAVE_FIPS */ + +#if !defined(NO_ASN) && defined(HAVE_ECC) && \ + defined(USE_CERT_BUFFERS_256) && !defined(HAVE_FIPS) + /* ---- ECC private + public key DER decode round trip ---- */ + { + ecc_key ecKey; + word32 idx = 0; + byte pubKeyDer[256]; + int derSz; + + XMEMSET(&ecKey, 0, sizeof(ecKey)); + ExpectIntEQ(wc_ecc_init(&ecKey), 0); + ExpectIntEQ(wc_EccPrivateKeyDecode(ecc_clikey_der_256, &idx, &ecKey, + sizeof_ecc_clikey_der_256), 0); + + derSz = wc_EccPublicKeyToDer(&ecKey, pubKeyDer, sizeof(pubKeyDer), 1); + ExpectIntGT(derSz, 0); + + if (derSz > 0) { + ecc_key pubOnly; + word32 idx2 = 0; + XMEMSET(&pubOnly, 0, sizeof(pubOnly)); + ExpectIntEQ(wc_ecc_init(&pubOnly), 0); + ExpectIntEQ(wc_EccPublicKeyDecode(pubKeyDer, &idx2, &pubOnly, + (word32)derSz), 0); + wc_ecc_free(&pubOnly); + } + wc_ecc_free(&ecKey); + } +#endif /* !NO_ASN && HAVE_ECC && USE_CERT_BUFFERS_256 && !HAVE_FIPS */ + return EXPECT_RESULT(); +} diff --git a/tests/api/test_asn.h b/tests/api/test_asn.h index d48aac7a6f..4bd375179e 100644 --- a/tests/api/test_asn.h +++ b/tests/api/test_asn.h @@ -42,6 +42,8 @@ int test_ToTraditional_ex_handcrafted(void); int test_ToTraditional_ex_roundtrip(void); int test_ToTraditional_ex_negative(void); int test_ToTraditional_ex_mldsa_bad_params(void); +int test_wc_AsnDecisionCoverage(void); +int test_wc_AsnFeatureCoverage(void); #define TEST_ASN_DECLS \ TEST_DECL_GROUP("asn", test_SetAsymKeyDer), \ @@ -61,6 +63,8 @@ int test_ToTraditional_ex_mldsa_bad_params(void); TEST_DECL_GROUP("asn", test_ToTraditional_ex_handcrafted), \ TEST_DECL_GROUP("asn", test_ToTraditional_ex_roundtrip), \ TEST_DECL_GROUP("asn", test_ToTraditional_ex_negative), \ - TEST_DECL_GROUP("asn", test_ToTraditional_ex_mldsa_bad_params) + TEST_DECL_GROUP("asn", test_ToTraditional_ex_mldsa_bad_params), \ + TEST_DECL_GROUP("asn", test_wc_AsnDecisionCoverage), \ + TEST_DECL_GROUP("asn", test_wc_AsnFeatureCoverage) #endif /* WOLFCRYPT_TEST_ASN_H */ diff --git a/tests/api/test_certman.c b/tests/api/test_certman.c index 419f16c673..25c203a4b2 100644 --- a/tests/api/test_certman.c +++ b/tests/api/test_certman.c @@ -716,20 +716,29 @@ int test_wolfSSL_CertManagerSetVerify(void) ExpectNotNull(cm = wolfSSL_CertManagerNew()); - wolfSSL_CertManagerSetVerify(cm, myVerify); - #if defined(NO_WOLFSSL_CLIENT) && defined(NO_WOLFSSL_SERVER) ExpectIntEQ(wolfSSL_CertManagerLoadCA(cm, ca_cert, NULL), -1); #else ExpectIntEQ(wolfSSL_CertManagerLoadCA(cm, ca_cert, NULL), WOLFSSL_SUCCESS); + /* Exercise the baseline verification path before the callback overrides + * the result, so the expired-cert failure remains visible to MC/DC. */ + ExpectIntNE(wolfSSL_CertManagerVerify(cm, expiredCert, + CERT_FILETYPE), WOLFSSL_SUCCESS); #endif + + wolfSSL_CertManagerSetVerify(cm, myVerify); /* Use the test CB that always accepts certs */ myVerifyAction = VERIFY_OVERRIDE_ERROR; ExpectIntEQ(wolfSSL_CertManagerVerify(cm, expiredCert, CERT_FILETYPE), WOLFSSL_SUCCESS); + wolfSSL_CertManagerSetVerify(cm, NULL); + ExpectIntNE(wolfSSL_CertManagerVerify(cm, expiredCert, + CERT_FILETYPE), WOLFSSL_SUCCESS); + wolfSSL_CertManagerSetVerify(cm, myVerify); + #ifdef WOLFSSL_ALWAYS_VERIFY_CB { const char* verifyCert = "./certs/server-cert.der"; @@ -2425,6 +2434,10 @@ int test_wolfSSL_CertManagerCRL(void) WOLFSSL_FILETYPE_ASN1), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wolfSSL_CertManagerLoadCRLBuffer(cm, crl_buff, -1, WOLFSSL_FILETYPE_ASN1), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntNE(wolfSSL_CertManagerLoadCRLBuffer(cm, crl_buff, 0, + WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + ExpectIntNE(wolfSSL_CertManagerLoadCRLBuffer(cm, crl_buff, + sizeof(crl_buff) - 1, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_CertManagerFreeCRL(NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); diff --git a/tests/api/test_ocsp.c b/tests/api/test_ocsp.c index 5ebed3b390..7ae1161942 100644 --- a/tests/api/test_ocsp.c +++ b/tests/api/test_ocsp.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #if defined(HAVE_OCSP) && !defined(NO_SHA) && !defined(NO_RSA) @@ -45,6 +46,38 @@ struct test_conf { int targetCertSz; }; +struct wolfio_http_test_ctx { + const char* data; + int dataSz; + int offset; + int maxChunk; + int finalRet; +}; + +static int wolfio_http_test_io_cb(char* buf, int sz, void* ctx) +{ + struct wolfio_http_test_ctx* ioCtx = (struct wolfio_http_test_ctx*)ctx; + int copySz; + + if (ioCtx == NULL) + return WOLFSSL_FATAL_ERROR; + + if (ioCtx->offset >= ioCtx->dataSz) + return ioCtx->finalRet; + + copySz = ioCtx->dataSz - ioCtx->offset; + if (copySz > sz) + copySz = sz; + if (ioCtx->maxChunk > 0 && copySz > ioCtx->maxChunk) + copySz = ioCtx->maxChunk; + if (copySz <= 0) + return WOLFSSL_FATAL_ERROR; + + XMEMCPY(buf, ioCtx->data + ioCtx->offset, (size_t)copySz); + ioCtx->offset += copySz; + return copySz; +} + static int ocsp_cb(void* ctx, const char* url, int urlSz, unsigned char* req, int reqSz, unsigned char** respBuf) { @@ -100,6 +133,26 @@ int test_ocsp_response_parsing(void) EXPECT_DECLS; struct test_conf conf; int expectedRet; + char urlName[80]; + char urlPath[80]; + word16 urlPort = 0; + byte reqBuf[256]; + byte httpBuf[128]; + byte* httpResp = NULL; + static const char* ocspAppStrList[] = { + "application/ocsp-response", + NULL + }; + struct wolfio_http_test_ctx ioCtx; + static const char validHttpResp[] = + "HTTP/1.1 200 OK\r\n" + "Content-Type: application/ocsp-response\r\n" + "Content-Length: 3\r\n" + "\r\n" + "abc"; + static const char headerEarlyEndResp[] = + "HTTP/1.1 200 OK\r\n" + "\r\n"; conf.resp = (unsigned char*)resp; conf.respSz = sizeof(resp); @@ -161,6 +214,81 @@ int test_ocsp_response_parsing(void) conf.targetCertSz = sizeof(intermediate1_ca_cert_pem); ExpectIntEQ(test_ocsp_response_with_cm(&conf, WOLFSSL_SUCCESS), TEST_SUCCESS); + + /* Truncated and empty responses should be rejected during decode. */ + conf.resp = (unsigned char*)resp; + conf.respSz = sizeof(resp) - 1; + conf.ca0 = root_ca_cert_pem; + conf.ca0Sz = sizeof(root_ca_cert_pem); + conf.ca1 = NULL; + conf.ca1Sz = 0; + conf.targetCert = intermediate1_ca_cert_pem; + conf.targetCertSz = sizeof(intermediate1_ca_cert_pem); + ExpectIntEQ(test_ocsp_response_with_cm(&conf, OCSP_LOOKUP_FAIL), + TEST_SUCCESS); + + conf.resp = (unsigned char*)resp; + conf.respSz = 0; + conf.ca0 = root_ca_cert_pem; + conf.ca0Sz = sizeof(root_ca_cert_pem); + conf.ca1 = NULL; + conf.ca1Sz = 0; + conf.targetCert = intermediate1_ca_cert_pem; + conf.targetCertSz = sizeof(intermediate1_ca_cert_pem); + ExpectIntEQ(test_ocsp_response_with_cm(&conf, OCSP_LOOKUP_FAIL), + TEST_SUCCESS); + + /* wolfio helpers used by OCSP/CRL lookup should reject malformed inputs + * and accept a compact valid HTTP response. */ + XMEMSET(urlName, 0, sizeof(urlName)); + XMEMSET(urlPath, 0, sizeof(urlPath)); + ExpectIntEQ(wolfIO_DecodeUrl(NULL, 0, urlName, urlPath, &urlPort), -1); + ExpectIntEQ(urlName[0], 0); + ExpectIntEQ(urlPath[0], 0); + ExpectIntEQ(urlPort, 0); + ExpectIntEQ(wolfIO_DecodeUrl("http://example.com:abc/", 23, + urlName, urlPath, &urlPort), WOLFSSL_FATAL_ERROR); + ExpectIntEQ(wolfIO_DecodeUrl("http://example.com/ocsp", + (int)XSTRLEN("http://example.com/ocsp"), urlName, urlPath, &urlPort), + 0); + ExpectBufEQ(urlName, "example.com", (int)sizeof("example.com")); + ExpectBufEQ(urlPath, "/ocsp", (int)sizeof("/ocsp")); + ExpectIntEQ(urlPort, 80); + + ExpectIntEQ(wolfIO_HttpBuildRequest("POST", "example.com", "/ocsp", 5, 3, + "application/ocsp-request", reqBuf, 8), 0); + ExpectIntGT(wolfIO_HttpBuildRequest("POST", "example.com", "/ocsp", 5, 3, + "application/ocsp-request", reqBuf, (int)sizeof(reqBuf)), 0); + + XMEMSET(&ioCtx, 0, sizeof(ioCtx)); + ioCtx.data = validHttpResp; + ioCtx.dataSz = (int)sizeof(validHttpResp) - 1; + ioCtx.maxChunk = 7; + ioCtx.finalRet = WOLFSSL_FATAL_ERROR; + ExpectIntEQ(wolfIO_HttpProcessResponseGenericIO(wolfio_http_test_io_cb, + &ioCtx, ocspAppStrList, &httpResp, httpBuf, (int)sizeof(httpBuf), + DYNAMIC_TYPE_OCSP, NULL), 3); + ExpectNotNull(httpResp); + if (httpResp != NULL) { + ExpectBufEQ(httpResp, "abc", 3); + XFREE(httpResp, NULL, DYNAMIC_TYPE_OCSP); + httpResp = NULL; + } + + XMEMSET(&ioCtx, 0, sizeof(ioCtx)); + ioCtx.finalRet = WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_WANT_READ); + ExpectIntEQ(wolfIO_HttpProcessResponseGenericIO(wolfio_http_test_io_cb, + &ioCtx, ocspAppStrList, &httpResp, httpBuf, (int)sizeof(httpBuf), + DYNAMIC_TYPE_OCSP, NULL), OCSP_WANT_READ); + + XMEMSET(&ioCtx, 0, sizeof(ioCtx)); + ioCtx.data = headerEarlyEndResp; + ioCtx.dataSz = (int)sizeof(headerEarlyEndResp) - 1; + ioCtx.maxChunk = 9; + ioCtx.finalRet = WOLFSSL_FATAL_ERROR; + ExpectIntEQ(wolfIO_HttpProcessResponseGenericIO(wolfio_http_test_io_cb, + &ioCtx, ocspAppStrList, &httpResp, httpBuf, (int)sizeof(httpBuf), + DYNAMIC_TYPE_OCSP, NULL), HTTP_HEADER_ERR); return EXPECT_SUCCESS(); } #else /* HAVE_OCSP && !NO_SHA */ diff --git a/tests/api/test_ossl_x509.c b/tests/api/test_ossl_x509.c index f6120c14ac..d0d31b7ab0 100644 --- a/tests/api/test_ossl_x509.c +++ b/tests/api/test_ossl_x509.c @@ -1050,10 +1050,6 @@ int test_wolfSSL_X509_check_ip_asc(void) WOLFSSL_FILETYPE_PEM)); ExpectNotNull(empty = wolfSSL_X509_new()); -#if 0 - /* TODO: add cert gen for testing positive case */ - ExpectIntEQ(wolfSSL_X509_check_ip_asc(x509, "127.0.0.1", 0), 1); -#endif ExpectIntEQ(wolfSSL_X509_check_ip_asc(x509, "0.0.0.0", 0), 0); ExpectIntEQ(wolfSSL_X509_check_ip_asc(x509, NULL, 0), 0); ExpectIntEQ(wolfSSL_X509_check_ip_asc(NULL, NULL, 0), 0); @@ -1179,6 +1175,7 @@ int test_wolfSSL_X509_bad_altname(void) int certSize = (int)sizeof(malformed_alt_name_cert) / sizeof(unsigned char); const char *name = "aaaaa"; int nameLen = (int)XSTRLEN(name); + const char badName[] = { 'a', 'a', '\0', 'a', 'a', 'a' }; ExpectNotNull(x509 = wolfSSL_X509_load_certificate_buffer( malformed_alt_name_cert, certSize, SSL_FILETYPE_ASN1)); @@ -1191,6 +1188,14 @@ int test_wolfSSL_X509_bad_altname(void) ExpectIntNE(wolfSSL_X509_check_host(x509, name, nameLen, WOLFSSL_ALWAYS_CHECK_SUBJECT | WOLFSSL_LEFT_MOST_WILDCARD_ONLY, NULL), 1); + /* Len handling must not rescue a malformed SAN. */ + ExpectIntNE(wolfSSL_X509_check_host(x509, name, 0, + WOLFSSL_ALWAYS_CHECK_SUBJECT, NULL), 1); + ExpectIntNE(wolfSSL_X509_check_host(x509, name, nameLen + 1, + WOLFSSL_ALWAYS_CHECK_SUBJECT, NULL), 1); + /* Embedded NUL in the compared host name must also be rejected. */ + ExpectIntNE(wolfSSL_X509_check_host(x509, badName, 6, + WOLFSSL_ALWAYS_CHECK_SUBJECT, NULL), 1); X509_free(x509); @@ -1295,6 +1300,9 @@ int test_wolfSSL_X509_name_match1(void) int nameLen3 = (int)(XSTRLEN(name3)); const char *name4 = "bbb"; int nameLen4 = (int)(XSTRLEN(name4)); + const char *name5 = "aaaaa"; + int nameLen5 = 6; + const char badName[] = { 'a', 'a', '\0', 'a', 'a', 'a' }; ExpectNotNull(x509 = wolfSSL_X509_load_certificate_buffer( cert_der, certSize, WOLFSSL_FILETYPE_ASN1)); @@ -1311,6 +1319,14 @@ int test_wolfSSL_X509_name_match1(void) /* Ensure that "a*" does not match "bbb" */ ExpectIntNE(wolfSSL_X509_check_host(x509, name4, nameLen4, WOLFSSL_ALWAYS_CHECK_SUBJECT, NULL), 1); + /* OpenSSL-compatible len handling should still accept the positive case. */ + ExpectIntEQ(wolfSSL_X509_check_host(x509, name5, 0, + WOLFSSL_ALWAYS_CHECK_SUBJECT, NULL), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_X509_check_host(x509, name5, nameLen5, + WOLFSSL_ALWAYS_CHECK_SUBJECT, NULL), WOLFSSL_SUCCESS); + /* Embedded NUL in the compared host name must be rejected. */ + ExpectIntNE(wolfSSL_X509_check_host(x509, badName, 6, + WOLFSSL_ALWAYS_CHECK_SUBJECT, NULL), WOLFSSL_SUCCESS); /* WOLFSSL_LEFT_MOST_WILDCARD_ONLY flag should fail on all cases, since * 'a*' alt name does not have wildcard left-most */ @@ -1584,6 +1600,10 @@ int test_wolfSSL_X509_name_match3(void) int nameLen2 = (int)(XSTRLEN(name2)); const char *name3 = "example.com"; int nameLen3 = (int)(XSTRLEN(name3)); + const char *name4 = "foo.example.com"; + int nameLen4 = (int)(XSTRLEN(name4)) + 1; + const char badName[] = { 'f', 'o', 'o', '.', 'e', 'x', '\0', 'a', 'm', + 'p', 'l', 'e', '.', 'c', 'o', 'm' }; ExpectNotNull(x509 = wolfSSL_X509_load_certificate_buffer( cert_der, certSize, WOLFSSL_FILETYPE_ASN1)); @@ -1591,12 +1611,20 @@ int test_wolfSSL_X509_name_match3(void) /* Ensure that "*.example.com" matches "foo.example.com" */ ExpectIntEQ(wolfSSL_X509_check_host(x509, name1, nameLen1, WOLFSSL_ALWAYS_CHECK_SUBJECT, NULL), WOLFSSL_SUCCESS); + /* strlen()-driven and NUL-inclusive lengths should both preserve match. */ + ExpectIntEQ(wolfSSL_X509_check_host(x509, name1, 0, + WOLFSSL_ALWAYS_CHECK_SUBJECT, NULL), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_X509_check_host(x509, name4, nameLen4, + WOLFSSL_ALWAYS_CHECK_SUBJECT, NULL), WOLFSSL_SUCCESS); /* Ensure that "*.example.com" does NOT match "x.y.example.com" */ ExpectIntNE(wolfSSL_X509_check_host(x509, name2, nameLen2, WOLFSSL_ALWAYS_CHECK_SUBJECT, NULL), WOLFSSL_SUCCESS); /* Ensure that "*.example.com" does NOT match "example.com" */ ExpectIntNE(wolfSSL_X509_check_host(x509, name3, nameLen3, WOLFSSL_ALWAYS_CHECK_SUBJECT, NULL), WOLFSSL_SUCCESS); + /* Embedded NUL must remain rejected. */ + ExpectIntNE(wolfSSL_X509_check_host(x509, badName, (int)sizeof(badName), + WOLFSSL_ALWAYS_CHECK_SUBJECT, NULL), WOLFSSL_SUCCESS); /* WOLFSSL_LEFT_MOST_WILDCARD_ONLY, should match "foo.example.com" */ ExpectIntEQ(wolfSSL_X509_check_host(x509, name1, nameLen1, @@ -2081,4 +2109,3 @@ int test_wolfSSL_X509_cmp(void) #endif return EXPECT_RESULT(); } - diff --git a/tests/api/test_ossl_x509_ext.c b/tests/api/test_ossl_x509_ext.c index af4f991ada..1a8f24ae9d 100644 --- a/tests/api/test_ossl_x509_ext.c +++ b/tests/api/test_ossl_x509_ext.c @@ -41,7 +41,7 @@ int test_wolfSSL_X509_get_extension_flags(void) { EXPECT_DECLS; -#if defined(OPENSSL_ALL) && !defined(NO_RSA) +#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && !defined(NO_RSA) XFILE f = XBADFILE; X509* x509 = NULL; unsigned int extFlags; @@ -94,14 +94,15 @@ int test_wolfSSL_X509_get_extension_flags(void) ExpectIntEQ(X509_get_extension_flags(x509), extFlags); ExpectIntEQ(X509_get_key_usage(x509), keyUsageFlags); X509_free(x509); -#endif /* OPENSSL_ALL */ +#endif return EXPECT_RESULT(); } int test_wolfSSL_X509_get_ext(void) { EXPECT_DECLS; -#if !defined(NO_FILESYSTEM) && defined(OPENSSL_ALL) && !defined(NO_RSA) +#if !defined(NO_FILESYSTEM) && \ + (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && !defined(NO_RSA) int ret = 0; XFILE f = XBADFILE; WOLFSSL_X509* x509 = NULL; @@ -137,7 +138,7 @@ int test_wolfSSL_X509_get_ext(void) int test_wolfSSL_X509_get_ext_by_NID(void) { EXPECT_DECLS; -#if defined(OPENSSL_ALL) && !defined(NO_RSA) +#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && !defined(NO_RSA) int rc = 0; XFILE f = XBADFILE; WOLFSSL_X509* x509 = NULL; @@ -187,7 +188,7 @@ int test_wolfSSL_X509_get_ext_by_NID(void) int test_wolfSSL_X509_get_ext_subj_alt_name(void) { EXPECT_DECLS; -#if defined(OPENSSL_ALL) && !defined(NO_RSA) +#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && !defined(NO_RSA) int rc = 0; XFILE f = XBADFILE; WOLFSSL_X509* x509 = NULL; @@ -219,7 +220,7 @@ int test_wolfSSL_X509_get_ext_subj_alt_name(void) int test_wolfSSL_X509_set_ext(void) { EXPECT_DECLS; -#if defined(OPENSSL_ALL) && !defined(NO_RSA) +#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && !defined(NO_RSA) WOLFSSL_X509* x509 = NULL; XFILE f = XBADFILE; int loc; @@ -250,7 +251,7 @@ int test_wolfSSL_X509_set_ext(void) return EXPECT_RESULT(); } -#if defined(OPENSSL_ALL) +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) static int test_X509_add_basic_constraints(WOLFSSL_X509* x509) { EXPECT_DECLS; @@ -524,7 +525,7 @@ static int test_x509_add_subj_key_id(WOLFSSL_X509* x509) int test_wolfSSL_X509_add_ext(void) { EXPECT_DECLS; -#if defined(OPENSSL_ALL) +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) WOLFSSL_X509* x509 = NULL; WOLFSSL_X509_EXTENSION* ext_empty = NULL; WOLFSSL_X509_EXTENSION* ext = NULL; @@ -662,8 +663,8 @@ int test_wolfSSL_X509_add_ext_dirname_san_rejected(void) int test_wolfSSL_X509_get_ext_count(void) { EXPECT_DECLS; -#if defined(OPENSSL_ALL) && !defined(NO_CERTS) && !defined(NO_FILESYSTEM) && \ - !defined(NO_RSA) +#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && \ + !defined(NO_CERTS) && !defined(NO_FILESYSTEM) && !defined(NO_RSA) int ret = 0; WOLFSSL_X509* x509 = NULL; const char ocspRootCaFile[] = "./certs/ocsp/root-ca-cert.pem"; @@ -752,7 +753,7 @@ int test_wolfSSL_X509_stack_extensions(void) int test_wolfSSL_X509_EXTENSION_new(void) { EXPECT_DECLS; -#if defined (OPENSSL_ALL) +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) WOLFSSL_X509_EXTENSION* ext = NULL; ExpectNotNull(ext = wolfSSL_X509_EXTENSION_new()); @@ -767,7 +768,7 @@ int test_wolfSSL_X509_EXTENSION_new(void) int test_wolfSSL_X509_EXTENSION_dup(void) { EXPECT_DECLS; -#if defined (OPENSSL_ALL) +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) WOLFSSL_X509_EXTENSION* ext = NULL; WOLFSSL_X509_EXTENSION* dup = NULL; @@ -784,7 +785,8 @@ int test_wolfSSL_X509_EXTENSION_dup(void) int test_wolfSSL_X509_EXTENSION_get_object(void) { EXPECT_DECLS; -#if !defined(NO_FILESYSTEM) && defined(OPENSSL_ALL) && !defined(NO_RSA) +#if !defined(NO_FILESYSTEM) && \ + (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && !defined(NO_RSA) WOLFSSL_X509* x509 = NULL; WOLFSSL_X509_EXTENSION* ext = NULL; WOLFSSL_X509_EXTENSION* dup = NULL; @@ -815,7 +817,8 @@ int test_wolfSSL_X509_EXTENSION_get_object(void) int test_wolfSSL_X509_EXTENSION_get_data(void) { EXPECT_DECLS; -#if !defined(NO_FILESYSTEM) && defined(OPENSSL_ALL) && !defined(NO_RSA) +#if !defined(NO_FILESYSTEM) && \ + (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && !defined(NO_RSA) WOLFSSL_X509* x509 = NULL; WOLFSSL_X509_EXTENSION* ext = NULL; WOLFSSL_ASN1_STRING* str = NULL; @@ -850,7 +853,8 @@ int test_wolfSSL_X509_EXTENSION_get_data(void) int test_wolfSSL_X509_EXTENSION_get_critical(void) { EXPECT_DECLS; -#if !defined(NO_FILESYSTEM) && defined(OPENSSL_ALL) && !defined(NO_RSA) +#if !defined(NO_FILESYSTEM) && \ + (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && !defined(NO_RSA) WOLFSSL_X509* x509 = NULL; WOLFSSL_X509_EXTENSION* ext = NULL; XFILE file = XBADFILE; @@ -874,13 +878,15 @@ int test_wolfSSL_X509_EXTENSION_get_critical(void) int test_wolfSSL_X509_EXTENSION_create_by_OBJ(void) { EXPECT_DECLS; -#if !defined(NO_FILESYSTEM) && defined(OPENSSL_ALL) && !defined(NO_RSA) +#if !defined(NO_FILESYSTEM) && \ + (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && !defined(NO_RSA) XFILE file = XBADFILE; WOLFSSL_X509* x509 = NULL; WOLFSSL_X509* empty = NULL; WOLFSSL_X509_EXTENSION* ext = NULL; WOLFSSL_X509_EXTENSION* ext2 = NULL; WOLFSSL_X509_EXTENSION* ext3 = NULL; + WOLFSSL_X509_EXTENSION* found = NULL; WOLFSSL_ASN1_OBJECT* o = NULL; int crit = 0; WOLFSSL_ASN1_STRING* str = NULL; @@ -893,6 +899,11 @@ int test_wolfSSL_X509_EXTENSION_create_by_OBJ(void) ExpectNotNull(o = wolfSSL_X509_EXTENSION_get_object(ext)); ExpectIntEQ(crit = wolfSSL_X509_EXTENSION_get_critical(ext), 0); + ExpectIntEQ(wolfSSL_X509_EXTENSION_set_critical(NULL, 1), WOLFSSL_FAILURE); + ExpectIntEQ(wolfSSL_X509_EXTENSION_set_critical(ext, 1), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_X509_EXTENSION_get_critical(ext), 1); + ExpectIntEQ(wolfSSL_X509_EXTENSION_set_critical(ext, 0), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_X509_EXTENSION_get_critical(ext), 0); ExpectNotNull(str = wolfSSL_X509_EXTENSION_get_data(ext)); ExpectNull(wolfSSL_X509_EXTENSION_create_by_OBJ(NULL, NULL, 0, NULL)); @@ -929,6 +940,9 @@ int test_wolfSSL_X509_EXTENSION_create_by_OBJ(void) ExpectIntEQ(wolfSSL_X509_get_ext_by_OBJ(x509, o, -2), 0); ExpectIntEQ(wolfSSL_X509_get_ext_by_OBJ(x509, o, 0), WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)); + ExpectNotNull(found = wolfSSL_X509_get_ext(x509, 0)); + ExpectNotNull(found->obj); + ExpectIntEQ(wolfSSL_X509_get_ext_by_OBJ(x509, found->obj, -1), 0); wolfSSL_X509_free(x509); #endif @@ -984,7 +998,8 @@ int test_wolfSSL_X509V3_set_ctx(void) int test_wolfSSL_X509V3_EXT_get(void) { EXPECT_DECLS; -#if !defined(NO_FILESYSTEM) && defined(OPENSSL_ALL) && !defined(NO_RSA) +#if !defined(NO_FILESYSTEM) && \ + (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && !defined(NO_RSA) XFILE f = XBADFILE; int numOfExt =0; int extNid = 0; @@ -1053,7 +1068,7 @@ int test_wolfSSL_X509V3_EXT_get(void) int test_wolfSSL_X509V3_EXT_nconf(void) { EXPECT_DECLS; -#ifdef OPENSSL_ALL +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) const char *ext_names[] = { "subjectKeyIdentifier", "authorityKeyIdentifier", @@ -1164,7 +1179,8 @@ int test_wolfSSL_X509V3_EXT_nconf(void) int test_wolfSSL_X509V3_EXT_bc(void) { EXPECT_DECLS; -#if !defined(NO_FILESYSTEM) && defined(OPENSSL_ALL) && !defined(NO_RSA) +#if !defined(NO_FILESYSTEM) && \ + (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && !defined(NO_RSA) WOLFSSL_X509_EXTENSION* ext = NULL; WOLFSSL_ASN1_OBJECT* obj = NULL; WOLFSSL_BASIC_CONSTRAINTS* bc = NULL; @@ -1298,7 +1314,8 @@ int test_wolfSSL_X509_get_ext_d2i_basic_constraints(void) int test_wolfSSL_X509V3_EXT_san(void) { EXPECT_DECLS; -#if !defined(NO_FILESYSTEM) && defined(OPENSSL_ALL) && !defined(NO_RSA) +#if !defined(NO_FILESYSTEM) && \ + (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && !defined(NO_RSA) WOLFSSL_X509_EXTENSION* ext = NULL; WOLFSSL_ASN1_OBJECT* obj = NULL; WOLFSSL_STACK* sk = NULL; @@ -1333,7 +1350,8 @@ int test_wolfSSL_X509V3_EXT_san(void) int test_wolfSSL_X509V3_EXT_aia(void) { EXPECT_DECLS; -#if !defined(NO_FILESYSTEM) && defined(OPENSSL_ALL) && !defined(NO_RSA) +#if !defined(NO_FILESYSTEM) && \ + (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && !defined(NO_RSA) WOLFSSL_X509_EXTENSION* ext = NULL; WOLFSSL_ASN1_OBJECT* obj = NULL; WOLFSSL_STACK* sk = NULL; @@ -1397,7 +1415,8 @@ int test_wolfSSL_X509V3_EXT_aia(void) int test_wolfSSL_X509V3_EXT(void) { EXPECT_DECLS; -#if !defined(NO_FILESYSTEM) && defined(OPENSSL_ALL) && !defined(NO_RSA) +#if !defined(NO_FILESYSTEM) && \ + (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && !defined(NO_RSA) XFILE f = XBADFILE; int numOfExt = 0, nid = 0, i = 0, expected, actual = 0; char* str = NULL; @@ -1414,6 +1433,7 @@ int test_wolfSSL_X509V3_EXT(void) WOLFSSL_BASIC_CONSTRAINTS* bc = NULL; WOLFSSL_ACCESS_DESCRIPTION* ad = NULL; WOLFSSL_GENERAL_NAME* gn = NULL; + int critical = -1; /* Check NULL argument */ ExpectNull(wolfSSL_X509V3_EXT_d2i(NULL)); @@ -1459,6 +1479,14 @@ int test_wolfSSL_X509V3_EXT(void) ExpectNotNull(obj = wolfSSL_X509_EXTENSION_get_object(ext)); ExpectIntEQ((nid = wolfSSL_OBJ_obj2nid(obj)), NID_basic_constraints); ExpectNotNull(bc = (WOLFSSL_BASIC_CONSTRAINTS*)wolfSSL_X509V3_EXT_d2i(ext)); + critical = -1; + ExpectNotNull(ext2 = X509_get_ext_d2i(x509, NID_basic_constraints, + &critical, NULL)); + ExpectIntNE(critical, -1); + ext2 = NULL; + ExpectNotNull(ext2 = wolfSSL_X509V3_EXT_i2d(NID_basic_constraints, 1, bc)); + X509_EXTENSION_free(ext2); + ext2 = NULL; ExpectIntEQ(bc->ca, 1); ExpectNull(bc->pathlen); @@ -1472,6 +1500,11 @@ int test_wolfSSL_X509V3_EXT(void) ExpectIntEQ((nid = wolfSSL_OBJ_obj2nid(obj)), NID_subject_key_identifier); ExpectNotNull(asn1str = (WOLFSSL_ASN1_STRING*)wolfSSL_X509V3_EXT_d2i(ext)); + critical = -1; + ExpectNotNull(ext2 = X509_get_ext_d2i(x509, NID_subject_key_identifier, + &critical, NULL)); + ExpectIntNE(critical, -1); + ext2 = NULL; ExpectNotNull(ext2 = wolfSSL_X509V3_EXT_i2d(NID_subject_key_identifier, 0, asn1str)); X509_EXTENSION_free(ext2); @@ -1497,6 +1530,15 @@ int test_wolfSSL_X509V3_EXT(void) ExpectNotNull(aKeyId = (WOLFSSL_AUTHORITY_KEYID*)wolfSSL_X509V3_EXT_d2i( ext)); + critical = -1; + ExpectNotNull(ext2 = X509_get_ext_d2i(x509, NID_authority_key_identifier, + &critical, NULL)); + ExpectIntNE(critical, -1); + ext2 = NULL; + ExpectNotNull(ext2 = wolfSSL_X509V3_EXT_i2d(NID_authority_key_identifier, + 0, aKeyId)); + X509_EXTENSION_free(ext2); + ext2 = NULL; ExpectNotNull(method = wolfSSL_X509V3_EXT_get(ext)); ExpectNotNull(asn1str = aKeyId->keyid); ExpectNotNull(str = wolfSSL_i2s_ASN1_STRING((WOLFSSL_v3_ext_method*)method, @@ -1519,6 +1561,14 @@ int test_wolfSSL_X509V3_EXT(void) ExpectIntEQ((nid = wolfSSL_OBJ_obj2nid(obj)), NID_key_usage); ExpectNotNull(asn1str = (WOLFSSL_ASN1_STRING*)wolfSSL_X509V3_EXT_d2i(ext)); + critical = -1; + ExpectNotNull(ext2 = X509_get_ext_d2i(x509, NID_key_usage, &critical, + NULL)); + ExpectIntNE(critical, -1); + ext2 = NULL; + ExpectNotNull(ext2 = wolfSSL_X509V3_EXT_i2d(NID_key_usage, 0, asn1str)); + X509_EXTENSION_free(ext2); + ext2 = NULL; #if defined(WOLFSSL_QT) ExpectNotNull(data = (unsigned char*)ASN1_STRING_get0_data(asn1str)); #else @@ -1545,6 +1595,11 @@ int test_wolfSSL_X509V3_EXT(void) ExpectIntEQ((nid = wolfSSL_OBJ_obj2nid(obj)), NID_info_access); ExpectNotNull(aia = (WOLFSSL_AUTHORITY_INFO_ACCESS*)wolfSSL_X509V3_EXT_d2i( ext)); + critical = -1; + ExpectNotNull(ext2 = X509_get_ext_d2i(x509, NID_info_access, &critical, + NULL)); + ExpectIntNE(critical, -1); + ext2 = NULL; #if defined(WOLFSSL_QT) ExpectIntEQ(OPENSSL_sk_num(aia), 1); /* Only one URI entry for this cert */ #else @@ -1595,8 +1650,9 @@ int test_wolfSSL_X509V3_EXT(void) int test_wolfSSL_X509V3_EXT_print(void) { EXPECT_DECLS; -#if !defined(NO_FILESYSTEM) && defined(OPENSSL_ALL) && !defined(NO_BIO) && \ - !defined(NO_RSA) +#if !defined(NO_FILESYSTEM) && \ + (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && \ + !defined(NO_BIO) && !defined(NO_RSA) { XFILE f = XBADFILE; @@ -2365,6 +2421,63 @@ int test_wolfSSL_NAME_CONSTRAINTS_check_name(void) return EXPECT_RESULT(); } +int test_wolfSSL_NAME_CONSTRAINTS_manual_paths(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) && !defined(IGNORE_NAME_CONSTRAINTS) + NAME_CONSTRAINTS* nc = NULL; + GENERAL_SUBTREE* subtree = NULL; + GENERAL_NAME* gn = NULL; + const char dnsName[] = ".wolfssl.com"; + + ExpectNotNull(nc = NAME_CONSTRAINTS_new()); + if (EXPECT_SUCCESS()) { + ExpectNotNull(nc->permittedSubtrees = wolfSSL_sk_new_null()); + } + if (EXPECT_SUCCESS()) { + nc->permittedSubtrees->type = STACK_TYPE_GENERAL_SUBTREE; + ExpectNotNull(subtree = GENERAL_SUBTREE_new()); + } + if (EXPECT_SUCCESS()) { + ExpectIntEQ(wolfSSL_sk_push(nc->permittedSubtrees, subtree), 1); + subtree = NULL; + } + + /* base == NULL should be skipped, leaving the name permitted. */ + if (EXPECT_SUCCESS()) { + ExpectIntEQ(wolfSSL_NAME_CONSTRAINTS_check_name(nc, GEN_DNS, + "www.example.com", 15), 1); + } + + if (EXPECT_SUCCESS()) { + ExpectNotNull(subtree = sk_GENERAL_SUBTREE_value(nc->permittedSubtrees, + 0)); + ExpectNotNull(gn = GENERAL_NAME_new()); + } + if (EXPECT_SUCCESS()) { + subtree->base = gn; + gn = NULL; + subtree->base->type = GEN_EMAIL; + ExpectIntEQ(wolfSSL_NAME_CONSTRAINTS_check_name(nc, GEN_DNS, + "www.example.com", 15), 1); + } + + /* Same-type permitted constraint with no match should now reject. */ + if (EXPECT_SUCCESS()) { + subtree->base->type = GEN_DNS; + ExpectIntEQ(ASN1_STRING_set(subtree->base->d.dNSName, dnsName, + (int)XSTRLEN(dnsName)), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_NAME_CONSTRAINTS_check_name(nc, GEN_DNS, + "www.example.com", 15), 0); + ExpectIntEQ(wolfSSL_NAME_CONSTRAINTS_check_name(nc, GEN_DNS, + "www.sub.wolfssl.com", 19), 1); + } + + NAME_CONSTRAINTS_free(nc); +#endif /* OPENSSL_EXTRA && !IGNORE_NAME_CONSTRAINTS */ + return EXPECT_RESULT(); +} + /* * Test DNS type name constraint checking with leading dot (subdomain matching). * Uses cert-ext-nc-combined.pem which has permitted;DNS:.wolfssl.com @@ -2506,4 +2619,3 @@ int test_wolfSSL_NAME_CONSTRAINTS_excluded(void) * !IGNORE_NAME_CONSTRAINTS */ return EXPECT_RESULT(); } - diff --git a/tests/api/test_ossl_x509_ext.h b/tests/api/test_ossl_x509_ext.h index 68be4ebf5e..13ab76484c 100644 --- a/tests/api/test_ossl_x509_ext.h +++ b/tests/api/test_ossl_x509_ext.h @@ -54,6 +54,7 @@ int test_wolfSSL_NAME_CONSTRAINTS_types(void); int test_wolfSSL_NAME_CONSTRAINTS_uri(void); int test_wolfSSL_NAME_CONSTRAINTS_ipaddr(void); int test_wolfSSL_NAME_CONSTRAINTS_check_name(void); +int test_wolfSSL_NAME_CONSTRAINTS_manual_paths(void); int test_wolfSSL_NAME_CONSTRAINTS_dns(void); int test_wolfSSL_NAME_CONSTRAINTS_excluded(void); @@ -93,6 +94,7 @@ int test_wolfSSL_NAME_CONSTRAINTS_excluded(void); TEST_DECL_GROUP("ossl_x509_ext", test_wolfSSL_NAME_CONSTRAINTS_uri), \ TEST_DECL_GROUP("ossl_x509_ext", test_wolfSSL_NAME_CONSTRAINTS_ipaddr), \ TEST_DECL_GROUP("ossl_x509_ext", test_wolfSSL_NAME_CONSTRAINTS_check_name),\ + TEST_DECL_GROUP("ossl_x509_ext", test_wolfSSL_NAME_CONSTRAINTS_manual_paths),\ TEST_DECL_GROUP("ossl_x509_ext", test_wolfSSL_NAME_CONSTRAINTS_dns), \ TEST_DECL_GROUP("ossl_x509_ext", test_wolfSSL_NAME_CONSTRAINTS_excluded) diff --git a/tests/api/test_ossl_x509_vp.c b/tests/api/test_ossl_x509_vp.c index a7c65ea256..9cc31179af 100644 --- a/tests/api/test_ossl_x509_vp.c +++ b/tests/api/test_ossl_x509_vp.c @@ -38,10 +38,12 @@ int test_wolfSSL_X509_VERIFY_PARAM(void) #if defined(OPENSSL_EXTRA) X509_VERIFY_PARAM *paramTo = NULL; X509_VERIFY_PARAM *paramFrom = NULL; + char longHost[WOLFSSL_HOST_NAME_MAX + 8]; char testIPv4[] = "127.0.0.1"; char testIPv6[] = "0001:0000:0000:0000:0000:0000:0000:0000/32"; char testhostName1[] = "foo.hoge.com"; char testhostName2[] = "foobar.hoge.com"; + size_t i; ExpectNotNull(paramTo = X509_VERIFY_PARAM_new()); ExpectNotNull(XMEMSET(paramTo, 0, sizeof(X509_VERIFY_PARAM))); @@ -53,6 +55,23 @@ int test_wolfSSL_X509_VERIFY_PARAM(void) (int)XSTRLEN(testhostName1)), 1); ExpectIntEQ(0, XSTRNCMP(paramFrom->hostName, testhostName1, (int)XSTRLEN(testhostName1))); + ExpectIntEQ(X509_VERIFY_PARAM_set1_host(paramFrom, testhostName1, 0), 1); + ExpectIntEQ(0, XSTRNCMP(paramFrom->hostName, testhostName1, + (int)XSTRLEN(testhostName1))); + ExpectIntEQ(X509_VERIFY_PARAM_set1_host(paramFrom, NULL, 0), 1); + ExpectIntEQ(paramFrom->hostName[0], '\0'); + + XMEMSET(longHost, 'a', sizeof(longHost)); + longHost[sizeof(longHost) - 1] = '\0'; + ExpectIntEQ(X509_VERIFY_PARAM_set1_host(paramFrom, longHost, + (int)sizeof(longHost)), 1); + for (i = 0; i < WOLFSSL_HOST_NAME_MAX - 1; i++) { + ExpectIntEQ(paramFrom->hostName[i], 'a'); + } + ExpectIntEQ(paramFrom->hostName[WOLFSSL_HOST_NAME_MAX - 1], '\0'); + + ExpectIntEQ(X509_VERIFY_PARAM_set1_host(paramFrom, testhostName1, + (int)XSTRLEN(testhostName1)), 1); X509_VERIFY_PARAM_set_hostflags(NULL, 0x00); @@ -132,6 +151,34 @@ int test_wolfSSL_X509_VERIFY_PARAM(void) ExpectIntEQ(0x00, paramTo->hostFlags); ExpectIntEQ(0, XSTRNCMP(paramTo->ipasc, testIPv4, WOLFSSL_MAX_IPSTR)); + /* inherit flags test : VPARAM_ONCE */ + ExpectIntEQ(X509_VERIFY_PARAM_set1_host(paramTo, testhostName2, + (int)XSTRLEN(testhostName2)), 1); + ExpectIntEQ(X509_VERIFY_PARAM_set1_ip_asc(paramTo, testIPv4), 1); + paramTo->inherit_flags = X509_VP_FLAG_ONCE; + paramFrom->inherit_flags = 0; + ExpectIntEQ(X509_VERIFY_PARAM_inherit(paramTo, paramFrom), 1); + ExpectIntEQ(paramTo->inherit_flags, 0); + ExpectIntEQ(0, XSTRNCMP(paramTo->hostName, testhostName2, + (int)XSTRLEN(testhostName2))); + ExpectIntEQ(0, XSTRNCMP(paramTo->ipasc, testIPv4, WOLFSSL_MAX_IPSTR)); + + /* check_time should not be copied when already set unless overwrite */ + XMEMSET(paramTo, 0, sizeof(X509_VERIFY_PARAM)); + XMEMSET(paramFrom, 0, sizeof(X509_VERIFY_PARAM)); + paramTo->check_time = 11; + paramTo->flags = WOLFSSL_USE_CHECK_TIME; + paramFrom->check_time = 22; + ExpectIntEQ(X509_VERIFY_PARAM_inherit(paramTo, paramFrom), 1); + ExpectIntEQ(paramTo->check_time, 11); + ExpectIntEQ(paramTo->flags & WOLFSSL_USE_CHECK_TIME, + WOLFSSL_USE_CHECK_TIME); + + paramTo->inherit_flags = X509_VP_FLAG_OVERWRITE; + ExpectIntEQ(X509_VERIFY_PARAM_inherit(paramTo, paramFrom), 1); + ExpectIntEQ(paramTo->check_time, 22); + ExpectIntEQ(paramTo->flags & WOLFSSL_USE_CHECK_TIME, 0); + /* test for incorrect parameters */ ExpectIntEQ(X509_VERIFY_PARAM_set_flags(NULL, X509_V_FLAG_CRL_CHECK_ALL), 0); @@ -273,4 +320,3 @@ int test_wolfSSL_X509_VERIFY_PARAM_set1_host(void) #endif /* OPENSSL_EXTRA */ return EXPECT_RESULT(); } - diff --git a/tests/api/test_pkcs12.c b/tests/api/test_pkcs12.c index cbe2186e8e..42b6d7d9bc 100644 --- a/tests/api/test_pkcs12.c +++ b/tests/api/test_pkcs12.c @@ -199,6 +199,72 @@ int test_wc_PKCS12_create(void) return EXPECT_RESULT(); } +int test_wc_PKCS12_create_guardrails(void) +{ + EXPECT_DECLS; +#if !defined(NO_ASN) && defined(HAVE_PKCS12) && !defined(NO_PWDBASED) && \ + !defined(NO_RSA) && !defined(NO_ASN_CRYPT) && \ + !defined(NO_HMAC) && !defined(NO_CERTS) && defined(USE_CERT_BUFFERS_2048) + byte* inKey = (byte*)server_key_der_2048; + const word32 inKeySz = sizeof_server_key_der_2048; + byte* inCert = (byte*)server_cert_der_2048; + const word32 inCertSz = sizeof_server_cert_der_2048; + WC_DerCertList inCa = { + (byte*)ca_cert_der_2048, sizeof_ca_cert_der_2048, NULL + }; + char pkcs12Passwd[] = "test_wc_PKCS12_create_guardrails"; + + ExpectNull(wc_PKCS12_create(pkcs12Passwd, sizeof(pkcs12Passwd) - 1, + (char*)"friendlyName", inKey, inKeySz, inCert, inCertSz, &inCa, 9999, + -1, 0, 0, 0, NULL)); + ExpectNull(wc_PKCS12_create(pkcs12Passwd, sizeof(pkcs12Passwd) - 1, + (char*)"friendlyName", inKey, inKeySz, inCert, inCertSz, &inCa, -1, + 9999, 0, 0, 0, NULL)); +#endif + return EXPECT_RESULT(); +} + +int test_wc_PKCS12_parse_guardrails(void) +{ + EXPECT_DECLS; +#if !defined(NO_ASN) && !defined(NO_PWDBASED) && defined(HAVE_PKCS12) + WC_PKCS12* pkcs12 = NULL; + byte* outKey = NULL; + byte* outCert = NULL; + WC_DerCertList* outCa = (WC_DerCertList*)1; + word32 outKeySz = 0; + word32 outCertSz = 0; + + ExpectIntEQ(wc_PKCS12_parse(NULL, "", &outKey, &outKeySz, &outCert, + &outCertSz, &outCa), BAD_FUNC_ARG); + + ExpectNotNull(pkcs12 = wc_PKCS12_new()); + ExpectIntEQ(wc_PKCS12_parse(pkcs12, NULL, &outKey, &outKeySz, &outCert, + &outCertSz, &outCa), BAD_FUNC_ARG); + ExpectIntEQ(wc_PKCS12_parse(pkcs12, "", NULL, &outKeySz, &outCert, + &outCertSz, &outCa), BAD_FUNC_ARG); + ExpectIntEQ(wc_PKCS12_parse(pkcs12, "", &outKey, NULL, &outCert, + &outCertSz, &outCa), BAD_FUNC_ARG); + ExpectIntEQ(wc_PKCS12_parse(pkcs12, "", &outKey, &outKeySz, NULL, + &outCertSz, &outCa), BAD_FUNC_ARG); + ExpectIntEQ(wc_PKCS12_parse(pkcs12, "", &outKey, &outKeySz, &outCert, + NULL, &outCa), BAD_FUNC_ARG); + + outKey = (byte*)1; + outCert = (byte*)1; + outKeySz = 17; + outCertSz = 19; + ExpectIntEQ(wc_PKCS12_parse(pkcs12, "", &outKey, &outKeySz, &outCert, + &outCertSz, &outCa), BAD_FUNC_ARG); + ExpectNull(outKey); + ExpectNull(outCert); + ExpectNull(outCa); + + wc_PKCS12_free(pkcs12); +#endif + return EXPECT_RESULT(); +} + int test_wc_d2i_PKCS12_bad_mac_salt(void) { EXPECT_DECLS; diff --git a/tests/api/test_pkcs12.h b/tests/api/test_pkcs12.h index d781005c9f..9928199703 100644 --- a/tests/api/test_pkcs12.h +++ b/tests/api/test_pkcs12.h @@ -26,6 +26,8 @@ int test_wc_i2d_PKCS12(void); int test_wc_PKCS12_create(void); +int test_wc_PKCS12_create_guardrails(void); +int test_wc_PKCS12_parse_guardrails(void); int test_wc_d2i_PKCS12_bad_mac_salt(void); int test_wc_d2i_PKCS12_oid_underflow(void); int test_wc_PKCS12_encrypted_content_bounds(void); @@ -42,6 +44,8 @@ int test_wc_PKCS12_PBKDF_ex_sha512_256(void); #define TEST_PKCS12_DECLS \ TEST_DECL_GROUP("pkcs12", test_wc_i2d_PKCS12), \ TEST_DECL_GROUP("pkcs12", test_wc_PKCS12_create), \ + TEST_DECL_GROUP("pkcs12", test_wc_PKCS12_create_guardrails), \ + TEST_DECL_GROUP("pkcs12", test_wc_PKCS12_parse_guardrails), \ TEST_DECL_GROUP("pkcs12", test_wc_d2i_PKCS12_bad_mac_salt), \ TEST_DECL_GROUP("pkcs12", test_wc_d2i_PKCS12_oid_underflow), \ TEST_DECL_GROUP("pkcs12", test_wc_PKCS12_encrypted_content_bounds), \ diff --git a/tests/api/test_pkcs7.c b/tests/api/test_pkcs7.c index c837c375b5..245f8485be 100644 --- a/tests/api/test_pkcs7.c +++ b/tests/api/test_pkcs7.c @@ -268,6 +268,72 @@ int test_wc_PKCS7_InitWithCert(void) return EXPECT_RESULT(); } /* END test_wc_PKCS7_InitWithCert */ +int test_wc_PKCS7_InitWithCert_guardrails(void) +{ + EXPECT_DECLS; +#if defined(HAVE_PKCS7) + PKCS7* pkcs7 = NULL; + static byte malformedCert[] = { 0x30, 0x03, 0x02, 0x01, 0x00 }; +#ifndef NO_RSA + #if defined(USE_CERT_BUFFERS_2048) + byte cert[sizeof(client_cert_der_2048)]; + word32 certSz = sizeof(cert); + + XMEMSET(cert, 0, sizeof(cert)); + XMEMCPY(cert, client_cert_der_2048, sizeof(client_cert_der_2048)); + #elif defined(USE_CERT_BUFFERS_1024) + byte cert[sizeof_client_cert_der_1024]; + word32 certSz = sizeof(cert); + + XMEMSET(cert, 0, sizeof(cert)); + XMEMCPY(cert, client_cert_der_1024, sizeof_client_cert_der_1024); + #else + byte cert[ONEK_BUF]; + XFILE fp = XBADFILE; + int tmpCertSz; + word32 certSz = 0; + + ExpectTrue((fp = XFOPEN("./certs/1024/client-cert.der", "rb")) != + XBADFILE); + ExpectIntGT(tmpCertSz = (int)XFREAD(cert, 1, + sizeof_client_cert_der_1024, fp), 0); + certSz = (word32)tmpCertSz; + if (fp != XBADFILE) + XFCLOSE(fp); + #endif +#elif defined(HAVE_ECC) + #if defined(USE_CERT_BUFFERS_256) + byte cert[sizeof(cliecc_cert_der_256)]; + word32 certSz = sizeof(cert); + + XMEMSET(cert, 0, sizeof(cert)); + XMEMCPY(cert, cliecc_cert_der_256, sizeof_cliecc_cert_der_256); + #else + byte cert[ONEK_BUF]; + XFILE fp = XBADFILE; + int tmpCertSz; + word32 certSz = 0; + + ExpectTrue((fp = XFOPEN("./certs/client-ecc-cert.der", "rb")) != + XBADFILE); + ExpectIntGT(tmpCertSz = (int)XFREAD(cert, 1, + sizeof_cliecc_cert_der_256, fp), 0); + certSz = (word32)tmpCertSz; + if (fp != XBADFILE) + XFCLOSE(fp); + #endif +#endif + + ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId)); + ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, (byte*)cert, 0), 0); + ExpectIntLT(wc_PKCS7_InitWithCert(pkcs7, malformedCert, + (word32)sizeof(malformedCert)), 0); + ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, (byte*)cert, certSz), 0); + wc_PKCS7_Free(pkcs7); +#endif + return EXPECT_RESULT(); +} + /* * Testing wc_PKCS7_EncodeData() diff --git a/tests/api/test_pkcs7.h b/tests/api/test_pkcs7.h index bf25365cc7..1a49be5aa6 100644 --- a/tests/api/test_pkcs7.h +++ b/tests/api/test_pkcs7.h @@ -27,6 +27,7 @@ int test_wc_PKCS7_New(void); int test_wc_PKCS7_Init(void); int test_wc_PKCS7_InitWithCert(void); +int test_wc_PKCS7_InitWithCert_guardrails(void); int test_wc_PKCS7_EncodeData(void); int test_wc_PKCS7_EncodeSignedData(void); int test_wc_PKCS7_EncodeSignedData_AttribOverflow(void); @@ -113,6 +114,7 @@ int test_wc_PKCS7_VerifySignedData_TruncCertSetTag(void); #define TEST_PKCS7_SIGNED_DATA_DECLS \ TEST_DECL_GROUP("pkcs7_sd", test_wc_PKCS7_InitWithCert), \ + TEST_DECL_GROUP("pkcs7_sd", test_wc_PKCS7_InitWithCert_guardrails), \ TEST_DECL_GROUP("pkcs7_sd", test_wc_PKCS7_EncodeData), \ TEST_DECL_GROUP("pkcs7_sd", test_wc_PKCS7_EncodeSignedData), \ TEST_DECL_GROUP("pkcs7_sd", test_wc_PKCS7_EncodeSignedData_AttribOverflow), \ diff --git a/tests/api/test_rsa.c b/tests/api/test_rsa.c index 262b1f92a4..bde665f0dc 100644 --- a/tests/api/test_rsa.c +++ b/tests/api/test_rsa.c @@ -30,6 +30,12 @@ #include #include +#ifndef NO_SHA256 +#include +#endif +#ifdef WOLFSSL_SHA384 +#include +#endif #include #include @@ -1400,3 +1406,366 @@ int test_wc_RsaKeyToDer_SizeOverflow(void) return EXPECT_RESULT(); } /* END test_wc_RsaKeyToDer_SizeOverflow */ +/* + * MC/DC wave 2 — decision-targeted negative paths for the high-level RSA + * encrypt/decrypt/sign surfaces. The existing tests above deliberately leave + * bad-arg coverage "tested in another testing function" for + * wc_RsaPublicEncrypt{,_ex}, wc_RsaPrivateDecrypt{,Inline}{,_ex}, and + * wc_RsaSetRNG. This function closes that gap by hitting the argument-check, + * short-buffer, and invalid-mode branches in wolfcrypt/src/rsa.c without + * changing any library source. + */ +int test_wc_RsaDecisionCoverage(void) +{ + EXPECT_DECLS; +#if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) && \ + !defined(WOLFSSL_RSA_PUBLIC_ONLY) + RsaKey key; + WC_RNG rng; + const char inStr[] = TEST_STRING; + const word32 inLen = (word32)TEST_STRING_SZ; + int bits = TEST_RSA_BITS; + const word32 cipherLen = TEST_RSA_BYTES; + int cipherOutLen = 0; + WC_DECLARE_VAR(in, byte, TEST_STRING_SZ, NULL); + WC_DECLARE_VAR(cipher, byte, TEST_RSA_BYTES, NULL); + WC_DECLARE_VAR(plain, byte, TEST_RSA_BYTES, NULL); + + WC_ALLOC_VAR(in, byte, TEST_STRING_SZ, NULL); + WC_ALLOC_VAR(cipher, byte, TEST_RSA_BYTES, NULL); + WC_ALLOC_VAR(plain, byte, TEST_RSA_BYTES, NULL); + +#ifdef WC_DECLARE_VAR_IS_HEAP_ALLOC + ExpectNotNull(in); + ExpectNotNull(cipher); + ExpectNotNull(plain); +#endif + ExpectNotNull(XMEMCPY(in, inStr, inLen)); + + XMEMSET(&key, 0, sizeof(RsaKey)); + XMEMSET(&rng, 0, sizeof(WC_RNG)); + + ExpectIntEQ(wc_InitRsaKey(&key, HEAP_HINT), 0); + ExpectIntEQ(wc_InitRng(&rng), 0); + ExpectIntEQ(MAKE_RSA_KEY(&key, bits, WC_RSA_EXPONENT, &rng), 0); + + /* ---- wc_RsaPublicEncrypt: argument-check decision branches ---- */ + ExpectIntEQ(wc_RsaPublicEncrypt(NULL, inLen, cipher, cipherLen, &key, &rng), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wc_RsaPublicEncrypt(in, inLen, NULL, cipherLen, &key, &rng), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wc_RsaPublicEncrypt(in, inLen, cipher, cipherLen, NULL, &rng), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + /* Short output buffer: cipher buffer smaller than modulus byte length + * must return RSA_BUFFER_E (short-buffer decision branch). */ + ExpectIntEQ(wc_RsaPublicEncrypt(in, inLen, cipher, cipherLen - 1, &key, + &rng), WC_NO_ERR_TRACE(RSA_BUFFER_E)); + + /* One real encrypt so the decrypt-side negative cases have a valid + * cipher text to work with. */ + ExpectIntGT(cipherOutLen = wc_RsaPublicEncrypt(in, inLen, cipher, cipherLen, + &key, &rng), 0); + + /* ---- wc_RsaPrivateDecrypt: argument-check + short-buffer branches ---- */ +#if defined(WC_RSA_BLINDING) && !defined(HAVE_FIPS) + ExpectIntEQ(wc_RsaSetRNG(&key, &rng), 0); + /* wc_RsaSetRNG NULL arg decision branches. */ + ExpectIntEQ(wc_RsaSetRNG(NULL, &rng), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wc_RsaSetRNG(&key, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); +#endif + ExpectIntEQ(wc_RsaPrivateDecrypt(NULL, (word32)cipherOutLen, plain, + cipherLen, &key), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wc_RsaPrivateDecrypt(cipher, (word32)cipherOutLen, NULL, + cipherLen, &key), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wc_RsaPrivateDecrypt(cipher, (word32)cipherOutLen, plain, + cipherLen, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + + /* ---- wc_RsaPrivateDecryptInline: argument-check decision branches ---- */ + { + byte* outPtr = NULL; + ExpectIntEQ(wc_RsaPrivateDecryptInline(NULL, (word32)cipherOutLen, + &outPtr, &key), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + { + int ret = wc_RsaPrivateDecryptInline(cipher, (word32)cipherOutLen, + NULL, &key); + ExpectTrue(ret == WC_NO_ERR_TRACE(BAD_FUNC_ARG) || ret > 0); + } + ExpectIntEQ(wc_RsaPrivateDecryptInline(cipher, (word32)cipherOutLen, + &outPtr, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + } + +#if !defined(HAVE_FIPS) && !defined(WC_NO_RSA_OAEP) && !defined(NO_SHA256) + /* ---- wc_RsaPublicEncrypt_ex: argument-check + invalid-mode branches --- */ + ExpectIntEQ(wc_RsaPublicEncrypt_ex(NULL, inLen, cipher, cipherLen, &key, + &rng, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, NULL, 0), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wc_RsaPublicEncrypt_ex(in, inLen, NULL, cipherLen, &key, &rng, + WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, NULL, 0), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wc_RsaPublicEncrypt_ex(in, inLen, cipher, cipherLen, NULL, &rng, + WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, NULL, 0), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + /* Invalid padding type selector: should not dispatch to any valid path. */ + ExpectIntLT(wc_RsaPublicEncrypt_ex(in, inLen, cipher, cipherLen, &key, + &rng, /* bogus pad type */ 99, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, + NULL, 0), 0); + + /* Produce a valid OAEP-SHA256 cipher text for the decrypt negative path. */ + cipherOutLen = wc_RsaPublicEncrypt_ex(in, inLen, cipher, cipherLen, &key, + &rng, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, NULL, 0); + ExpectIntGT(cipherOutLen, 0); + + /* ---- wc_RsaPrivateDecrypt_ex: argument-check + padding-mismatch ---- */ + ExpectIntEQ(wc_RsaPrivateDecrypt_ex(NULL, (word32)cipherOutLen, plain, + cipherLen, &key, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, + NULL, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wc_RsaPrivateDecrypt_ex(cipher, (word32)cipherOutLen, NULL, + cipherLen, &key, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, + NULL, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wc_RsaPrivateDecrypt_ex(cipher, (word32)cipherOutLen, plain, + cipherLen, NULL, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, + NULL, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + /* Cipher text is OAEP-SHA256: decoding it as PKCS#1 v1.5 must fail and + * exercise the padding-mismatch decision branch in rsa.c. */ + ExpectIntLT(wc_RsaPrivateDecrypt_ex(cipher, (word32)cipherOutLen, plain, + cipherLen, &key, WC_RSA_PKCSV15_PAD, WC_HASH_TYPE_NONE, 0, NULL, 0), + 0); + + /* ---- wc_RsaPrivateDecryptInline_ex argument-check branches ---- */ + { + byte* outPtr = NULL; + ExpectIntEQ(wc_RsaPrivateDecryptInline_ex(NULL, (word32)cipherOutLen, + &outPtr, &key, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, + NULL, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + { + int ret = wc_RsaPrivateDecryptInline_ex(cipher, + (word32)cipherOutLen, NULL, &key, WC_RSA_OAEP_PAD, + WC_HASH_TYPE_SHA256, WC_MGF1SHA256, NULL, 0); + ExpectTrue(ret == WC_NO_ERR_TRACE(BAD_FUNC_ARG) || ret > 0); + } + ExpectIntEQ(wc_RsaPrivateDecryptInline_ex(cipher, (word32)cipherOutLen, + &outPtr, NULL, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, + NULL, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + } +#endif /* !HAVE_FIPS && !WC_NO_RSA_OAEP && !NO_SHA256 */ + + WC_FREE_VAR(in, NULL); + WC_FREE_VAR(cipher, NULL); + WC_FREE_VAR(plain, NULL); + DoExpectIntEQ(wc_FreeRsaKey(&key), 0); + DoExpectIntEQ(wc_FreeRng(&rng), 0); +#endif + return EXPECT_RESULT(); +} /* END test_wc_RsaDecisionCoverage */ + +/* + * MC/DC wave 2 — feature-oriented positive paths to lift rsa.c MC/DC by + * exercising OAEP, PSS, and PKCS#1 v1.5 sign/verify across multiple hash + * algorithms and label/salt configurations using the static client key DER + * (no runtime key generation). + */ +int test_wc_RsaFeatureCoverage(void) +{ + EXPECT_DECLS; +#if !defined(NO_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) && \ + defined(USE_CERT_BUFFERS_2048) && !defined(HAVE_FIPS) + RsaKey key; + WC_RNG rng; + word32 idx = 0; + byte cipher[256]; + byte plain[256]; + byte sig[256]; + int cipherLen; + int sigLen; + int initKey = 0; + int initRng = 0; + static const byte msg[16] = { + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, + 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f + }; + static const byte label[4] = { 0xde, 0xad, 0xbe, 0xef }; + + XMEMSET(&key, 0, sizeof(key)); + XMEMSET(&rng, 0, sizeof(rng)); + ExpectIntEQ(wc_InitRsaKey(&key, HEAP_HINT), 0); + if (EXPECT_SUCCESS()) initKey = 1; + ExpectIntEQ(wc_InitRng(&rng), 0); + if (EXPECT_SUCCESS()) initRng = 1; + ExpectIntEQ(wc_RsaPrivateKeyDecode(client_key_der_2048, &idx, &key, + sizeof_client_key_der_2048), 0); +#ifdef WC_RSA_BLINDING + ExpectIntEQ(wc_RsaSetRNG(&key, &rng), 0); +#endif + +#if !defined(WC_NO_RSA_OAEP) && !defined(NO_SHA256) + /* ---- OAEP-SHA256 round trip with empty label ---- */ + cipherLen = wc_RsaPublicEncrypt_ex(msg, sizeof(msg), cipher, + sizeof(cipher), &key, &rng, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, + WC_MGF1SHA256, NULL, 0); + ExpectIntGT(cipherLen, 0); + if (cipherLen > 0) { + int n = wc_RsaPrivateDecrypt_ex(cipher, (word32)cipherLen, plain, + sizeof(plain), &key, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, + WC_MGF1SHA256, NULL, 0); + ExpectIntEQ(n, (int)sizeof(msg)); + if (n == (int)sizeof(msg)) + ExpectBufEQ(plain, msg, sizeof(msg)); + } + + /* ---- OAEP-SHA256 round trip with non-empty label ---- */ + cipherLen = wc_RsaPublicEncrypt_ex(msg, sizeof(msg), cipher, + sizeof(cipher), &key, &rng, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, + WC_MGF1SHA256, (byte*)label, sizeof(label)); + ExpectIntGT(cipherLen, 0); + if (cipherLen > 0) { + int n = wc_RsaPrivateDecrypt_ex(cipher, (word32)cipherLen, plain, + sizeof(plain), &key, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, + WC_MGF1SHA256, (byte*)label, sizeof(label)); + ExpectIntEQ(n, (int)sizeof(msg)); + /* Wrong label must reject. */ + n = wc_RsaPrivateDecrypt_ex(cipher, (word32)cipherLen, plain, + sizeof(plain), &key, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, + WC_MGF1SHA256, NULL, 0); + ExpectIntLT(n, 0); + } +#endif /* !WC_NO_RSA_OAEP && !NO_SHA256 */ + +#if !defined(WC_NO_RSA_OAEP) && defined(WOLFSSL_SHA384) + /* ---- OAEP-SHA384 round trip ---- */ + cipherLen = wc_RsaPublicEncrypt_ex(msg, sizeof(msg), cipher, + sizeof(cipher), &key, &rng, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA384, + WC_MGF1SHA384, NULL, 0); + ExpectIntGT(cipherLen, 0); + if (cipherLen > 0) { + int n = wc_RsaPrivateDecrypt_ex(cipher, (word32)cipherLen, plain, + sizeof(plain), &key, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA384, + WC_MGF1SHA384, NULL, 0); + ExpectIntEQ(n, (int)sizeof(msg)); + } +#endif /* !WC_NO_RSA_OAEP && WOLFSSL_SHA384 */ + + /* ---- PKCS#1 v1.5 raw encrypt/decrypt round trip ---- */ + cipherLen = wc_RsaPublicEncrypt(msg, sizeof(msg), cipher, sizeof(cipher), + &key, &rng); + ExpectIntGT(cipherLen, 0); + if (cipherLen > 0) { + int n = wc_RsaPrivateDecrypt(cipher, (word32)cipherLen, plain, + sizeof(plain), &key); + ExpectIntEQ(n, (int)sizeof(msg)); + if (n == (int)sizeof(msg)) + ExpectBufEQ(plain, msg, sizeof(msg)); + } + + /* ---- PKCS#1 v1.5 sign / verify ---- */ + sigLen = wc_RsaSSL_Sign(msg, sizeof(msg), sig, sizeof(sig), &key, &rng); + ExpectIntGT(sigLen, 0); + if (sigLen > 0) { + int n = wc_RsaSSL_Verify(sig, (word32)sigLen, plain, sizeof(plain), + &key); + ExpectIntEQ(n, (int)sizeof(msg)); + if (n == (int)sizeof(msg)) + ExpectBufEQ(plain, msg, sizeof(msg)); + } + /* Tampered signature must be rejected. */ + if (sigLen > 0) { + sig[0] ^= 0x01; + ExpectIntLT(wc_RsaSSL_Verify(sig, (word32)sigLen, plain, sizeof(plain), + &key), 0); + sig[0] ^= 0x01; + } + +#if defined(WC_RSA_PSS) && !defined(NO_SHA256) + /* ---- PSS-SHA256 sign / verify with default salt length ---- + * PSS expects a hash-sized input, not arbitrary plaintext. */ + { + byte hash256[WC_SHA256_DIGEST_SIZE]; + ExpectIntEQ(wc_Sha256Hash(msg, sizeof(msg), hash256), 0); + + sigLen = wc_RsaPSS_Sign(hash256, sizeof(hash256), sig, sizeof(sig), + WC_HASH_TYPE_SHA256, WC_MGF1SHA256, &key, &rng); + ExpectIntGT(sigLen, 0); + if (sigLen > 0) { + ExpectIntGT(wc_RsaPSS_Verify(sig, (word32)sigLen, plain, + sizeof(plain), WC_HASH_TYPE_SHA256, WC_MGF1SHA256, &key), 0); + } + + /* ---- PSS-SHA256 sign / verify with explicit salt length ---- */ + sigLen = wc_RsaPSS_Sign_ex(hash256, sizeof(hash256), sig, sizeof(sig), + WC_HASH_TYPE_SHA256, WC_MGF1SHA256, /* saltLen */ 16, &key, &rng); + ExpectIntGT(sigLen, 0); + if (sigLen > 0) { + ExpectIntGT(wc_RsaPSS_Verify_ex(sig, (word32)sigLen, plain, + sizeof(plain), WC_HASH_TYPE_SHA256, WC_MGF1SHA256, 16, &key), + 0); + } + } +#endif /* WC_RSA_PSS && !NO_SHA256 */ + +#if defined(WC_RSA_PSS) && defined(WOLFSSL_SHA384) + /* ---- PSS-SHA384 sign / verify ---- */ + { + byte hash384[WC_SHA384_DIGEST_SIZE]; + ExpectIntEQ(wc_Sha384Hash(msg, sizeof(msg), hash384), 0); + + sigLen = wc_RsaPSS_Sign(hash384, sizeof(hash384), sig, sizeof(sig), + WC_HASH_TYPE_SHA384, WC_MGF1SHA384, &key, &rng); + ExpectIntGT(sigLen, 0); + if (sigLen > 0) { + ExpectIntGT(wc_RsaPSS_Verify(sig, (word32)sigLen, plain, + sizeof(plain), WC_HASH_TYPE_SHA384, WC_MGF1SHA384, &key), 0); + } + } +#endif /* WC_RSA_PSS && WOLFSSL_SHA384 */ + + /* ---- wc_CheckRsaKey: exercise consistency checks on a good key ---- */ + #ifdef WOLFSSL_RSA_KEY_CHECK + ExpectIntEQ(wc_CheckRsaKey(&key), 0); + #endif + + /* ---- wc_InitRsaKey_Id / wc_InitRsaKey_Label: positive path ---- */ + #ifdef WOLF_PRIVATE_KEY_ID + { + RsaKey tmpKey; + static const byte idBuf[4] = { 0x01, 0x02, 0x03, 0x04 }; + XMEMSET(&tmpKey, 0, sizeof(tmpKey)); + ExpectIntEQ(wc_InitRsaKey_Id(&tmpKey, (byte*)idBuf, sizeof(idBuf), + HEAP_HINT, INVALID_DEVID), 0); + DoExpectIntEQ(wc_FreeRsaKey(&tmpKey), 0); + } + { + RsaKey tmpKey; + XMEMSET(&tmpKey, 0, sizeof(tmpKey)); + ExpectIntEQ(wc_InitRsaKey_Label(&tmpKey, "test-label", HEAP_HINT, + INVALID_DEVID), 0); + DoExpectIntEQ(wc_FreeRsaKey(&tmpKey), 0); + } + #endif /* WOLF_PRIVATE_KEY_ID */ + + /* ---- wc_RsaKeyToPublicDer_ex: with and without algorithm header ---- */ + #ifdef WOLFSSL_KEY_GEN + { + byte pubDer[512]; + ExpectIntGT(wc_RsaKeyToPublicDer_ex(&key, pubDer, sizeof(pubDer), 1), + 0); + ExpectIntGT(wc_RsaKeyToPublicDer_ex(&key, pubDer, sizeof(pubDer), 0), + 0); + } + #endif + + /* ---- wc_RsaEncryptSize / wc_RsaFlattenPublicKey positive path ---- */ + ExpectIntGT(wc_RsaEncryptSize(&key), 0); + { + byte n[256]; + byte e[8]; + word32 nSz = sizeof(n); + word32 eSz = sizeof(e); + ExpectIntEQ(wc_RsaFlattenPublicKey(&key, e, &eSz, n, &nSz), 0); + ExpectIntGT(nSz, 0); + ExpectIntGT(eSz, 0); + } + + if (initKey) DoExpectIntEQ(wc_FreeRsaKey(&key), 0); + if (initRng) DoExpectIntEQ(wc_FreeRng(&rng), 0); +#endif + return EXPECT_RESULT(); +} /* END test_wc_RsaFeatureCoverage */ diff --git a/tests/api/test_rsa.h b/tests/api/test_rsa.h index 27bc8f6402..69081a5cc5 100644 --- a/tests/api/test_rsa.h +++ b/tests/api/test_rsa.h @@ -45,6 +45,8 @@ int test_wc_RsaFlattenPublicKey(void); int test_wc_RsaDecrypt_BoundsCheck(void); int test_wc_RsaFunctionCheckIn_OversizedModulus(void); int test_wc_RsaKeyToDer_SizeOverflow(void); +int test_wc_RsaDecisionCoverage(void); +int test_wc_RsaFeatureCoverage(void); #define TEST_RSA_DECLS \ TEST_DECL_GROUP("rsa", test_wc_InitRsaKey), \ @@ -67,6 +69,8 @@ int test_wc_RsaKeyToDer_SizeOverflow(void); TEST_DECL_GROUP("rsa", test_wc_RsaFlattenPublicKey), \ TEST_DECL_GROUP("rsa", test_wc_RsaDecrypt_BoundsCheck), \ TEST_DECL_GROUP("rsa", test_wc_RsaFunctionCheckIn_OversizedModulus), \ - TEST_DECL_GROUP("rsa", test_wc_RsaKeyToDer_SizeOverflow) + TEST_DECL_GROUP("rsa", test_wc_RsaKeyToDer_SizeOverflow), \ + TEST_DECL_GROUP("rsa", test_wc_RsaDecisionCoverage), \ + TEST_DECL_GROUP("rsa", test_wc_RsaFeatureCoverage) #endif /* WOLFCRYPT_TEST_RSA_H */ diff --git a/tests/api/test_signature.c b/tests/api/test_signature.c index 63eb7ae29e..b77ebbf8bc 100644 --- a/tests/api/test_signature.c +++ b/tests/api/test_signature.c @@ -31,7 +31,14 @@ #include #include #include +#include #include +#if defined(HAVE_PQC) && defined(HAVE_FALCON) + #include + #ifdef HAVE_LIBOQS + #include + #endif +#endif #include #include @@ -161,3 +168,46 @@ int test_wc_SignatureGetSize_rsa(void) return EXPECT_RESULT(); } /* END test_wc_SignatureGetSize_rsa(void) */ +int test_wc_falcon_sign_verify(void) +{ + EXPECT_DECLS; +#if defined(HAVE_PQC) && defined(HAVE_FALCON) && defined(HAVE_LIBOQS) + falcon_key key; + WC_RNG rng; + OQS_SIG* oqssig = NULL; + byte pub[FALCON_LEVEL1_PUB_KEY_SIZE]; + byte priv[FALCON_LEVEL1_KEY_SIZE]; + byte sig[FALCON_LEVEL1_SIG_SIZE]; + word32 sigLen = (word32)sizeof(sig); + int verified = 0; + static const byte msg[] = "wolfssl falcon coverage"; + + XMEMSET(&key, 0, sizeof(key)); + ExpectIntEQ(wc_falcon_init(&key), 0); + ExpectIntEQ(wc_falcon_set_level(&key, 1), 0); + ExpectIntEQ(wc_InitRng(&rng), 0); + + ExpectNotNull(oqssig = OQS_SIG_new(OQS_SIG_alg_falcon_512)); + if (oqssig != NULL) { + ExpectIntEQ(OQS_SIG_keypair(oqssig, pub, priv), OQS_SUCCESS); + ExpectIntEQ(wc_falcon_import_private_key(priv, (word32)sizeof(priv), pub, + (word32)sizeof(pub), &key), 0); + ExpectIntGT(wc_falcon_size(&key), 0); + ExpectIntGT(wc_falcon_pub_size(&key), 0); + ExpectIntGT(wc_falcon_priv_size(&key), 0); + ExpectIntGT(wc_falcon_sig_size(&key), 0); + ExpectIntEQ(wc_falcon_sign_msg(msg, (word32)sizeof(msg), sig, &sigLen, + &key, &rng), 0); + ExpectIntEQ(wc_falcon_verify_msg(sig, sigLen, msg, (word32)sizeof(msg), + &verified, &key), 0); + ExpectIntEQ(verified, 1); + } + + if (oqssig != NULL) { + OQS_SIG_free(oqssig); + } + DoExpectIntEQ(wc_FreeRng(&rng), 0); + wc_falcon_free(&key); +#endif + return EXPECT_RESULT(); +} diff --git a/tests/api/test_signature.h b/tests/api/test_signature.h index 85f43c5180..1f8f2e4b88 100644 --- a/tests/api/test_signature.h +++ b/tests/api/test_signature.h @@ -26,9 +26,11 @@ int test_wc_SignatureGetSize_ecc(void); int test_wc_SignatureGetSize_rsa(void); +int test_wc_falcon_sign_verify(void); #define TEST_SIGNATURE_DECLS \ TEST_DECL_GROUP("signature", test_wc_SignatureGetSize_ecc), \ - TEST_DECL_GROUP("signature", test_wc_SignatureGetSize_rsa) + TEST_DECL_GROUP("signature", test_wc_SignatureGetSize_rsa), \ + TEST_DECL_GROUP("signature", test_wc_falcon_sign_verify) #endif /* WOLFCRYPT_TEST_SIGNATURE_H */