From f3c0dd4f0cd3bc282575a98181f8190d81189a78 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 6 Mar 2023 18:38:00 -0500 Subject: [PATCH] Add test for context duplication failure This checks that the first operation successfully completes even if context duplication fails. But follwing operations get errors as if the context was finlised. Signed-off-by: Simo Sorce Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell Reviewed-by: Dmitry Belyavskiy (Merged from https://github.com/openssl/openssl/pull/20375) --- test/build.info | 2 +- test/evp_extra_test.c | 62 ++++++++++++++++ test/fake_rsaprov.c | 159 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 222 insertions(+), 1 deletion(-) diff --git a/test/build.info b/test/build.info index 15c0985150f..99f27e12b5c 100644 --- a/test/build.info +++ b/test/build.info @@ -180,7 +180,7 @@ IF[{- !$disabled{tests} -}] DEFINE[evp_test]=NO_LEGACY_MODULE ENDIF - SOURCE[evp_extra_test]=evp_extra_test.c + SOURCE[evp_extra_test]=evp_extra_test.c fake_rsaprov.c INCLUDE[evp_extra_test]=../include ../apps/include DEPEND[evp_extra_test]=../libcrypto.a libtestutil.a diff --git a/test/evp_extra_test.c b/test/evp_extra_test.c index 9230e7b9950..a829a1f7ef5 100644 --- a/test/evp_extra_test.c +++ b/test/evp_extra_test.c @@ -36,6 +36,7 @@ #include "internal/nelem.h" #include "internal/sizes.h" #include "crypto/evp.h" +#include "fake_rsaprov.h" static OSSL_LIB_CTX *testctx = NULL; static char *testpropq = NULL; @@ -4717,6 +4718,65 @@ static int test_ecx_not_private_key(int tst) } #endif /* OPENSSL_NO_EC */ +static int test_sign_continuation(void) +{ + OSSL_PROVIDER *fake_rsa = NULL; + int testresult = 0; + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *pctx = NULL; + EVP_MD_CTX *mctx = NULL; + const char sigbuf[] = "To Be Signed"; + unsigned char signature[256]; + size_t siglen = 256; + static int nodupnum = 1; + static const OSSL_PARAM nodup_params[] = { + OSSL_PARAM_int("NO_DUP", &nodupnum), + OSSL_PARAM_END + }; + + if (!TEST_ptr(fake_rsa = fake_rsa_start(testctx))) + return 0; + + /* Construct a pkey using precise propq to use our provider */ + if (!TEST_ptr(pctx = EVP_PKEY_CTX_new_from_name(testctx, "RSA", + "provider=fake-rsa")) + || !TEST_true(EVP_PKEY_fromdata_init(pctx)) + || !TEST_true(EVP_PKEY_fromdata(pctx, &pkey, EVP_PKEY_KEYPAIR, NULL)) + || !TEST_ptr(pkey)) + goto end; + + /* First test it continues (classic behavior) */ + if (!TEST_ptr(mctx = EVP_MD_CTX_new()) + || !TEST_true(EVP_DigestSignInit_ex(mctx, NULL, NULL, testctx, + NULL, pkey, NULL)) + || !TEST_true(EVP_DigestSignUpdate(mctx, sigbuf, sizeof(sigbuf))) + || !TEST_true(EVP_DigestSignFinal(mctx, signature, &siglen)) + || !TEST_true(EVP_DigestSignUpdate(mctx, sigbuf, sizeof(sigbuf))) + || !TEST_true(EVP_DigestSignFinal(mctx, signature, &siglen))) + goto end; + + EVP_MD_CTX_free(mctx); + + /* try again but failing the continuation */ + if (!TEST_ptr(mctx = EVP_MD_CTX_new()) + || !TEST_true(EVP_DigestSignInit_ex(mctx, NULL, NULL, testctx, + NULL, pkey, nodup_params)) + || !TEST_true(EVP_DigestSignUpdate(mctx, sigbuf, sizeof(sigbuf))) + || !TEST_true(EVP_DigestSignFinal(mctx, signature, &siglen)) + || !TEST_false(EVP_DigestSignUpdate(mctx, sigbuf, sizeof(sigbuf))) + || !TEST_false(EVP_DigestSignFinal(mctx, signature, &siglen))) + goto end; + + testresult = 1; + +end: + EVP_MD_CTX_free(mctx); + EVP_PKEY_free(pkey); + EVP_PKEY_CTX_free(pctx); + fake_rsa_finish(fake_rsa); + return testresult; +} + int setup_tests(void) { OPTION_CHOICE o; @@ -4858,6 +4918,8 @@ int setup_tests(void) ADD_ALL_TESTS(test_ecx_not_private_key, OSSL_NELEM(keys)); #endif + ADD_TEST(test_sign_continuation); + return 1; } diff --git a/test/fake_rsaprov.c b/test/fake_rsaprov.c index 5e92e72d4b3..bbb74a21474 100644 --- a/test/fake_rsaprov.c +++ b/test/fake_rsaprov.c @@ -346,11 +346,170 @@ static int fake_rsa_sig_sign(void *ctx, unsigned char *sig, return 1; } +#define FAKE_DGSTSGN_SIGN 0x01 +#define FAKE_DGSTSGN_VERIFY 0x02 +#define FAKE_DGSTSGN_UPDATED 0x04 +#define FAKE_DGSTSGN_FINALISED 0x08 +#define FAKE_DGSTSGN_NO_DUP 0xA0 + +static void *fake_rsa_sig_dupctx(void *ctx) +{ + unsigned char *sigctx = ctx; + unsigned char *newctx; + + if ((*sigctx & FAKE_DGSTSGN_NO_DUP) != 0) + return NULL; + + if (!TEST_ptr(newctx = OPENSSL_zalloc(1))) + return NULL; + + *newctx = *sigctx; + return newctx; +} + +static int fake_rsa_dgstsgnvfy_init(void *ctx, unsigned char type, + void *provkey, const OSSL_PARAM params[]) +{ + unsigned char *sigctx = ctx; + struct fake_rsa_keydata *keydata = provkey; + + /* we must have a ctx */ + if (!TEST_ptr(sigctx)) + return 0; + + /* we must have some initialized key */ + if (!TEST_ptr(keydata) || !TEST_int_gt(keydata->status, 0)) + return 0; + + /* record that sign/verify init was called */ + *sigctx = type; + + if (params) { + const OSSL_PARAM *p; + int dup; + p = OSSL_PARAM_locate_const(params, "NO_DUP"); + if (p != NULL) { + if (OSSL_PARAM_get_int(p, &dup)) { + *sigctx |= FAKE_DGSTSGN_NO_DUP; + } + } + } + + return 1; +} + +static int fake_rsa_dgstsgn_init(void *ctx, const char *mdname, + void *provkey, const OSSL_PARAM params[]) +{ + return fake_rsa_dgstsgnvfy_init(ctx, FAKE_DGSTSGN_SIGN, provkey, params); +} + +static int fake_rsa_dgstvfy_init(void *ctx, const char *mdname, + void *provkey, const OSSL_PARAM params[]) +{ + return fake_rsa_dgstsgnvfy_init(ctx, FAKE_DGSTSGN_VERIFY, provkey, params); +} + +static int fake_rsa_dgstsgnvfy_update(void *ctx, const unsigned char *data, + size_t datalen) +{ + unsigned char *sigctx = ctx; + + /* we must have a ctx */ + if (!TEST_ptr(sigctx)) + return 0; + + if (*sigctx == 0 || (*sigctx & FAKE_DGSTSGN_FINALISED) != 0) + return 0; + + *sigctx |= FAKE_DGSTSGN_UPDATED; + return 1; +} + +static int fake_rsa_dgstsgnvfy_final(void *ctx, unsigned char *sig, + size_t *siglen, size_t sigsize) +{ + unsigned char *sigctx = ctx; + + /* we must have a ctx */ + if (!TEST_ptr(sigctx)) + return 0; + + if (*sigctx == 0 || (*sigctx & FAKE_DGSTSGN_FINALISED) != 0) + return 0; + + if ((*sigctx & FAKE_DGSTSGN_SIGN) != 0 && (siglen == NULL)) + return 0; + + if ((*sigctx & FAKE_DGSTSGN_VERIFY) != 0 && (siglen != NULL)) + return 0; + + /* this is sign op */ + if (siglen) { + *siglen = 256; + /* record that the real sign operation was called */ + if (sig != NULL) { + if (!TEST_int_ge(sigsize, *siglen)) + return 0; + /* produce a fake signature */ + memset(sig, 'a', *siglen); + } + } + + /* simulate inability to duplicate context and finalise it */ + if ((*sigctx & FAKE_DGSTSGN_NO_DUP) != 0) { + *sigctx |= FAKE_DGSTSGN_FINALISED; + } + return 1; +} + +static int fake_rsa_dgstvfy_final(void *ctx, unsigned char *sig, + size_t siglen) +{ + return fake_rsa_dgstsgnvfy_final(ctx, sig, NULL, siglen); +} + +static int fake_rsa_dgstsgn(void *ctx, unsigned char *sig, size_t *siglen, + size_t sigsize, const unsigned char *tbs, + size_t tbslen) +{ + if (!fake_rsa_dgstsgnvfy_update(ctx, tbs, tbslen)) + return 0; + + return fake_rsa_dgstsgnvfy_final(ctx, sig, siglen, sigsize); +} + +static int fake_rsa_dgstvfy(void *ctx, unsigned char *sig, size_t siglen, + const unsigned char *tbv, size_t tbvlen) +{ + if (!fake_rsa_dgstsgnvfy_update(ctx, tbv, tbvlen)) + return 0; + + return fake_rsa_dgstvfy_final(ctx, sig, siglen); +} + static const OSSL_DISPATCH fake_rsa_sig_funcs[] = { { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))fake_rsa_sig_newctx }, { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))fake_rsa_sig_freectx }, { OSSL_FUNC_SIGNATURE_SIGN_INIT, (void (*)(void))fake_rsa_sig_sign_init }, { OSSL_FUNC_SIGNATURE_SIGN, (void (*)(void))fake_rsa_sig_sign }, + { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))fake_rsa_sig_dupctx }, + { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT, + (void (*)(void))fake_rsa_dgstsgn_init }, + { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE, + (void (*)(void))fake_rsa_dgstsgnvfy_update }, + { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL, + (void (*)(void))fake_rsa_dgstsgnvfy_final }, + { OSSL_FUNC_SIGNATURE_DIGEST_SIGN, + (void (*)(void))fake_rsa_dgstsgn }, + { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT, + (void (*)(void))fake_rsa_dgstvfy_init }, + { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE, + (void (*)(void))fake_rsa_dgstsgnvfy_update }, + { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL, + (void (*)(void))fake_rsa_dgstvfy_final }, + { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY, + (void (*)(void))fake_rsa_dgstvfy }, { 0, NULL } }; -- 2.47.2