]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Add test for context duplication failure
authorSimo Sorce <simo@redhat.com>
Mon, 6 Mar 2023 23:38:00 +0000 (18:38 -0500)
committerPauli <pauli@openssl.org>
Tue, 14 Mar 2023 21:42:56 +0000 (08:42 +1100)
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 <simo@redhat.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
(Merged from https://github.com/openssl/openssl/pull/20375)

test/build.info
test/evp_extra_test.c
test/fake_rsaprov.c

index 15c0985150f074682da32c515a3db02f8d451ff4..99f27e12b5c56f7c0601529b2735fc0df82254bb 100644 (file)
@@ -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
 
index 9230e7b99500053eade9b9080e84d8982928877a..a829a1f7ef5af5e6fcef6a980b231483f4871409 100644 (file)
@@ -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;
 }
 
index 5e92e72d4b39b67db8bf749fcd047cdc624b26a0..bbb74a21474b64d740c6a1307ea680dcca1f6c46 100644 (file)
@@ -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 }
 };