]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Add FIPS DSA Keygen tests
authorslontis <shane.lontis@oracle.com>
Wed, 24 Jul 2024 07:24:33 +0000 (17:24 +1000)
committerTomas Mraz <tomas@openssl.org>
Tue, 6 Aug 2024 09:01:13 +0000 (11:01 +0200)
Adjust the existing tests to disable DSA keygen in FIPS mode.

Allow evp_test to load DSA 'KeyParams' that can then be used to
perform a DSA KeyGen.

Reviewed-by: Paul Dale <ppzgs1@gmail.com>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/24978)

test/acvp_test.c
test/dsatest.c
test/evp_libctx_test.c
test/evp_test.c
test/recipes/15-test_gendsa.t
test/recipes/30-test_evp_data/evppkey_dsa.txt
test/testutil/stanza.c

index 82ecaf8b00eeb7f863ccda0bbbe6eac45046f6f2..623fab028c40244622c8a7e304fb7996be2b5e7a 100644 (file)
@@ -347,7 +347,7 @@ static EVP_PKEY *dsa_paramgen(int L, int N)
         || !TEST_true(EVP_PKEY_CTX_set_dsa_paramgen_bits(paramgen_ctx, L))
         || !TEST_true(EVP_PKEY_CTX_set_dsa_paramgen_q_bits(paramgen_ctx, N))
         || !TEST_true(EVP_PKEY_paramgen(paramgen_ctx, &param_key)))
-        return NULL;
+        TEST_info("dsa_paramgen failed");
     EVP_PKEY_CTX_free(paramgen_ctx);
     return param_key;
 }
@@ -378,6 +378,10 @@ static int dsa_keygen_test(int id)
     size_t priv_len = 0, pub_len = 0;
     const struct dsa_paramgen_st *tst = &dsa_keygen_data[id];
 
+    if (!dsasign_allowed) {
+        TEST_info("DSA keygen test skipped: DSA signing is not allowed");
+        return 1;
+    }
     if (!TEST_ptr(param_key = dsa_paramgen(tst->L, tst->N))
         || !TEST_ptr(keygen_ctx = EVP_PKEY_CTX_new_from_pkey(libctx, param_key,
                                                              NULL))
@@ -421,23 +425,31 @@ static int dsa_paramgen_test(int id)
     if (!TEST_ptr(paramgen_ctx = EVP_PKEY_CTX_new_from_name(libctx, "DSA", NULL))
         || !TEST_int_gt(EVP_PKEY_paramgen_init(paramgen_ctx), 0)
         || !TEST_true(EVP_PKEY_CTX_set_dsa_paramgen_bits(paramgen_ctx, tst->L))
-        || !TEST_true(EVP_PKEY_CTX_set_dsa_paramgen_q_bits(paramgen_ctx, tst->N))
-        || !TEST_true(EVP_PKEY_paramgen(paramgen_ctx, &param_key))
-        || !TEST_true(pkey_get_bn_bytes(param_key, OSSL_PKEY_PARAM_FFC_P,
-                                        &p, &plen))
-        || !TEST_true(pkey_get_bn_bytes(param_key, OSSL_PKEY_PARAM_FFC_Q,
-                                        &q, &qlen))
-        || !TEST_true(pkey_get_octet_bytes(param_key, OSSL_PKEY_PARAM_FFC_SEED,
-                                           &seed, &seedlen))
-        || !TEST_true(EVP_PKEY_get_int_param(param_key,
-                                             OSSL_PKEY_PARAM_FFC_PCOUNTER,
-                                             &counter)))
-        goto err;
-
-    test_output_memory("p", p, plen);
-    test_output_memory("q", q, qlen);
-    test_output_memory("domainSeed", seed, seedlen);
-    test_printf_stderr("%s: %d\n", "counter", counter);
+        || !TEST_true(EVP_PKEY_CTX_set_dsa_paramgen_q_bits(paramgen_ctx,
+                                                           tst->N)))
+        goto err;
+
+    if (!dsasign_allowed) {
+        if (!TEST_false(EVP_PKEY_paramgen(paramgen_ctx, &param_key)))
+            goto err;
+    } else {
+        if (!TEST_true(EVP_PKEY_paramgen(paramgen_ctx, &param_key))
+            || !TEST_true(pkey_get_bn_bytes(param_key, OSSL_PKEY_PARAM_FFC_P,
+                                            &p, &plen))
+            || !TEST_true(pkey_get_bn_bytes(param_key, OSSL_PKEY_PARAM_FFC_Q,
+                                            &q, &qlen))
+            || !TEST_true(pkey_get_octet_bytes(param_key,
+                                               OSSL_PKEY_PARAM_FFC_SEED,
+                                               &seed, &seedlen))
+            || !TEST_true(EVP_PKEY_get_int_param(param_key,
+                                                 OSSL_PKEY_PARAM_FFC_PCOUNTER,
+                                                 &counter)))
+            goto err;
+        test_output_memory("p", p, plen);
+        test_output_memory("q", q, qlen);
+        test_output_memory("domainSeed", seed, seedlen);
+        test_printf_stderr("%s: %d\n", "counter", counter);
+    }
     ret = 1;
 err:
     OPENSSL_free(p);
@@ -597,10 +609,12 @@ static int dsa_siggen_test(int id)
     size_t sig_len = 0, rlen = 0, slen = 0;
     const struct dsa_siggen_st *tst = &dsa_siggen_data[id];
 
-    if (!TEST_ptr(pkey = dsa_keygen(tst->L, tst->N)))
-        goto err;
-
-    if (dsasign_allowed) {
+    if (!dsasign_allowed) {
+        if (!TEST_ptr_null(pkey = dsa_keygen(tst->L, tst->N)))
+            goto err;
+    } else {
+        if (!TEST_ptr(pkey = dsa_keygen(tst->L, tst->N)))
+            goto err;
         if (!TEST_true(sig_gen(pkey, NULL, tst->digest_alg, tst->msg, tst->msg_len,
                                &sig, &sig_len))
             || !TEST_true(get_dsa_sig_rs_bytes(sig, sig_len, &r, &s, &rlen, &slen)))
index 73c6827bb0defe1189647838624c8a7b20bd1ed6..e8839c71765296cb8e4a0c45d0d6f26a9f0bb360 100644 (file)
@@ -247,7 +247,7 @@ static int dsa_keygen_test(void)
         goto end;
     if (!TEST_ptr(pg_ctx = EVP_PKEY_CTX_new_from_name(NULL, "DSA", NULL))
         || !TEST_int_gt(EVP_PKEY_paramgen_init(pg_ctx), 0)
-        || !TEST_ptr_null(EVP_PKEY_CTX_gettable_params(pg_ctx))
+        || !TEST_ptr(EVP_PKEY_CTX_gettable_params(pg_ctx))
         || !TEST_ptr(settables = EVP_PKEY_CTX_settable_params(pg_ctx))
         || !TEST_ptr(OSSL_PARAM_locate_const(settables,
                                              OSSL_PKEY_PARAM_FFC_PBITS))
index 35a112719372b621ebd0dcf40353f84b462529c6..65e63cffe89ce3d03123a47a1e7d3b884d98dad9 100644 (file)
@@ -781,7 +781,9 @@ int setup_tests(void)
     ADD_TEST(test_evp_cipher_api_safety);
 
 #if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_DH)
-    ADD_ALL_TESTS(test_dsa_param_keygen, 3 * 3 * 3);
+    if (strcmp(prov_name, "fips") != 0
+            || fips_provider_version_lt(libctx, 3, 4, 0))
+        ADD_ALL_TESTS(test_dsa_param_keygen, 3 * 3 * 3);
 #endif
 #ifndef OPENSSL_NO_DH
     ADD_ALL_TESTS(test_dh_safeprime_param_keygen, 3 * 3 * 3);
index b817f72b00824704ea40a85af9c3e549b4e4555f..c3d28cdf711e1ee51f1c4d8159dede4d466cba78 100644 (file)
@@ -153,6 +153,13 @@ static int pkey_check_fips_approved(EVP_PKEY_CTX *ctx, EVP_TEST *t)
      * value of approved.
      */
     int approved = 1;
+    const OSSL_PARAM *gettables = EVP_PKEY_CTX_gettable_params(ctx);
+
+    if (gettables == NULL
+            || OSSL_PARAM_locate_const(gettables,
+                                       OSSL_ALG_PARAM_FIPS_APPROVED_INDICATOR)
+            == NULL)
+        return 1;
 
     /* Older providers dont have a gettable */
     if (EVP_PKEY_CTX_gettable_params(ctx) == NULL)
@@ -3879,14 +3886,15 @@ static const EVP_TEST_METHOD keypair_test_method = {
  **/
 
 typedef struct keygen_test_data_st {
-    EVP_PKEY_CTX *genctx; /* Keygen context to use */
     char *keyname; /* Key name to store key or NULL */
+    char *paramname;
+    char *alg;
+    STACK_OF(OPENSSL_STRING) *controls; /* Collection of controls */
 } KEYGEN_TEST_DATA;
 
 static int keygen_test_init(EVP_TEST *t, const char *alg)
 {
     KEYGEN_TEST_DATA *data;
-    EVP_PKEY_CTX *genctx;
     int nid = OBJ_sn2nid(alg);
 
     if (nid == NID_undef) {
@@ -3899,24 +3907,17 @@ static int keygen_test_init(EVP_TEST *t, const char *alg)
         t->skip = 1;
         return 1;
     }
-    if (!TEST_ptr(genctx = EVP_PKEY_CTX_new_from_name(libctx, alg, propquery)))
-        goto err;
-
-    if (EVP_PKEY_keygen_init(genctx) <= 0) {
-        t->err = "KEYGEN_INIT_ERROR";
-        goto err;
-    }
 
     if (!TEST_ptr(data = OPENSSL_malloc(sizeof(*data))))
         goto err;
-    data->genctx = genctx;
     data->keyname = NULL;
+    data->alg = OPENSSL_strdup(alg);
+    data->paramname = NULL;
+    data->controls = sk_OPENSSL_STRING_new_null();
     t->data = data;
     t->err = NULL;
     return 1;
-
 err:
-    EVP_PKEY_CTX_free(genctx);
     return 0;
 }
 
@@ -3924,7 +3925,9 @@ static void keygen_test_cleanup(EVP_TEST *t)
 {
     KEYGEN_TEST_DATA *keygen = t->data;
 
-    EVP_PKEY_CTX_free(keygen->genctx);
+    ctrlfree(keygen->controls);
+    OPENSSL_free(keygen->alg);
+    OPENSSL_free(keygen->paramname);
     OPENSSL_free(keygen->keyname);
     OPENSSL_free(t->data);
     t->data = NULL;
@@ -3937,21 +3940,57 @@ static int keygen_test_parse(EVP_TEST *t,
 
     if (strcmp(keyword, "KeyName") == 0)
         return TEST_ptr(keygen->keyname = OPENSSL_strdup(value));
+    if (strcmp(keyword, "KeyParam") == 0)
+        return TEST_ptr(keygen->paramname = OPENSSL_strdup(value));
     if (strcmp(keyword, "Ctrl") == 0)
-        return pkey_test_ctrl(t, keygen->genctx, value);
+        return ctrladd(keygen->controls, value);
     return 0;
 }
 
 static int keygen_test_run(EVP_TEST *t)
 {
     KEYGEN_TEST_DATA *keygen = t->data;
-    EVP_PKEY *pkey = NULL;
-    int rv = 1;
+    EVP_PKEY *pkey = NULL, *keyparams = NULL;
+    EVP_PKEY_CTX *genctx = NULL; /* Keygen context to use */
+    int rv = 1, i;
+
+    if (keygen->paramname != NULL) {
+        rv = find_key(&keyparams, keygen->paramname, public_keys);
+        if (rv == 0 || keyparams == NULL) {
+            TEST_info("skipping, key '%s' is disabled", keygen->paramname);
+            t->skip = 1;
+            return 1;
+        }
+        if (!TEST_ptr(genctx = EVP_PKEY_CTX_new_from_pkey(libctx, keyparams,
+                                                          propquery)))
+            goto err;
+
+    } else {
+        if (!TEST_ptr(genctx = EVP_PKEY_CTX_new_from_name(libctx, keygen->alg,
+                                                          propquery)))
+            goto err;
+    }
+
+    if (EVP_PKEY_keygen_init(genctx) <= 0) {
+        t->err = "KEYGEN_INIT_ERROR";
+        goto err;
+    }
 
-    if (EVP_PKEY_keygen(keygen->genctx, &pkey) <= 0) {
+    for (i = 0; i < sk_OPENSSL_STRING_num(keygen->controls); ++i) {
+        if (!pkey_test_ctrl(t, genctx,
+                            sk_OPENSSL_STRING_value(keygen->controls, i))
+                || t->err != NULL)
+            goto err;
+    }
+
+    if (EVP_PKEY_keygen(genctx, &pkey) <= 0) {
         t->err = "KEYGEN_GENERATE_ERROR";
         goto err;
     }
+    if (!pkey_check_fips_approved(genctx, t)) {
+        rv = 0;
+        goto err;
+    }
 
     if (!evp_pkey_is_provided(pkey)) {
         TEST_info("Warning: legacy key generated %s", keygen->keyname);
@@ -3979,8 +4018,8 @@ static int keygen_test_run(EVP_TEST *t)
     }
 
     t->err = NULL;
-
 err:
+    EVP_PKEY_CTX_free(genctx);
     return rv;
 }
 
@@ -4662,6 +4701,15 @@ start:
             return 0;
         }
         klist = &public_keys;
+    } else if (strcmp(pp->key, "ParamKey") == 0) {
+        pkey = PEM_read_bio_Parameters_ex(t->s.key, NULL, libctx, NULL);
+        if (pkey == NULL && !key_unsupported()) {
+            EVP_PKEY_free(pkey);
+            TEST_info("Can't read params key %s", pp->value);
+            TEST_openssl_errors();
+            return 0;
+        }
+        klist = &public_keys;
     } else if (strcmp(pp->key, "PrivateKeyRaw") == 0
                || strcmp(pp->key, "PublicKeyRaw") == 0) {
         char *strnid = NULL, *keydata = NULL;
index 4bc460784b4612b231e9d65915c8d4325d6bf35d..cd331c4cfc22fb21b5c0906efcb0e91025e7e90b 100644 (file)
@@ -1,5 +1,5 @@
 #! /usr/bin/env perl
-# Copyright 2017-2023 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2017-2024 The OpenSSL Project Authors. All Rights Reserved.
 #
 # Licensed under the Apache License 2.0 (the "License").  You may not use
 # this file except in compliance with the License.  You can obtain a copy
@@ -160,22 +160,28 @@ unless ($no_fips) {
 
     $ENV{OPENSSL_TEST_LIBCTX} = "1";
 
+    # DSA signing/keygen is not approved in FIPS 140-3
+    run(test(["fips_version_test", "-config", $provconf, "<3.4.0"]),
+             capture => 1, statusvar => \my $dsasignpass);
+
     # Generate params
-    ok(run(app(['openssl', 'genpkey',
+    is(run(app(['openssl', 'genpkey',
                 @prov,
                '-genparam',
                '-algorithm', 'DSA',
                '-pkeyopt', 'pbits:3072',
                '-pkeyopt', 'qbits:256',
                '-out', 'gendsatest3072params.pem'])),
+       $dsasignpass,
        "Generating 3072-bit DSA params");
 
     # Generate keypair
-    ok(run(app(['openssl', 'genpkey',
+    is(run(app(['openssl', 'genpkey',
                 @prov,
                '-paramfile', 'gendsatest3072params.pem',
                '-text',
                '-out', 'gendsatest3072.pem'])),
+       $dsasignpass,
        "Generating 3072-bit DSA keypair");
 
 }
index 1109abb4531a35b10fe37b6ca583955f5cad9fcc..51c4405b158b72ba2e23712d307b6a69cf4eb64d 100644 (file)
@@ -437,3 +437,43 @@ CtrlInit = sign-check:0
 Key = DSA-2048-256
 Input = "Hello"
 Result = DIGESTSIGNINIT_ERROR
+
+Title = Test DSA keygen
+
+# Load DSA Params to use in the DSA keygen tests 
+ParamKey = DSA-2048-PARAMS
+-----BEGIN DSA PARAMETERS-----
+MIICKAKCAQEAgrJrFYjhhJ3NnIBSRNpVK5+gze+9fA4Ce0Yjbiz3KOU2TTtE1mbf
+lGVsjuAEX2c/cBUWFEjg77EoGCFCpfbzSh6nd2DgCiFaw91ak3GuQ+yKs55SyeQV
+ikUQaAILVm0SgIPhdCUtG5XdghJyNUTEHFowWXh3gaQDaRB6MqxbMj0a9LoRwYAw
+Mo/9bug6Uh/ITEKjoBertznRW8SflHhATvc6eCL6NXi3qhkQIgYDdwxUGGz1SnfH
+wUTYcvu2eogv+0WAnnxCJh51qv2gUynH4TLeL9g/jskcJfvYtejJ+k/G3Q6dsEn/
+an8pdKdH0MaplOZNB6nJSa1H0VZfg9V9VQIdALq9dtHaBpeXSal0qhn0P/nmR9ID
+I1Yn4K1l33cCggEAAulOaqN0hBs9DXQyljrKesD8zTLgIsabgyEauuyFfsZp5ezU
+762cnqDde20DPTHu1hbVmw68hvKDAWNpVzMMsopFPPWt8JwnEHSMZxwv08RxBET9
+HQXL4+YxA9hfAmtRkUK+QdZFRdXv4AjnxcLyNbIqT/uPm1c/+Dd7875rIzTcW3cc
+IvhlS7VgfwIg0IUuGF2uXt/6P7zInftR+nan4/DbNWind5308I7l4jchRjUDRlsK
+WbJpcH2m2K43Ue0MUKIki1dTlH07PiHUuY4wQ+jInWtnnRQlLGSw+LdrD7gwpFYY
+w/lWdpSTr0aHbSvxD9vcrUzKljFY6iSQF32wcg==
+-----END DSA PARAMETERS-----
+
+# FIPS Key generation tests
+
+# Test FIPS DSA keygen is not allowed 
+Availablein = fips
+FIPSversion = >=3.4.0
+KeyGen = DSA
+KeyParam = DSA-2048-PARAMS
+KeyName = tmp1dsa
+Result = KEYGEN_GENERATE_ERROR
+
+Title = Test DSA keygen FIPS indicator test
+
+# Test DSA keygen is not approved
+Availablein = fips
+FIPSversion = >=3.4.0
+KeyGen = DSA
+KeyParam = DSA-2048-PARAMS
+KeyName = tmp2dsa
+Unapproved = 1
+Ctrl = sign-check:0
index a3f833a543e8869118afb83443581d67f0140553..69edfad6686010fad26760fc01abceb284535dcb 100644 (file)
@@ -126,11 +126,9 @@ int test_readstanza(STANZA *s)
         if (s->numpairs == 0)
             s->start = s->curr;
 
-        if (strcmp(key, "PrivateKey") == 0) {
-            if (!read_key(s))
-                return 0;
-        }
-        if (strcmp(key, "PublicKey") == 0) {
+        if (strcmp(key, "PrivateKey") == 0
+                || strcmp(key, "PublicKey") == 0
+                || strcmp(key, "ParamKey") == 0) {
             if (!read_key(s))
                 return 0;
         }