From 06da14737369e7c90899aed4bb21cce9a0910d29 Mon Sep 17 00:00:00 2001 From: slontis Date: Wed, 3 Jul 2024 11:12:39 +1000 Subject: [PATCH] Add FIPS indicators to evp_test evp_test code needed to be modified to defer setting algorithm contexts until the run phase. The parse functions also defer setting into the context until the run phase, which allows the context to initialize in a controlled order. This allows params to be passed into the algorithm init function. Reviewed-by: Neil Horman Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/24623) --- test/evp_test.c | 792 ++++++++++++++---- .../30-test_evp_data/evpkdf_tls12_prf.txt | 22 + test/recipes/30-test_evp_data/evppkey_dsa.txt | 45 +- test/recipes/30-test_evp_data/evppkey_ecc.txt | 11 +- .../recipes/30-test_evp_data/evppkey_ecdh.txt | 2 +- .../30-test_evp_data/evppkey_ecdsa.txt | 48 +- .../30-test_evp_data/evppkey_ffdhe.txt | 16 +- test/recipes/30-test_evp_data/evppkey_kas.txt | 2 +- test/recipes/30-test_evp_data/evppkey_rsa.txt | 37 +- .../30-test_evp_data/evppkey_rsa_common.txt | 58 +- test/recipes/30-test_evp_data/evprand.txt | 38 + util/libcrypto.num | 2 + 12 files changed, 895 insertions(+), 178 deletions(-) diff --git a/test/evp_test.c b/test/evp_test.c index 71fea6f47ffa8..9ebcd29e09fa6 100644 --- a/test/evp_test.c +++ b/test/evp_test.c @@ -45,6 +45,7 @@ typedef struct evp_test_st { char *expected_err; /* Expected error value of test */ char *reason; /* Expected error reason string */ void *data; /* test specific data */ + int expect_unapproved; } EVP_TEST; /* Test method structure */ @@ -82,6 +83,7 @@ typedef enum OPTION_choice { static OSSL_PROVIDER *prov_null = NULL; static OSSL_PROVIDER *libprov = NULL; static OSSL_LIB_CTX *libctx = NULL; +static int fips_indicator_callback_unapproved_count = 0; /* List of public and private keys */ static KEY_LIST *private_keys; @@ -97,6 +99,162 @@ static int is_mac_disabled(const char *name); static int is_cipher_disabled(const char *name); static int is_kdf_disabled(const char *name); +/* A callback that is triggered if fips unapproved mode is detected */ +static int fips_indicator_cb(const char *type, const char *desc, + const OSSL_PARAM params[]) +{ + fips_indicator_callback_unapproved_count++; + TEST_info("(Indicator Callback received %s : %s is not approved)", type, desc); + return 1; +} + +static int check_fips_approved(EVP_TEST *t, int approved) +{ + /* + * If the expected result is approved + * then it is expected that approved will be 1 + * and the fips indicator callback has not been triggered, otherwise + * approved should be 0 and the fips indicator callback should be triggered. + */ + if (t->expect_unapproved) { + if (approved == 1 || fips_indicator_callback_unapproved_count == 0) + return 0; + } else { + if (approved == 0 || fips_indicator_callback_unapproved_count > 0) + return 0; + } + return 1; +} + +static int pkey_check_fips_approved(EVP_PKEY_CTX *ctx, EVP_TEST *t) +{ + OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; + /* + * For any getters that do not handle the FIPS indicator assume a default + * value of approved. + */ + int approved = 1; + + params[0] = OSSL_PARAM_construct_int(OSSL_ALG_PARAM_FIPS_APPROVED_INDICATOR, + &approved); + if (!EVP_PKEY_CTX_get_params(ctx, params)) + return 0; + return check_fips_approved(t, approved); +} + +static int rand_check_fips_approved(EVP_RAND_CTX *ctx, EVP_TEST *t) +{ + OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; + /* + * For any getters that do not handle the FIPS indicator assume a default + * value of approved. + */ + int approved = 1; + + params[0] = OSSL_PARAM_construct_int(OSSL_DRBG_PARAM_FIPS_APPROVED_INDICATOR, + &approved); + if (!EVP_RAND_CTX_get_params(ctx, params)) + return 0; + return check_fips_approved(t, approved); +} + +static int ctrladd(STACK_OF(OPENSSL_STRING) *controls, const char *value) +{ + char *data = OPENSSL_strdup(value); + + if (data == NULL) + return -1; + return sk_OPENSSL_STRING_push(controls, data) > 0; +} + +/* Because OPENSSL_free is a macro, it can't be passed as a function pointer */ +static void openssl_free(char *m) +{ + OPENSSL_free(m); +} + +static void ctrlfree(STACK_OF(OPENSSL_STRING) *controls) +{ + sk_OPENSSL_STRING_pop_free(controls, openssl_free); +} + +/* + * This is used if ctrl2params() passes settables as NULL. + * A default list of settable OSSL_PARAM that may be set during an operations + * init(). + * Using the algorithms settable list is problematic since it requires that the + * init() has already run. + */ +static const OSSL_PARAM settable_ctx_params[] = { + OSSL_PARAM_int("key-check", NULL), + OSSL_PARAM_int("digest-check", NULL), + OSSL_PARAM_int("ems_check", NULL), + OSSL_PARAM_END +}; + +static int ctrl2params(EVP_TEST *t, STACK_OF(OPENSSL_STRING) *controls, + const OSSL_PARAM *settables, + OSSL_PARAM params[], size_t params_sz, size_t *params_n) +{ + int i; + + if (settables == NULL) + settables = settable_ctx_params; + /* check bounds */ + if (*params_n + sk_OPENSSL_STRING_num(controls) >= params_sz) { + t->err = "ERR_TOO_MANY_PARAMETERS"; + goto err; + } + for (i = 0; i < sk_OPENSSL_STRING_num(controls); i++) { + char *tmpkey, *tmpval; + char *value = sk_OPENSSL_STRING_value(controls, i); + + if (!TEST_ptr(tmpkey = OPENSSL_strdup(value))) { + t->err = "ERR_PARAM_ERROR"; + goto err; + } + tmpval = strchr(tmpkey, ':'); + if (tmpval != NULL) + *tmpval++ = '\0'; + + if (tmpval == NULL + || !OSSL_PARAM_allocate_from_text(¶ms[*params_n], + settables, + tmpkey, tmpval, + strlen(tmpval), NULL)) { + OPENSSL_free(tmpkey); + t->err = "ERR_PARAM_ERROR"; + goto err; + } + *params_n += 1; + OPENSSL_free(tmpkey); + } + params[*params_n] = OSSL_PARAM_construct_end(); + return 1; +err: + return 0; +} + +static void ctrl2params_free(OSSL_PARAM params[], + size_t params_n, size_t params_n_allocstart) +{ + while (params_n-- > params_n_allocstart) { + OPENSSL_free(params[params_n].data); + } +} + +static int kdf_check_fips_approved(EVP_KDF_CTX *ctx, EVP_TEST *t) +{ + OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; + int approved = 1; + + params[0] = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_FIPS_APPROVED_INDICATOR, + &approved); + if (!EVP_KDF_CTX_get_params(ctx, params)) + return 0; + return check_fips_approved(t, approved); +} + /* * Compare two memory regions for equality, returning zero if they differ. * However, if there is expected to be an error and the actual error @@ -1421,12 +1579,6 @@ static int mac_test_init(EVP_TEST *t, const char *alg) return 1; } -/* Because OPENSSL_free is a macro, it can't be passed as a function pointer */ -static void openssl_free(char *m) -{ - OPENSSL_free(m); -} - static void mac_test_cleanup(EVP_TEST *t) { MAC_DATA *mdat = t->data; @@ -1470,13 +1622,8 @@ static int mac_test_parse(EVP_TEST *t, return mdata->xof = 1; if (strcmp(keyword, "NoReinit") == 0) return mdata->no_reinit = 1; - if (strcmp(keyword, "Ctrl") == 0) { - char *data = OPENSSL_strdup(value); - - if (data == NULL) - return -1; - return sk_OPENSSL_STRING_push(mdata->controls, data) != 0; - } + if (strcmp(keyword, "Ctrl") == 0) + return ctrladd(mdata->controls, value); if (strcmp(keyword, "OutputSize") == 0) { mdata->output_size = atoi(value); if (mdata->output_size < 0) @@ -1643,8 +1790,8 @@ static int mac_test_run_mac(EVP_TEST *t) unsigned char *got = NULL; size_t got_len = 0, size = 0; size_t size_before_init = 0, size_after_init, size_val = 0; - int i, block_size = -1, output_size = -1; - OSSL_PARAM params[21], sizes[3], *psizes = sizes; + int block_size = -1, output_size = -1; + OSSL_PARAM params[21], sizes[3], *psizes = sizes, *p; size_t params_n = 0; size_t params_n_allocstart = 0; const OSSL_PARAM *defined_params = @@ -1710,42 +1857,14 @@ static int mac_test_run_mac(EVP_TEST *t) expected->iv, expected->iv_len); - /* Unknown controls. They must match parameters that the MAC recognizes */ - if (params_n + sk_OPENSSL_STRING_num(expected->controls) - >= OSSL_NELEM(params)) { - t->err = "MAC_TOO_MANY_PARAMETERS"; - goto err; - } params_n_allocstart = params_n; - for (i = 0; i < sk_OPENSSL_STRING_num(expected->controls); i++) { - char *tmpkey, *tmpval; - char *value = sk_OPENSSL_STRING_value(expected->controls, i); - - if (!TEST_ptr(tmpkey = OPENSSL_strdup(value))) { - t->err = "MAC_PARAM_ERROR"; - goto err; - } - tmpval = strchr(tmpkey, ':'); - if (tmpval != NULL) - *tmpval++ = '\0'; - - if (tmpval == NULL - || !OSSL_PARAM_allocate_from_text(¶ms[params_n], - defined_params, - tmpkey, tmpval, - strlen(tmpval), NULL)) { - OPENSSL_free(tmpkey); - t->err = "MAC_PARAM_ERROR"; - goto err; - } - params_n++; - - if (strcmp(tmpkey, "size") == 0) - size_val = (size_t)strtoul(tmpval, NULL, 0); + if (!ctrl2params(t, expected->controls, defined_params, + params, OSSL_NELEM(params), ¶ms_n)) + goto err; - OPENSSL_free(tmpkey); - } - params[params_n] = OSSL_PARAM_construct_end(); + p = OSSL_PARAM_locate(params + params_n_allocstart, "size"); + if (p != NULL) + OSSL_PARAM_get_size_t(p, &size_val); if ((ctx = EVP_MAC_CTX_new(expected->mac)) == NULL) { t->err = "MAC_CREATE_ERROR"; @@ -1894,9 +2013,7 @@ static int mac_test_run_mac(EVP_TEST *t) } } err: - while (params_n-- > params_n_allocstart) { - OPENSSL_free(params[params_n].data); - } + ctrl2params_free(params, params_n, params_n_allocstart); EVP_MAC_CTX_free(ctx); OPENSSL_free(got); return 1; @@ -1919,6 +2036,217 @@ static const EVP_TEST_METHOD mac_test_method = { mac_test_run }; +typedef struct kem_data_st { + /* Context for this operation */ + EVP_PKEY_CTX *ctx; + const char *op; + /* Input to decapsulate */ + unsigned char *input; + size_t inputlen; + /* Expected secret */ + unsigned char *output; + size_t outputlen; + STACK_OF(OPENSSL_STRING) *init_ctrls; +} KEM_DATA; + +static int kem_test_init(EVP_TEST *t, const char *name) +{ + KEM_DATA *kdata = NULL; + EVP_PKEY *pkey = NULL; + int rv; + + rv = find_key(&pkey, name, private_keys); + if (rv == 0 || pkey == NULL) { + TEST_info("skipping, key '%s' is disabled", name); + t->skip = 1; + return 1; + } + + if (!TEST_ptr(kdata = OPENSSL_zalloc(sizeof(*kdata)))) + goto err; + if (!TEST_ptr(kdata->ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, propquery))) + goto err; + + t->data = kdata; + kdata->init_ctrls = sk_OPENSSL_STRING_new_null(); + return 1; +err: + EVP_PKEY_free(pkey); + OPENSSL_free(kdata); + return 0; +} + +static void kem_test_cleanup(EVP_TEST *t) +{ + KEM_DATA *kdata = t->data; + + ctrlfree(kdata->init_ctrls); + OPENSSL_free(kdata->input); + OPENSSL_free(kdata->output); + EVP_PKEY_CTX_free(kdata->ctx); +} + +static int kem_test_parse(EVP_TEST *t, const char *keyword, const char *value) +{ + KEM_DATA *kdata = t->data; + + if (strcmp(keyword, "Op") == 0) { + kdata->op = value; + return 1; + } + if (strcmp(keyword, "CtrlInit") == 0) + return ctrladd(kdata->init_ctrls, value); + if (strcmp(keyword, "Input") == 0) + return parse_bin(value, &kdata->input, &kdata->inputlen); + if (strcmp(keyword, "Output") == 0) + return parse_bin(value, &kdata->output, &kdata->outputlen); + return 1; +} + +static int encapsulate(EVP_TEST *t, EVP_PKEY_CTX *ctx, const char *op, + unsigned char **outwrapped, size_t *outwrappedlen, + unsigned char **outsecret, size_t *outsecretlen) +{ + int ret = 1; + KEM_DATA *kdata = t->data; + unsigned char *wrapped = NULL, *secret = NULL; + size_t wrappedlen = 0, secretlen = 0; + OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; + size_t params_n = 0, params_n_allocated = 0; + OSSL_PARAM *p = NULL; + + if (sk_OPENSSL_STRING_num(kdata->init_ctrls) > 0) { + if (ctrl2params(t, kdata->init_ctrls, NULL, + params, OSSL_NELEM(params), ¶ms_n)) + goto err; + p = params; + } + if (EVP_PKEY_encapsulate_init(ctx, p) <= 0) { + t->err = "TEST_ENCAPSULATE_INIT_ERROR"; + goto err; + } + + if (EVP_PKEY_CTX_set_kem_op(ctx, op) <= 0) { + t->err = "TEST_SET_KEM_OP_ERROR"; + goto err; + } + if (EVP_PKEY_encapsulate(ctx, NULL, &wrappedlen, NULL, &secretlen) <= 0) { + t->err = "TEST_ENCAPSULATE_LEN_ERROR"; + goto err; + } + wrapped = OPENSSL_malloc(wrappedlen); + secret = OPENSSL_malloc(secretlen); + if (!TEST_ptr(wrapped) || !TEST_ptr(secret)) { + ret = 0; + goto err; + } + if (EVP_PKEY_encapsulate(ctx, wrapped, &wrappedlen, secret, &secretlen) <= 0) { + t->err = "TEST_ENCAPSULATE_ERROR"; + goto err; + } + ret = pkey_check_fips_approved(ctx, t); + if (ret == 0) + goto err; + + t->err = NULL; + *outwrapped = wrapped; + *outsecret = secret; + *outwrappedlen = wrappedlen; + *outsecretlen = secretlen; + ret = 1; + goto end; +err: + OPENSSL_free(wrapped); + OPENSSL_free(secret); +end: + ctrl2params_free(params, params_n, params_n_allocated); + return ret; +} + +static int decapsulate(EVP_TEST *t, EVP_PKEY_CTX *ctx, const char *op, + const unsigned char *in, size_t inlen, + const unsigned char *expected, size_t expectedlen) +{ + int ret = 1; + KEM_DATA *kdata = t->data; + size_t outlen = 0; + unsigned char *out = NULL; + OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; + OSSL_PARAM *p = NULL; + size_t params_n = 0, params_n_allocated = 0; + + if (sk_OPENSSL_STRING_num(kdata->init_ctrls) > 0) { + if (!ctrl2params(t, kdata->init_ctrls, NULL, + params, OSSL_NELEM(params), ¶ms_n)) + goto err; + p = params; + } + if (EVP_PKEY_decapsulate_init(ctx, p) <= 0) { + t->err = "TEST_DECAPSULATE_INIT_ERROR"; + goto err; + } + + if (EVP_PKEY_CTX_set_kem_op(ctx, op) <= 0) { + t->err = "TEST_SET_KEM_OP_ERROR"; + goto err; + } + if (EVP_PKEY_decapsulate(ctx, NULL, &outlen, in, inlen) <= 0) { + t->err = "TEST_DECAPSULATE_LEN_ERROR"; + goto err; + } + if (!TEST_ptr(out = OPENSSL_malloc(outlen))) { + ret = 0; + goto err; + } + + if (EVP_PKEY_decapsulate(ctx, out, &outlen, in, inlen) <= 0) { + t->err = "TEST_DECAPSULATE_ERROR"; + goto err; + } + if (!TEST_mem_eq(out, outlen, expected, expectedlen)) { + t->err = "TEST_SECRET_MISMATCH"; + goto err; + } + t->err = NULL; + ret = 1; +err: + OPENSSL_free(out); + ctrl2params_free(params, params_n, params_n_allocated); + return ret; +} + +static int kem_test_run(EVP_TEST *t) +{ + int ret = 0; + KEM_DATA *kdata = t->data; + unsigned char *wrapped = NULL, *secret = NULL; + + if (kdata->input == NULL) { + size_t wrappedlen = 0, secretlen = 0; + + ret = encapsulate(t, kdata->ctx, kdata->op, &wrapped, &wrappedlen, + &secret, &secretlen); + if (ret == 0 || t->err != NULL) + goto err; + ret = decapsulate(t, kdata->ctx, kdata->op, wrapped, wrappedlen, + secret, secretlen); + } else { + ret = decapsulate(t, kdata->ctx, kdata->op, kdata->input, kdata->inputlen, + kdata->output, kdata->outputlen); + } +err: + OPENSSL_free(wrapped); + OPENSSL_free(secret); + return ret; +} + +static const EVP_TEST_METHOD pkey_kem_test_method = { + "Kem", + kem_test_init, + kem_test_cleanup, + kem_test_parse, + kem_test_run +}; /** ** PUBLIC KEY TESTS @@ -1929,6 +2257,7 @@ typedef struct pkey_data_st { /* Context for this operation */ EVP_PKEY_CTX *ctx; /* Key operation to perform */ + int (*keyopinit) (EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]); int (*keyop) (EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, const unsigned char *tbs, size_t tbslen); @@ -1938,6 +2267,10 @@ typedef struct pkey_data_st { /* Expected output */ unsigned char *output; size_t output_len; + STACK_OF(OPENSSL_STRING) *init_controls; /* collection of controls */ + STACK_OF(OPENSSL_STRING) *controls; /* collection of controls */ + EVP_PKEY *peer; + int validate; } PKEY_DATA; /* @@ -1946,7 +2279,8 @@ typedef struct pkey_data_st { */ static int pkey_test_init(EVP_TEST *t, const char *name, int use_public, - int (*keyopinit) (EVP_PKEY_CTX *ctx), + int (*keyopinit) (EVP_PKEY_CTX *ctx, + const OSSL_PARAM params[]), int (*keyop)(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, const unsigned char *tbs, @@ -1970,15 +2304,16 @@ static int pkey_test_init(EVP_TEST *t, const char *name, EVP_PKEY_free(pkey); return 0; } + kdata->keyopinit = keyopinit; kdata->keyop = keyop; if (!TEST_ptr(kdata->ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, propquery))) { EVP_PKEY_free(pkey); OPENSSL_free(kdata); return 0; } - if (keyopinit(kdata->ctx) <= 0) - t->err = "KEYOP_INIT_ERROR"; t->data = kdata; + kdata->init_controls = sk_OPENSSL_STRING_new_null(); + kdata->controls = sk_OPENSSL_STRING_new_null(); return 1; } @@ -1986,6 +2321,8 @@ static void pkey_test_cleanup(EVP_TEST *t) { PKEY_DATA *kdata = t->data; + ctrlfree(kdata->init_controls); + ctrlfree(kdata->controls); OPENSSL_free(kdata->input); OPENSSL_free(kdata->output); EVP_PKEY_CTX_free(kdata->ctx); @@ -2021,6 +2358,27 @@ static int pkey_test_ctrl(EVP_TEST *t, EVP_PKEY_CTX *pctx, return rv > 0; } +static int pkey_add_control(EVP_TEST *t, STACK_OF(OPENSSL_STRING) *controls, + const char *value) +{ + char *p; + + if (controls == NULL) + return 0; + + p = strchr(value, ':'); + if (p == NULL) + return 0; + p++; + if (is_digest_disabled(p) || is_cipher_disabled(p)) { + TEST_info("skipping, '%s' is disabled", p); + t->skip = 1; + return 1; + } + + return ctrladd(controls, value) > 0; +} + static int pkey_test_parse(EVP_TEST *t, const char *keyword, const char *value) { @@ -2029,11 +2387,45 @@ static int pkey_test_parse(EVP_TEST *t, return parse_bin(value, &kdata->input, &kdata->input_len); if (strcmp(keyword, "Output") == 0) return parse_bin(value, &kdata->output, &kdata->output_len); + if (strcmp(keyword, "CtrlInit") == 0) + return ctrladd(kdata->init_controls, value); if (strcmp(keyword, "Ctrl") == 0) - return pkey_test_ctrl(t, kdata->ctx, value); + return pkey_add_control(t, kdata->controls, value); return 0; } +static int pkey_test_run_init(EVP_TEST *t) +{ + PKEY_DATA *data = t->data; + int i, ret = 0; + OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; + OSSL_PARAM *p = NULL; + size_t params_n = 0, params_n_allocstart = 0; + + if (sk_OPENSSL_STRING_num(data->init_controls) > 0) { + if (!ctrl2params(t, data->init_controls, + NULL, + params, OSSL_NELEM(params), ¶ms_n)) + goto err; + p = params; + } + if (data->keyopinit(data->ctx, p) <= 0) { + t->err = "KEYOP_INIT_ERROR"; + goto err; + } + + for (i = 0; i < sk_OPENSSL_STRING_num(data->controls); i++) { + char *value = sk_OPENSSL_STRING_value(data->controls, i); + + if (!pkey_test_ctrl(t, data->ctx, value) || t->err != NULL) + goto err; + } + ret = 1; +err: + ctrl2params_free(params, params_n, params_n_allocstart); + return ret; +} + static int pkey_test_run(EVP_TEST *t) { PKEY_DATA *expected = t->data; @@ -2041,6 +2433,9 @@ static int pkey_test_run(EVP_TEST *t) size_t got_len; EVP_PKEY_CTX *copy = NULL; + if (!pkey_test_run_init(t)) + goto err; + if (expected->keyop(expected->ctx, NULL, &got_len, expected->input, expected->input_len) <= 0 || !TEST_ptr(got = OPENSSL_malloc(got_len))) { @@ -2090,7 +2485,7 @@ static int pkey_test_run(EVP_TEST *t) static int sign_test_init(EVP_TEST *t, const char *name) { - return pkey_test_init(t, name, 0, EVP_PKEY_sign_init, EVP_PKEY_sign); + return pkey_test_init(t, name, 0, EVP_PKEY_sign_init_ex, EVP_PKEY_sign); } static const EVP_TEST_METHOD psign_test_method = { @@ -2103,7 +2498,7 @@ static const EVP_TEST_METHOD psign_test_method = { static int verify_recover_test_init(EVP_TEST *t, const char *name) { - return pkey_test_init(t, name, 1, EVP_PKEY_verify_recover_init, + return pkey_test_init(t, name, 1, EVP_PKEY_verify_recover_init_ex, EVP_PKEY_verify_recover); } @@ -2117,7 +2512,7 @@ static const EVP_TEST_METHOD pverify_recover_test_method = { static int decrypt_test_init(EVP_TEST *t, const char *name) { - return pkey_test_init(t, name, 0, EVP_PKEY_decrypt_init, + return pkey_test_init(t, name, 0, EVP_PKEY_decrypt_init_ex, EVP_PKEY_decrypt); } @@ -2131,16 +2526,19 @@ static const EVP_TEST_METHOD pdecrypt_test_method = { static int verify_test_init(EVP_TEST *t, const char *name) { - return pkey_test_init(t, name, 1, EVP_PKEY_verify_init, 0); + return pkey_test_init(t, name, 1, EVP_PKEY_verify_init_ex, NULL); } static int verify_test_run(EVP_TEST *t) { PKEY_DATA *kdata = t->data; + if (!pkey_test_run_init(t)) + goto err; if (EVP_PKEY_verify(kdata->ctx, kdata->output, kdata->output_len, kdata->input, kdata->input_len) <= 0) t->err = "VERIFY_ERROR"; +err: return 1; } @@ -2154,7 +2552,7 @@ static const EVP_TEST_METHOD pverify_test_method = { static int pderive_test_init(EVP_TEST *t, const char *name) { - return pkey_test_init(t, name, 0, EVP_PKEY_derive_init, 0); + return pkey_test_init(t, name, 0, EVP_PKEY_derive_init_ex, 0); } static int pderive_test_parse(EVP_TEST *t, @@ -2167,65 +2565,20 @@ static int pderive_test_parse(EVP_TEST *t, validate = 1; if (validate || strcmp(keyword, "PeerKey") == 0) { - EVP_PKEY *peer; + EVP_PKEY *peer = NULL; + + kdata->validate = validate; if (find_key(&peer, value, public_keys) == 0) return -1; - if (EVP_PKEY_derive_set_peer_ex(kdata->ctx, peer, validate) <= 0) { - t->err = "DERIVE_SET_PEER_ERROR"; - return 1; - } - t->err = NULL; + kdata->peer = peer; return 1; } if (strcmp(keyword, "SharedSecret") == 0) return parse_bin(value, &kdata->output, &kdata->output_len); if (strcmp(keyword, "Ctrl") == 0) - return pkey_test_ctrl(t, kdata->ctx, value); - if (strcmp(keyword, "KDFType") == 0) { - OSSL_PARAM params[2]; - - params[0] = OSSL_PARAM_construct_utf8_string(OSSL_EXCHANGE_PARAM_KDF_TYPE, - (char *)value, 0); - params[1] = OSSL_PARAM_construct_end(); - if (EVP_PKEY_CTX_set_params(kdata->ctx, params) == 0) - return -1; - return 1; - } - if (strcmp(keyword, "KDFDigest") == 0) { - OSSL_PARAM params[2]; - - params[0] = OSSL_PARAM_construct_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST, - (char *)value, 0); - params[1] = OSSL_PARAM_construct_end(); - if (EVP_PKEY_CTX_set_params(kdata->ctx, params) == 0) - return -1; - return 1; - } - if (strcmp(keyword, "CEKAlg") == 0) { - OSSL_PARAM params[2]; - - params[0] = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_CEK_ALG, - (char *)value, 0); - params[1] = OSSL_PARAM_construct_end(); - if (EVP_PKEY_CTX_set_params(kdata->ctx, params) == 0) - return -1; - return 1; - } - if (strcmp(keyword, "KDFOutlen") == 0) { - OSSL_PARAM params[2]; - char *endptr; - size_t outlen = (size_t)strtoul(value, &endptr, 0); - - if (endptr[0] != '\0') - return -1; - - params[0] = OSSL_PARAM_construct_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN, - &outlen); - params[1] = OSSL_PARAM_construct_end(); - if (EVP_PKEY_CTX_set_params(kdata->ctx, params) == 0) - return -1; - return 1; - } + return pkey_add_control(t, kdata->controls, value); + if (strcmp(keyword, "CtrlInit") == 0) + return ctrladd(kdata->init_controls, value); return 0; } @@ -2236,6 +2589,16 @@ static int pderive_test_run(EVP_TEST *t) unsigned char *got = NULL; size_t got_len; + if (!pkey_test_run_init(t)) + goto err; + + t->err = NULL; + if (EVP_PKEY_derive_set_peer_ex(expected->ctx, expected->peer, + expected->validate) <= 0) { + t->err = "DERIVE_SET_PEER_ERROR"; + goto err; + } + if (!TEST_ptr(dctx = EVP_PKEY_CTX_dup(expected->ctx))) { t->err = "DERIVE_ERROR"; goto err; @@ -2274,7 +2637,6 @@ static const EVP_TEST_METHOD pderive_test_method = { pderive_test_run }; - /** ** PBE TESTS **/ @@ -2707,6 +3069,7 @@ typedef struct rand_data_st { unsigned int generate_bits; char *cipher; char *digest; + STACK_OF(OPENSSL_STRING) *init_controls; /* collection of controls */ /* Expected output */ RAND_DATA_PASS data[MAX_RAND_REPEATS]; @@ -2742,6 +3105,7 @@ static int rand_test_init(EVP_TEST *t, const char *name) EVP_RAND_free(rand); if (rdata->ctx == NULL) goto err; + rdata->init_controls = sk_OPENSSL_STRING_new_null(); rdata->n = -1; t->data = rdata; @@ -2757,6 +3121,7 @@ static void rand_test_cleanup(EVP_TEST *t) RAND_DATA *rdata = t->data; int i; + ctrlfree(rdata->init_controls); OPENSSL_free(rdata->cipher); OPENSSL_free(rdata->digest); @@ -2832,6 +3197,8 @@ static int rand_test_parse(EVP_TEST *t, rdata->prediction_resistance = atoi(value) != 0; return 1; } + if (strcmp(keyword, "CtrlInit") == 0) + return ctrladd(rdata->init_controls, value); } return 0; } @@ -2842,14 +3209,23 @@ static int rand_test_run(EVP_TEST *t) RAND_DATA_PASS *item; unsigned char *got; size_t got_len = expected->generate_bits / 8; - OSSL_PARAM params[5], *p = params; + OSSL_PARAM params[8], *p = params; int i = -1, ret = 0; unsigned int strength; unsigned char *z; + size_t params_n = 0, params_allocated_n = 0; if (!TEST_ptr(got = OPENSSL_malloc(got_len))) return 0; + if (sk_OPENSSL_STRING_num(expected->init_controls) > 0) { + if (!ctrl2params(t, expected->init_controls, + NULL, + params, OSSL_NELEM(params), ¶ms_n)) + goto err; + } + p = params + params_n; + *p++ = OSSL_PARAM_construct_int(OSSL_DRBG_PARAM_USE_DF, &expected->use_df); if (expected->cipher != NULL) *p++ = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_CIPHER, @@ -2859,8 +3235,15 @@ static int rand_test_run(EVP_TEST *t) expected->digest, 0); *p++ = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_MAC, "HMAC", 0); *p = OSSL_PARAM_construct_end(); - if (!TEST_true(EVP_RAND_CTX_set_params(expected->ctx, params))) + if (!EVP_RAND_CTX_set_params(expected->ctx, params)) { + if (t->expect_unapproved == 0) { + t->err = "EVP_RAND_CTX_set_params"; + ret = 1; + } goto err; + } + ctrl2params_free(params, params_n, params_allocated_n); + params_n = 0; strength = EVP_RAND_get_strength(expected->ctx); for (i = 0; i <= expected->n; i++) { @@ -2928,6 +3311,8 @@ static int rand_test_run(EVP_TEST *t) goto err; if (!TEST_mem_eq(got, got_len, item->output, item->output_len)) goto err; + if (!rand_check_fips_approved(expected->ctx, t)) + goto err; if (!TEST_true(EVP_RAND_uninstantiate(expected->ctx)) || !TEST_true(EVP_RAND_uninstantiate(expected->parent)) || !TEST_true(EVP_RAND_verify_zeroization(expected->ctx)) @@ -2942,6 +3327,7 @@ static int rand_test_run(EVP_TEST *t) if (ret == 0 && i >= 0) TEST_info("Error in test case %d of %d\n", i, expected->n + 1); OPENSSL_free(got); + ctrl2params_free(params, params_n, params_allocated_n); return ret; } @@ -2953,7 +3339,6 @@ static const EVP_TEST_METHOD rand_test_method = { rand_test_run }; - /** ** KDF TESTS **/ @@ -2965,6 +3350,7 @@ typedef struct kdf_data_st { size_t output_len; OSSL_PARAM params[20]; OSSL_PARAM *p; + STACK_OF(OPENSSL_STRING) *init_controls; /* collection of controls */ } KDF_DATA; /* @@ -2999,6 +3385,7 @@ static int kdf_test_init(EVP_TEST *t, const char *name) return 0; } t->data = kdata; + kdata->init_controls = sk_OPENSSL_STRING_new_null(); return 1; } @@ -3007,6 +3394,7 @@ static void kdf_test_cleanup(EVP_TEST *t) KDF_DATA *kdata = t->data; OSSL_PARAM *p; + ctrlfree(kdata->init_controls); for (p = kdata->params; p->key != NULL; p++) OPENSSL_free(p->data); OPENSSL_free(kdata->output); @@ -3118,6 +3506,8 @@ static int kdf_test_parse(EVP_TEST *t, if (strcmp(keyword, "Output") == 0) return parse_bin(value, &kdata->output, &kdata->output_len); + if (strcmp(keyword, "CtrlInit") == 0) + return ctrladd(kdata->init_controls, value); if (HAS_PREFIX(keyword, "Ctrl")) return kdf_test_ctrl(t, kdata->ctx, value); return 0; @@ -3125,14 +3515,28 @@ static int kdf_test_parse(EVP_TEST *t, static int kdf_test_run(EVP_TEST *t) { + int ret = 1; KDF_DATA *expected = t->data; unsigned char *got = NULL; size_t got_len = expected->output_len; EVP_KDF_CTX *ctx; + OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; + size_t params_n = 0, params_allocated_n = 0; + + if (sk_OPENSSL_STRING_num(expected->init_controls) > 0) { + if (!ctrl2params(t, expected->init_controls, + NULL, + params, OSSL_NELEM(params), ¶ms_n)) + goto err; + if (!EVP_KDF_CTX_set_params(expected->ctx, params)) { + t->err = "KDF_CTRL_ERROR"; + goto err; + } + } if (!EVP_KDF_CTX_set_params(expected->ctx, expected->params)) { t->err = "KDF_CTRL_ERROR"; - return 1; + goto err; } if (!TEST_ptr(got = OPENSSL_malloc(got_len == 0 ? 1 : got_len))) { t->err = "INTERNAL_ERROR"; @@ -3148,6 +3552,10 @@ static int kdf_test_run(EVP_TEST *t) t->err = "KDF_DERIVE_ERROR"; goto err; } + if (!kdf_check_fips_approved(expected->ctx, t)) { + ret = 0; + goto err; + } if (!memory_err_compare(t, "KDF_MISMATCH", expected->output, expected->output_len, got, got_len)) @@ -3156,8 +3564,9 @@ static int kdf_test_run(EVP_TEST *t) t->err = NULL; err: + ctrl2params_free(params, params_n, params_allocated_n); OPENSSL_free(got); - return 1; + return ret; } static const EVP_TEST_METHOD kdf_test_method = { @@ -3533,7 +3942,10 @@ typedef struct { size_t osin_len; /* Input length data if one shot */ unsigned char *output; /* Expected output */ size_t output_len; /* Expected output length */ - const char *nonce_type; + int deterministic_noncetype; + EVP_PKEY *key; + STACK_OF(OPENSSL_STRING) *init_controls; /* collection of controls */ + STACK_OF(OPENSSL_STRING) *controls; /* Collection of controls */ } DIGESTSIGN_DATA; static int digestsigver_test_init(EVP_TEST *t, const char *alg, int is_verify, @@ -3553,6 +3965,8 @@ static int digestsigver_test_init(EVP_TEST *t, const char *alg, int is_verify, } if (!TEST_ptr(mdat = OPENSSL_zalloc(sizeof(*mdat)))) return 0; + mdat->init_controls = sk_OPENSSL_STRING_new_null(); + mdat->controls = sk_OPENSSL_STRING_new_null(); mdat->md = md; if (!TEST_ptr(mdat->ctx = EVP_MD_CTX_new())) { OPENSSL_free(mdat); @@ -3573,6 +3987,8 @@ static void digestsigver_test_cleanup(EVP_TEST *t) { DIGESTSIGN_DATA *mdata = t->data; + ctrlfree(mdata->init_controls); + ctrlfree(mdata->controls); EVP_MD_CTX_free(mdata->ctx); sk_EVP_TEST_BUFFER_pop_free(mdata->input, evp_test_buffer_free); OPENSSL_free(mdata->osin); @@ -3589,7 +4005,6 @@ static int digestsigver_test_parse(EVP_TEST *t, if (strcmp(keyword, "Key") == 0) { EVP_PKEY *pkey = NULL; int rv = 0; - const char *name = mdata->md == NULL ? NULL : EVP_MD_get0_name(mdata->md); if (mdata->is_verify) rv = find_key(&pkey, value, public_keys); @@ -3599,15 +4014,7 @@ static int digestsigver_test_parse(EVP_TEST *t, t->skip = 1; return 1; } - if (mdata->is_verify) { - if (!EVP_DigestVerifyInit_ex(mdata->ctx, &mdata->pctx, name, libctx, - NULL, pkey, NULL)) - t->err = "DIGESTVERIFYINIT_ERROR"; - return 1; - } - if (!EVP_DigestSignInit_ex(mdata->ctx, &mdata->pctx, name, libctx, NULL, - pkey, NULL)) - t->err = "DIGESTSIGNINIT_ERROR"; + mdata->key = pkey; return 1; } @@ -3625,34 +4032,83 @@ static int digestsigver_test_parse(EVP_TEST *t, if (strcmp(keyword, "Ncopy") == 0) return evp_test_buffer_ncopy(value, mdata->input); } - if (strcmp(keyword, "Ctrl") == 0) { - if (mdata->pctx == NULL) - return -1; - return pkey_test_ctrl(t, mdata->pctx, value); - } + if (strcmp(keyword, "Ctrl") == 0) + return pkey_add_control(t, mdata->controls, value); + if (strcmp(keyword, "CtrlInit") == 0) + return ctrladd(mdata->init_controls, value); if (strcmp(keyword, "NonceType") == 0) { - if (strcmp(value, "deterministic") == 0) { - OSSL_PARAM params[2]; - unsigned int nonce_type = 1; - - params[0] = - OSSL_PARAM_construct_uint(OSSL_SIGNATURE_PARAM_NONCE_TYPE, - &nonce_type); - params[1] = OSSL_PARAM_construct_end(); - if (!EVP_PKEY_CTX_set_params(mdata->pctx, params)) - t->err = "EVP_PKEY_CTX_set_params_ERROR"; - else if (!EVP_PKEY_CTX_get_params(mdata->pctx, params)) - t->err = "EVP_PKEY_CTX_get_params_ERROR"; - else if (!OSSL_PARAM_modified(¶ms[0])) - t->err = "nonce_type_not_modified_ERROR"; - else if (nonce_type != 1) - t->err = "nonce_type_value_ERROR"; - } + if (strcmp(value, "deterministic") == 0) + mdata->deterministic_noncetype = 1; return 1; } return 0; } +static int check_deterministic_noncetype(EVP_TEST *t, + DIGESTSIGN_DATA *mdata) +{ + if (mdata->deterministic_noncetype == 1) { + OSSL_PARAM params[2]; + unsigned int nonce_type = 1; + + params[0] = + OSSL_PARAM_construct_uint(OSSL_SIGNATURE_PARAM_NONCE_TYPE, + &nonce_type); + params[1] = OSSL_PARAM_construct_end(); + if (!EVP_PKEY_CTX_set_params(mdata->pctx, params)) + t->err = "EVP_PKEY_CTX_set_params_ERROR"; + else if (!EVP_PKEY_CTX_get_params(mdata->pctx, params)) + t->err = "EVP_PKEY_CTX_get_params_ERROR"; + else if (!OSSL_PARAM_modified(¶ms[0])) + t->err = "nonce_type_not_modified_ERROR"; + else if (nonce_type != 1) + t->err = "nonce_type_value_ERROR"; + } + return t->err == NULL; +} + +static int signverify_init(EVP_TEST *t, DIGESTSIGN_DATA *data) +{ + const char *name = data->md == NULL ? NULL : EVP_MD_get0_name(data->md); + OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; + OSSL_PARAM *p = NULL; + int i, ret = 0; + size_t params_n = 0, params_allocated_n = 0; + + if (sk_OPENSSL_STRING_num(data->init_controls) > 0) { + if (!ctrl2params(t, data->init_controls, + NULL, + params, OSSL_NELEM(params), ¶ms_n)) + goto err; + p = params; + } + + if (data->is_verify) { + if (!EVP_DigestVerifyInit_ex(data->ctx, &data->pctx, name, libctx, + NULL, data->key, p)) { + t->err = "DIGESTVERIFYINIT_ERROR"; + goto err; + } + } else { + if (!EVP_DigestSignInit_ex(data->ctx, &data->pctx, name, libctx, NULL, + data->key, p)) { + t->err = "DIGESTSIGNINIT_ERROR"; + goto err; + } + } + + for (i = 0; i < sk_OPENSSL_STRING_num(data->controls); i++) { + char *value = sk_OPENSSL_STRING_value(data->controls, i); + + if (!pkey_test_ctrl(t, data->pctx, value) || t->err != NULL) + goto err; + } + ret = 1; +err: + ctrl2params_free(params, params_n, params_allocated_n); + return ret; +} + static int digestsign_update_fn(void *ctx, const unsigned char *buf, size_t buflen) { @@ -3661,10 +4117,22 @@ static int digestsign_update_fn(void *ctx, const unsigned char *buf, static int digestsign_test_run(EVP_TEST *t) { + int i; DIGESTSIGN_DATA *expected = t->data; unsigned char *got = NULL; size_t got_len; + if (!signverify_init(t, expected)) + goto err; + if (!check_deterministic_noncetype(t, expected)) + goto err; + + for (i = 0; i < sk_OPENSSL_STRING_num(expected->controls); i++) { + char *value = sk_OPENSSL_STRING_value(expected->controls, i); + if (!pkey_test_ctrl(t, expected->pctx, value) || t->err != NULL) + return 0; + } + if (!evp_test_buffer_do(expected->input, digestsign_update_fn, expected->ctx)) { t->err = "DIGESTUPDATE_ERROR"; @@ -3718,6 +4186,9 @@ static int digestverify_test_run(EVP_TEST *t) { DIGESTSIGN_DATA *mdata = t->data; + if (!signverify_init(t, mdata)) + return 1; + if (!evp_test_buffer_do(mdata->input, digestverify_update_fn, mdata->ctx)) { t->err = "DIGESTUPDATE_ERROR"; return 1; @@ -3748,6 +4219,9 @@ static int oneshot_digestsign_test_run(EVP_TEST *t) unsigned char *got = NULL; size_t got_len; + if (!signverify_init(t, expected)) + goto err; + if (!EVP_DigestSign(expected->ctx, NULL, &got_len, expected->osin, expected->osin_len)) { t->err = "DIGESTSIGN_LENGTH_ERROR"; @@ -3791,6 +4265,9 @@ static int oneshot_digestverify_test_run(EVP_TEST *t) { DIGESTSIGN_DATA *mdata = t->data; + if (!signverify_init(t, mdata)) + return 1; + if (EVP_DigestVerify(mdata->ctx, mdata->output, mdata->output_len, mdata->osin, mdata->osin_len) <= 0) t->err = "VERIFY_ERROR"; @@ -3830,6 +4307,7 @@ static const EVP_TEST_METHOD *evp_test_list[] = { &psign_test_method, &pverify_recover_test_method, &pverify_test_method, + &pkey_kem_test_method, NULL }; @@ -3863,6 +4341,7 @@ static void clear_test(EVP_TEST *t) t->err = NULL; t->skip = 0; t->meth = NULL; + t->expect_unapproved = 0; #if !defined(OPENSSL_NO_DEFAULT_THREAD_POOL) OSSL_set_max_threads(libctx, 0); @@ -4085,6 +4564,7 @@ static int parse(EVP_TEST *t) PAIR *pp; int i, j, skipped = 0; + fips_indicator_callback_unapproved_count = 0; top: do { if (BIO_eof(t->s.fp)) @@ -4185,6 +4665,11 @@ static int parse(EVP_TEST *t) t->skip = 1; return 0; } + } else { + TEST_info("skipping, FIPS provider not active: %s:%d", + t->s.test_file, t->s.start); + t->skip = 1; + return 0; } skipped++; pp++; @@ -4258,6 +4743,8 @@ static int parse(EVP_TEST *t) pp->value, t->s.test_file, t->s.start); t->skip = 1; } + } else if (strcmp(pp->key, "Unapproved") == 0) { + t->expect_unapproved = 1; } else { /* Must be test specific line: try to parse it */ int rv = t->meth->parse(t, pp->key, pp->value); @@ -4292,6 +4779,7 @@ static int run_file_tests(int i) return 0; } + OSSL_INDICATOR_set_callback(libctx, fips_indicator_cb); while (!BIO_eof(t->s.fp)) { c = parse(t); if (t->skip) { diff --git a/test/recipes/30-test_evp_data/evpkdf_tls12_prf.txt b/test/recipes/30-test_evp_data/evpkdf_tls12_prf.txt index 44040ff66b481..09720e7dcaf67 100644 --- a/test/recipes/30-test_evp_data/evpkdf_tls12_prf.txt +++ b/test/recipes/30-test_evp_data/evpkdf_tls12_prf.txt @@ -47,3 +47,25 @@ Ctrl.Secret = hexsecret:01 Ctrl.Seed = hexseed:02 Output = 03 Result = KDF_DERIVE_ERROR + +# Test that "master secret" is not not used in FIPS mode +FIPSversion = >=3.4.0 +KDF = TLS1-PRF +Ctrl.digest = digest:SHA256 +Ctrl.Secret = hexsecret:f8938ecc9edebc5030c0c6a441e213cd24e6f770a50dda07876f8d55da062bcadb386b411fd4fe4313a604fce6c17fbc +Ctrl.label = seed:master secret +Ctrl.client_random = hexseed:36c129d01a3200894b9179faac589d9835d58775f9b5ea3587cb8fd0364cae8c +Ctrl.server_random = hexseed:f6c9575ed7ddd73e1f7d16eca115415812a43c2b747daaaae043abfb50053fce +Result = KDF_DERIVE_ERROR + +# FIPS indicator callback test +FIPSversion = >=3.4.0 +KDF = TLS1-PRF +Unapproved = 1 +CtrlInit = ems_check:0 +Ctrl.digest = digest:SHA256 +Ctrl.Secret = hexsecret:f8938ecc9edebc5030c0c6a441e213cd24e6f770a50dda07876f8d55da062bcadb386b411fd4fe4313a604fce6c17fbc +Ctrl.label = seed:master secret +Ctrl.client_random = hexseed:36c129d01a3200894b9179faac589d9835d58775f9b5ea3587cb8fd0364cae8c +Ctrl.server_random = hexseed:f6c9575ed7ddd73e1f7d16eca115415812a43c2b747daaaae043abfb50053fce +Output = 202c88c00f84a17a20027079604787461176455539e705be730890602c289a5001e34eeb3a043e5d52a65e66125188bf diff --git a/test/recipes/30-test_evp_data/evppkey_dsa.txt b/test/recipes/30-test_evp_data/evppkey_dsa.txt index debd62bca84cb..5cc5f015e6806 100644 --- a/test/recipes/30-test_evp_data/evppkey_dsa.txt +++ b/test/recipes/30-test_evp_data/evppkey_dsa.txt @@ -334,7 +334,7 @@ Result = DIGESTSIGNINIT_ERROR Availablein = fips DigestSign = SHA1 Securitycheck = 1 -Key = DSA-2048 +Key = DSA-2048-256 Input = "Hello" Result = DIGESTSIGNINIT_ERROR @@ -353,3 +353,46 @@ Securitycheck = 1 Key = DSA-4096-256 Input = "Hello" Result = DIGESTSIGNINIT_ERROR + +Title = Fips Indicator Tests +# Check that the indicator callback is triggered + +# Test sign with a 1024 bit key in fips mode +FIPSversion = >=3.4.0 +DigestSign = SHA256 +Securitycheck = 1 +Unapproved = 1 +CtrlInit = key-check:0 +Key = DSA-1024-FIPS186-2 +Input = "Hello" +Result = SIGNATURE_MISMATCH + +# Test sign with a 3072 bit key with N == 224 is not allowed in fips mode +FIPSversion = >=3.4.0 +DigestSign = SHA256 +Securitycheck = 1 +Unapproved = 1 +CtrlInit = key-check:0 +Key = DSA-3072-224 +Input = "Hello" +Result = SIGNATURE_MISMATCH + +# Test sign with a 4096 bit key is not allowed in fips mode +FIPSversion = >=3.4.0 +DigestSign = SHA256 +Securitycheck = 1 +Unapproved = 1 +CtrlInit = key-check:0 +Key = DSA-4096-256 +Input = "Hello" +Result = SIGNATURE_MISMATCH + +# Test sign with SHA1 is not allowed in fips mode +FIPSversion = >=3.4.0 +DigestSign = SHA1 +Securitycheck = 1 +Unapproved = 1 +CtrlInit = digest-check:0 +Key = DSA-2048-256 +Input = "Hello" +Result = SIGNATURE_MISMATCH diff --git a/test/recipes/30-test_evp_data/evppkey_ecc.txt b/test/recipes/30-test_evp_data/evppkey_ecc.txt index 6ea11db668315..8264496a40706 100644 --- a/test/recipes/30-test_evp_data/evppkey_ecc.txt +++ b/test/recipes/30-test_evp_data/evppkey_ecc.txt @@ -3594,7 +3594,16 @@ Derive=BOB_cf_prime192v1 Securitycheck = 1 PeerKey=ALICE_cf_prime192v1_PUB SharedSecret=e36cad3b0f8d00f60f090440a76df47896713ae61421c354 -Result = DERIVE_SET_PEER_ERROR +Result = KEYOP_INIT_ERROR + +# Check the indicator callback is triggered +FIPSversion = >=3.4.0 +Derive=BOB_cf_prime192v1 +Securitycheck = 1 +Unapproved = 1 +CtrlInit = key-check:0 +PeerKey=ALICE_cf_prime192v1_PUB +SharedSecret=e36cad3b0f8d00f60f090440a76df47896713ae61421c354 Title=prime256v1 curve tests diff --git a/test/recipes/30-test_evp_data/evppkey_ecdh.txt b/test/recipes/30-test_evp_data/evppkey_ecdh.txt index d50b2d166eb7a..eae84e4b107f2 100644 --- a/test/recipes/30-test_evp_data/evppkey_ecdh.txt +++ b/test/recipes/30-test_evp_data/evppkey_ecdh.txt @@ -2710,7 +2710,7 @@ Availablein = fips Derive=ALICE_prime192v1 Securitycheck = 1 PeerKey=BOB_prime192v1_PUB -Result = DERIVE_SET_PEER_ERROR +Result = KEYOP_INIT_ERROR # ECDH Bob with Alice peer diff --git a/test/recipes/30-test_evp_data/evppkey_ecdsa.txt b/test/recipes/30-test_evp_data/evppkey_ecdsa.txt index 1543ed9f7534b..cca8c0694547e 100644 --- a/test/recipes/30-test_evp_data/evppkey_ecdsa.txt +++ b/test/recipes/30-test_evp_data/evppkey_ecdsa.txt @@ -37,34 +37,34 @@ PrivPubKeyPair = P-256:P-256-PUBLIC Title = ECDSA tests -Verify = P-256 +Verify = P-256-PUBLIC Ctrl = digest:SHA1 Input = "0123456789ABCDEF1234" Output = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec8 # Digest too long -Verify = P-256 +Verify = P-256-PUBLIC Ctrl = digest:SHA1 Input = "0123456789ABCDEF12345" Output = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec8 Result = VERIFY_ERROR # Digest too short -Verify = P-256 +Verify = P-256-PUBLIC Ctrl = digest:SHA1 Input = "0123456789ABCDEF123" Output = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec8 Result = VERIFY_ERROR # Digest invalid -Verify = P-256 +Verify = P-256-PUBLIC Ctrl = digest:SHA1 Input = "0123456789ABCDEF1235" Output = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec8 Result = VERIFY_ERROR # Invalid signature -Verify = P-256 +Verify = P-256-PUBLIC Ctrl = digest:SHA1 Input = "0123456789ABCDEF1234" Output = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec7 @@ -72,14 +72,14 @@ Result = VERIFY_ERROR # Garbage after signature Availablein = default -Verify = P-256 +Verify = P-256-PUBLIC Ctrl = digest:SHA1 Input = "0123456789ABCDEF1234" Output = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec800 Result = VERIFY_ERROR # BER signature -Verify = P-256 +Verify = P-256-PUBLIC Ctrl = digest:SHA1 Input = "0123456789ABCDEF1234" Output = 3080022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec80000 @@ -185,7 +185,6 @@ Title = FIPS Negative tests (using different curves and digests) # Test that a explicit curve is not allowed in fips mode Availablein = fips DigestVerify = SHA256 -Securitycheck = 1 Key = EC_EXPLICIT Input = "Hello World" Result = DIGESTVERIFYINIT_ERROR @@ -228,3 +227,36 @@ DigestVerify = MD5 Securitycheck = 1 Key = P-256-PUBLIC Result = DIGESTVERIFYINIT_ERROR + +Title = FIPS Indicator tests +# Check that the indicator callback is triggered +# We check for signature mismatch since the signature is unique + +FIPSversion = >=3.4.0 +DigestSign = SHA3-512 +Securitycheck = 1 +Unapproved = 1 +CtrlInit = key-check:0 +Key = B-163 +Input = "Hello World" +Result = SIGNATURE_MISMATCH + +# Test that SHA1 is not allowed in fips mode for signing +FIPSversion = >=3.4.0 +DigestSign = SHA1 +Securitycheck = 1 +Unapproved = 1 +CtrlInit = digest-check:0 +Key = P-256 +Input = "Hello World" +Result = SIGNATURE_MISMATCH + +# Test that SHA1 is not allowed in fips mode for signing +FIPSversion = >=3.4.0 +Sign = P-256 +Securitycheck = 1 +Unapproved = 1 +CtrlInit = digest-check:0 +Ctrl = digest:SHA1 +Input = "0123456789ABCDEF1234" +Result = KEYOP_MISMATCH diff --git a/test/recipes/30-test_evp_data/evppkey_ffdhe.txt b/test/recipes/30-test_evp_data/evppkey_ffdhe.txt index b6b1a8e8a090c..2e17571e9e5a5 100644 --- a/test/recipes/30-test_evp_data/evppkey_ffdhe.txt +++ b/test/recipes/30-test_evp_data/evppkey_ffdhe.txt @@ -98,10 +98,10 @@ SharedSecret=00006620DD85B56EE8540C8040CAC46B7385344A164E4DBDF521F7D99F88FA68EDD # The plain shared secret for these keys needs padding as seen above. Derive=ffdhe2048-1 PeerKey=ffdhe2048-2-pub -KDFType=X942KDF-ASN1 -KDFOutlen=32 -KDFDigest=SHA-256 -CEKAlg=id-aes128-wrap +Ctrl = kdf-type:X942KDF-ASN1 +Ctrl = kdf-outlen:32 +Ctrl = kdf-digest:SHA-256 +Ctrl = cekalg:AES-128-WRAP Ctrl = dh_pad:1 SharedSecret=89A249DF4EE9033B89C2B4E52072A736D94F51143A1ED5C8F1E91FCBEBE09654 @@ -109,10 +109,10 @@ SharedSecret=89A249DF4EE9033B89C2B4E52072A736D94F51143A1ED5C8F1E91FCBEBE09654 FIPSversion = >3.0.0 Derive=ffdhe2048-2 PeerKey=ffdhe2048-1-pub -KDFType=X942KDF-ASN1 -KDFOutlen=32 -KDFDigest=SHA-256 -CEKAlg=id-aes128-wrap +Ctrl = kdf-type:X942KDF-ASN1 +Ctrl = kdf-outlen:32 +Ctrl = kdf-digest:SHA-256 +Ctrl = cekalg:AES-128-WRAP Ctrl = dh_pad:0 SharedSecret=89A249DF4EE9033B89C2B4E52072A736D94F51143A1ED5C8F1E91FCBEBE09654 diff --git a/test/recipes/30-test_evp_data/evppkey_kas.txt b/test/recipes/30-test_evp_data/evppkey_kas.txt index ba1049628f94a..8933273a59e64 100644 --- a/test/recipes/30-test_evp_data/evppkey_kas.txt +++ b/test/recipes/30-test_evp_data/evppkey_kas.txt @@ -54,7 +54,7 @@ Availablein = fips Derive=KAS-ECC-CDH_P-192_C0 Securitycheck = 1 PeerKey=KAS-ECC-CDH_P-192_C0-Peer-PUBLIC -Result = DERIVE_SET_PEER_ERROR +Result = KEYOP_INIT_ERROR PrivateKey=KAS-ECC-CDH_P-192_C1 -----BEGIN PRIVATE KEY----- diff --git a/test/recipes/30-test_evp_data/evppkey_rsa.txt b/test/recipes/30-test_evp_data/evppkey_rsa.txt index 78d14d31be10f..b36a19f4fd086 100644 --- a/test/recipes/30-test_evp_data/evppkey_rsa.txt +++ b/test/recipes/30-test_evp_data/evppkey_rsa.txt @@ -599,7 +599,6 @@ Ctrl = rsa_mgf1_md:sha1 Input=65033bc2f67d6aba7d526acb873b8d9241e5e4d9 Output=1ed1d848fb1edb44129bd9b354795af97a069a7a00d0151048593e0c72c3517ff9ff2a41d0cb5a0ac860d736a199704f7cb6a53986a88bbd8abcc0076a2ce847880031525d449da2ac78356374c536e343faa7cba42a5aaa6506087791c06a8e989335aed19bfab2d5e67e27fb0c2875af896c21b6e8e7309d04e4f6727e69463e - Title = RSA DigestSign and DigestVerify DigestSign = SHA1 @@ -613,7 +612,6 @@ Key = RSA-2048 Input = "Hello World" Output = 3da3ca2bdd1b23a231b0e3c49d95d5959f9398c27a1e534c7e6baf1d2682304d3b6b229385b1edf483f5ef6f9b35bf10c519a302bb2f79c564e1a59ba71aa2fa36df96c942c43e8d9bd4702b5f61c12a078ae2b34d0de221fc8f9f936b79a67c89d11ba5da8c63a1370d0e824c6b661123e9b58b143ff533cf362cbdad70e65b419a6d45723bf22db3c76bb8f5337c5c5c93cb6f38b30d0c835b54c23405ca4217dd0b755f3712ebad285d9e0c02655f6ce5ce6fed78f3c81843de325f628055eef57f280dee0c3170050137ee599b9ab7f2b5d3c5f831777ea05a5eb097c70bad1a7214dadae12d7960bb9425390c7d25a79985e1e3c28ad422ff93c808f4b5 - Title = Test RSA keygen # Key generation tests @@ -623,3 +621,38 @@ Ctrl = rsa_keygen_bits:128 KeyName = tmprsa Result = PKEY_CTRL_ERROR Reason = key size too small + +Title = Test RSASVE (KEM) + +# RSA Encapsulate/Decapsulate +Kem = RSA-2048 +Op = RSASVE + +# RSA Decapsulate +Kem = RSA-2048 +Op = RSASVE +Input = 431937b777ae3ddda69da20ea602aeb76f87a7e120f24ff2bf7757de4302413fd875eb740d5ea108d0bce1102d9f0ec1613aa433ab33164afeb06b531334e4a0ea0965a4ef1c06ad783ce5799a35a62c1f8926b878be7400bd39a35a144ddccb1161f9b22891afb84bff8c31028fee69eaeca4c73d9d1dc0db371d52f33c950d7a3d51c2032567d07e1c2af36b4a4e13af04ba165ca3242cafcc2e1778ff205ede37397c1b71aa88ff16927b2ed6e7b04fd980b9a9392ce7ce902c11ac22e0d72633eb6d0b85c766e22a5f80bca7161d7bf544af4790b3d2af0d7631faf6204c3908be1072d52a5be47687cad09a978b856f4d72e659650adccd05b343630d7b +Output = 01fd95c07b4f4888f4efaf6d69d9309f677b4c0cd2179f10572e4576163c25046917340e8c5098f64d580f56614856a4c46e7e14843a62f5c387b0b30f09d456302534bfa2c944af66bb8a172ea3064d59ed9855797436ea70e218ef59181c6497222819cb1903cdf6febc6d484f1cb8a44946ee7be9e734e6423c83d4aaf509d84980292fe996000d34c9727146157a422110047b7441e0ecd81824b96e09a5fe3a1f0a46099625aeb0a3712e991293a7401bc01dca8bb5e72aaee9a9367ff3294ca158b64404a651c2fd3bab21178e54f27dd0ca25f64f3a6f44a284f8687459a7e453e6c3cc8c2f58da214047d7c416167923b6d6c61d5988e96dff15fad9 + +# Test small RSA keys are not allowed for Encapsulation in FIPS mode +FIPSversion = >=3.4.0 +Kem = RSA-512 +Securitycheck = 1 +Op = RSASVE +Result = TEST_ENCAPSULATE_INIT_ERROR + +# Test small RSA keys are not allowed for Decapsulation in FIPS mode +FIPSversion = >=3.4.0 +Kem = RSA-512 +Securitycheck = 1 +Op = RSASVE +Input = 431937b777ae3ddda69da20ea602aeb76f87a7e120f24ff2bf7757de4302413fd875eb740d5ea108d0bce1102d9f0ec1613aa433ab33164afeb06b531334e4a0ea0965a4ef1c06ad783ce5799a35a62c1f8926b878be7400bd39a35a144ddccb1161f9b22891afb84bff8c31028fee69eaeca4c73d9d1dc0db371d52f33c950d +Result = TEST_DECAPSULATE_INIT_ERROR + +# Test FIPS indicator callback is triggered +FIPSversion = >=3.4.0 +Kem = RSA-512 +Securitycheck = 1 +Unapproved = 1 +CtrlInit = key-check:0 +Op = RSASVE diff --git a/test/recipes/30-test_evp_data/evppkey_rsa_common.txt b/test/recipes/30-test_evp_data/evppkey_rsa_common.txt index 9cc007ad7b195..da0d7cd77b31c 100644 --- a/test/recipes/30-test_evp_data/evppkey_rsa_common.txt +++ b/test/recipes/30-test_evp_data/evppkey_rsa_common.txt @@ -1915,6 +1915,13 @@ Title = RSA FIPS tests # FIPS tests +# Decrypt with small RSA key is not permitted in FIPS mode +Availablein = fips +Decrypt = RSA-512 +Securitycheck = 1 +Input = 550AF55A2904E7B9762352F8FB7FA235A9CB053AACB2D5FCB8CA48453CB2EE3619746C701ABF2D4CC67003471A187900B05AA812BD25ED05C675DFC8C97A24A7BF49BD6214992CAD766D05A9A2B57B74F26A737E0237B8B76C45F1F226A836D7CFBC75BA999BDBE48DBC09227AA46C88F21DCCBA7840141AD5A5D71FD122E6BD6AC3E564780DFE623FC1CA9B995A6037BF0BBD43B205A84AC5444F34202C05CE9113087176432476576DE6FFFF9A52EA57C08BE3EC2F49676CB8E12F762AC71FA3C321E00AC988910C85FF52F93825666CE0D40FFAA0592078919D4493F46D95CCF76364C6D57760DD0B64805F9AFC76A2365A5575CA301D5103F0EA76CB9A78 +Result = KEYOP_INIT_ERROR + # Verifying with SHA1 is permitted in fips mode for older applications DigestVerify = SHA1 Key = RSA-2048 @@ -1928,7 +1935,7 @@ Input = "Hello" Output = 80382819f51b197c42f9fc02a85198683d918059afc013ae155992442563dd2897008297fecb3a8d8cf9421d493a99bd427a628f17cc4a7c76d23dfad0619f4068403fa7351f6d5a92a631d670c04407f305a4b5cb492295754e73e9b7ad41459826d3619a61e90d4744bdaf0f24f2393ea9241e973600c2ed62b1a0a37c504e # Signing with SHA1 is not allowed in fips mode -Availablein = fips +FIPSversion = >=3.4.0 DigestSign = SHA1 Securitycheck = 1 Key = RSA-2048 @@ -1936,7 +1943,7 @@ Input = "Hello" Result = DIGESTSIGNINIT_ERROR # Signing with a 1024 bit key is not allowed in fips mode -Availablein = fips +FIPSversion = >=3.4.0 DigestSign = SHA256 Securitycheck = 1 Key = RSA-1024 @@ -1944,7 +1951,7 @@ Input = "Hello" Result = DIGESTSIGNINIT_ERROR # Verifying with a legacy digest in fips mode is not allowed -Availablein = fips +FIPSversion = >=3.4.0 DigestVerify = MD5 Securitycheck = 1 Key = RSA-2048 @@ -1952,9 +1959,52 @@ Input = "Hello" Result = DIGESTVERIFYINIT_ERROR # Verifying with a key smaller than 1024 bits in fips mode is not allowed -Availablein = fips +FIPSversion = >=3.4.0 DigestVerify = SHA256 Securitycheck = 1 Key = RSA-512 Input = "Hello" Result = DIGESTVERIFYINIT_ERROR + +################################################## +# Check that the indicator callback is triggered + +Title = RSA FIPS Indicator tests + +# Decrypt with small RSA key is not permitted in FIPS mode +FIPSversion = >=3.4.0 +Decrypt = RSA-512 +Securitycheck = 1 +Unapproved = 1 +CtrlInit = key-check:0 +Input = 550AF55A2904E7B9762352F8FB7FA235 +Result = KEYOP_MISMATCH + +# Signing with SHA1 is not allowed in fips mode +FIPSversion = >=3.4.0 +DigestSign = SHA1 +Securitycheck = 1 +Unapproved = 1 +CtrlInit = digest-check:0 +Key = RSA-2048 +Input = "Hello" +Result = SIGNATURE_MISMATCH + +FIPSversion = >=3.4.0 +DigestSign = SHA256 +Securitycheck = 1 +Unapproved = 1 +CtrlInit = key-check:0 +Key = RSA-1024 +Input = "Hello" +Result = SIGNATURE_MISMATCH + +# Verifying with a key smaller than 1024 bits in fips mode is not allowed +FIPSversion = >=3.4.0 +DigestVerify = SHA256 +Securitycheck = 1 +Unapproved = 1 +CtrlInit = key-check:0 +Key = RSA-512 +Input = "Hello" +Result = VERIFY_ERROR diff --git a/test/recipes/30-test_evp_data/evprand.txt b/test/recipes/30-test_evp_data/evprand.txt index 0e2ee82c587a0..b4516f5e61127 100644 --- a/test/recipes/30-test_evp_data/evprand.txt +++ b/test/recipes/30-test_evp_data/evprand.txt @@ -79776,3 +79776,41 @@ EntropyPredictionResistanceA.14 = d7842e7ad0cbac6b9404e8e942fabb77974b353a7f9633 AdditionalInputB.14 = 0155dc73a36c160d9e13c023e732798b4fba3a9fd849c0edf899765c5ff7349f EntropyPredictionResistanceB.14 = 96a30d8593cce5febd4f034ff97479eb8808e81bd7b8f7b44ae945fbbf503572 Output.14 = ee191dc6bef025e36302bb8ce0e6a949f7b0d2944b246fc52d68a20c3b2b787595ca9d4bae2f55a13924fabbef8f700abc09d7dac1c1eb3a63c040867519e6724faeb532d01cd38922e4e0973566fc23f5fbc067f496cb97fe3ce97564f0010d6cd2b5d81a3e79fcb85f010191a76b4d796ea8c85b119dd24210f64725c09689 + +Title = Test truncated Digests are not allowed in FIPS + +Availablein = fips +RAND = HASH-DRBG +Digest = SHA2-224 +GenerateBits = 16 +Result = EVP_RAND_CTX_set_params + +Availablein = fips +RAND = HMAC-DRBG +Digest = SHA2-384 +GenerateBits = 16 +Result = EVP_RAND_CTX_set_params + +Title = Test FIPS indicator callbacks for truncated digests + +FIPSversion = >=3.4.0 +RAND = HASH-DRBG +Unapproved = 1 +CtrlInit = digest-check:0 +Digest = SHA2-224 +PredictionResistance = 0 +GenerateBits = 16 +Entropy.0 = c3ef82ce241f02e4298b118ca4f1622515e32abbae6b7433 +Nonce.0 = 15e32abbae6b7433 +Output.0 = 5af6 + +FIPSversion = >=3.4.0 +RAND = HMAC-DRBG +Unapproved = 1 +CtrlInit = digest-check:0 +Digest = SHA2-384 +PredictionResistance = 0 +GenerateBits = 16 +Entropy.0 = 32c1ca125223de8de569697f92a37c6732c1ca125223de8de569697f92a37c67 +Nonce.0 = 15e32abbae6b7433 +Output.0 = ee9f diff --git a/util/libcrypto.num b/util/libcrypto.num index a553a9ae74864..e434b95d46039 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -5700,3 +5700,5 @@ i2d_OSSL_USER_NOTICE_SYNTAX ? 3_4_0 EXIST::FUNCTION: OSSL_USER_NOTICE_SYNTAX_free ? 3_4_0 EXIST::FUNCTION: OSSL_USER_NOTICE_SYNTAX_new ? 3_4_0 EXIST::FUNCTION: OSSL_USER_NOTICE_SYNTAX_it ? 3_4_0 EXIST::FUNCTION: +OSSL_INDICATOR_set_callback ? 3_4_0 EXIST::FUNCTION: +OSSL_INDICATOR_get_callback ? 3_4_0 EXIST::FUNCTION: