Skip to content

Commit

Permalink
Add tests for FIPS keygen self test failures.
Browse files Browse the repository at this point in the history
During key generation RSA, EC and DSA have extra tests that run in FIPS mode
All 3 algorithms have a pairwise test, EC & DSA also run a KAT test.

This test uses the self test callback to force an error
during each of the extra pairwise and KAT tests.

Reviewed-by: Paul Dale <pauli@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from #20183)
  • Loading branch information
slontis authored and t8m committed Feb 8, 2023
1 parent 89601c7 commit dcd20cc
Show file tree
Hide file tree
Showing 4 changed files with 257 additions and 1 deletion.
6 changes: 5 additions & 1 deletion test/build.info
Expand Up @@ -64,7 +64,7 @@ IF[{- !$disabled{tests} -}]
bio_readbuffer_test user_property_test pkcs7_test upcallstest \
provfetchtest prov_config_test rand_test ca_internals_test \
bio_tfo_test membio_test bio_dgram_test list_test fips_version_test \
x509_test hpke_test
x509_test hpke_test pairwise_fail_test

IF[{- !$disabled{'deprecated-3.0'} -}]
PROGRAMS{noinst}=enginetest
Expand Down Expand Up @@ -228,6 +228,10 @@ IF[{- !$disabled{tests} -}]
INCLUDE[provider_status_test]=../include ../apps/include
DEPEND[provider_status_test]=../libcrypto.a libtestutil.a

SOURCE[pairwise_fail_test]=pairwise_fail_test.c
INCLUDE[pairwise_fail_test]=../include ../apps/include
DEPEND[pairwise_fail_test]=../libcrypto.a libtestutil.a

SOURCE[evp_pkey_dhkem_test]=evp_pkey_dhkem_test.c
INCLUDE[evp_pkey_dhkem_test]=../include ../apps/include
DEPEND[evp_pkey_dhkem_test]=../libcrypto.a libtestutil.a
Expand Down
173 changes: 173 additions & 0 deletions test/pairwise_fail_test.c
@@ -0,0 +1,173 @@
/*
* Copyright 2023 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
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/

#include <openssl/pem.h>
#include <openssl/core_names.h>
#include <openssl/self_test.h>
#include "testutil.h"

typedef enum OPTION_choice {
OPT_ERR = -1,
OPT_EOF = 0,
OPT_PROVIDER_NAME,
OPT_CONFIG_FILE,
OPT_PAIRWISETEST,
OPT_DSAPARAM,
OPT_TEST_ENUM
} OPTION_CHOICE;

struct self_test_arg {
const char *type;
};

static OSSL_LIB_CTX *libctx = NULL;
static char *pairwise_name = NULL;
static char *dsaparam_file = NULL;
static struct self_test_arg self_test_args = { 0 };

const OPTIONS *test_get_options(void)
{
static const OPTIONS test_options[] = {
OPT_TEST_OPTIONS_DEFAULT_USAGE,
{ "config", OPT_CONFIG_FILE, '<',
"The configuration file to use for the libctx" },
{ "pairwise", OPT_PAIRWISETEST, 's',
"Test keygen pairwise test failures" },
{ "dsaparam", OPT_DSAPARAM, 's', "DSA param file" },
{ NULL }
};
return test_options;
}

static int self_test_on_pairwise_fail(const OSSL_PARAM params[], void *arg)
{
struct self_test_arg *args = arg;
const OSSL_PARAM *p = NULL;
const char *type = NULL, *phase = NULL;

p = OSSL_PARAM_locate_const(params, OSSL_PROV_PARAM_SELF_TEST_PHASE);
if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING)
return 0;
phase = (const char *)p->data;
if (strcmp(phase, OSSL_SELF_TEST_PHASE_CORRUPT) == 0) {
p = OSSL_PARAM_locate_const(params, OSSL_PROV_PARAM_SELF_TEST_TYPE);
if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING)
return 0;
type = (const char *)p->data;
if (strcmp(type, args->type) == 0)
return 0;
}
return 1;
}

static int setup_selftest_pairwise_failure(const char *type)
{
int ret = 0;
OSSL_PROVIDER *prov = NULL;

if (!TEST_ptr(prov = OSSL_PROVIDER_load(libctx, "fips")))
goto err;

/* Setup a callback that corrupts the pairwise self tests and causes failures */
self_test_args.type = type;
OSSL_SELF_TEST_set_callback(libctx, self_test_on_pairwise_fail, &self_test_args);

ret = 1;
err:
OSSL_PROVIDER_unload(prov);
return ret;
}

static int test_keygen_pairwise_failure(void)
{
BIO *bio = NULL;
EVP_PKEY_CTX *ctx = NULL;
EVP_PKEY *pParams = NULL;
EVP_PKEY *pkey = NULL;
const char *type = OSSL_SELF_TEST_TYPE_PCT;
int ret = 0;

if (strcmp(pairwise_name, "rsa") == 0) {
if (!TEST_true(setup_selftest_pairwise_failure(type)))
goto err;
if (!TEST_ptr_null(pkey = EVP_PKEY_Q_keygen(libctx, NULL, "RSA", 2048)))
goto err;
} else if (strncmp(pairwise_name, "ec", 2) == 0) {
if (strcmp(pairwise_name, "eckat") == 0)
type = OSSL_SELF_TEST_TYPE_PCT_KAT;
if (!TEST_true(setup_selftest_pairwise_failure(type)))
goto err;
if (!TEST_ptr_null(pkey = EVP_PKEY_Q_keygen(libctx, NULL, "EC", "P-256")))
goto err;
} else if (strncmp(pairwise_name, "dsa", 3) == 0) {
if (strcmp(pairwise_name, "dsakat") == 0)
type = OSSL_SELF_TEST_TYPE_PCT_KAT;
if (!TEST_true(setup_selftest_pairwise_failure(type)))
goto err;
if (!TEST_ptr(bio = BIO_new_file(dsaparam_file, "r")))
goto err;
if (!TEST_ptr(pParams = PEM_read_bio_Parameters_ex(bio, NULL, libctx, NULL)))
goto err;
if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pParams, NULL)))
goto err;
if (!TEST_int_eq(EVP_PKEY_keygen_init(ctx), 1))
goto err;
if (!TEST_int_le(EVP_PKEY_keygen(ctx, &pkey), 0))
goto err;
if (!TEST_ptr_null(pkey))
goto err;
}
ret = 1;
err:
EVP_PKEY_free(pkey);
EVP_PKEY_CTX_free(ctx);
BIO_free(bio);
EVP_PKEY_free(pParams);
return ret;
}

int setup_tests(void)
{
OPTION_CHOICE o;
char *config_file = NULL;

while ((o = opt_next()) != OPT_EOF) {
switch (o) {
case OPT_CONFIG_FILE:
config_file = opt_arg();
break;
case OPT_PAIRWISETEST:
pairwise_name = opt_arg();
break;
case OPT_DSAPARAM:
dsaparam_file = opt_arg();
break;
case OPT_TEST_CASES:
break;
default:
case OPT_ERR:
return 0;
}
}

libctx = OSSL_LIB_CTX_new();
if (libctx == NULL)
return 0;
if (!OSSL_LIB_CTX_load_config(libctx, config_file)) {
opt_printf_stderr("Failed to load config\n");
return 0;
}
ADD_TEST(test_keygen_pairwise_failure);
return 1;
}

void cleanup_tests(void)
{
OSSL_LIB_CTX_free(libctx);
}
65 changes: 65 additions & 0 deletions test/recipes/30-test_pairwise_fail.t
@@ -0,0 +1,65 @@
#! /usr/bin/env perl
# Copyright 2023 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
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html

use strict;
use warnings;

use OpenSSL::Test qw(:DEFAULT bldtop_dir srctop_file srctop_dir data_file);
use OpenSSL::Test::Utils;

BEGIN {
setup("test_pairwise_fail");
}

use lib srctop_dir('Configurations');
use lib bldtop_dir('.');

plan skip_all => "These tests are unsupported in a non fips build"
if disabled("fips");

plan tests => 5;
my $provconf = srctop_file("test", "fips-and-base.cnf");

run(test(["fips_version_test", "-config", $provconf, ">=3.1.0"]),
capture => 1, statusvar => \my $fips_exit);

SKIP: {
skip "Skip RSA test because of no rsa in this build", 1
if disabled("rsa");
ok(run(test(["pairwise_fail_test", "-config", $provconf,
"-pairwise", "rsa"])),
"fips provider rsa keygen pairwise failure test");
}

SKIP: {
skip "Skip EC test because of no ec in this build", 2
if disabled("ec");
ok(run(test(["pairwise_fail_test", "-config", $provconf,
"-pairwise", "ec"])),
"fips provider ec keygen pairwise failure test");

skip "FIPS provider version is too old", 1
if !$fips_exit;
ok(run(test(["pairwise_fail_test", "-config", $provconf,
"-pairwise", "eckat"])),
"fips provider ec keygen kat failure test");
}

SKIP: {
skip "Skip DSA tests because of no dsa in this build", 2
if disabled("dsa");
ok(run(test(["pairwise_fail_test", "-config", $provconf,
"-pairwise", "dsa", "-dsaparam", data_file("dsaparam.pem")])),
"fips provider dsa keygen pairwise failure test");

skip "FIPS provider version is too old", 1
if !$fips_exit;
ok(run(test(["pairwise_fail_test", "-config", $provconf,
"-pairwise", "dsakat", "-dsaparam", data_file("dsaparam.pem")])),
"fips provider dsa keygen kat failure test");
}
14 changes: 14 additions & 0 deletions test/recipes/30-test_pairwise_fail_data/dsaparam.pem
@@ -0,0 +1,14 @@
-----BEGIN DSA PARAMETERS-----
MIICLQKCAQEA2Drds0DjRV8ht73dVp44MMtcjvSxugNuElrwheVB5Bm1wsmrEVnt
MSGdZJ5FpndQD/ndqSctTssjW+cxjJ4mHjVTXpTZURQZW0MNkn7+qVw6oFrnd+qq
tDkh0jnaTYTNiEp6qm5QmnEC/Ccvr3YZuY9EHurzVptJuoRIMgFGCz4CHj5q2vQ/
CPvBohUSvC9EmKGveWGFID+tmFWuHZ9d9pF/GWjA2rdW//uRiStssbN24jscsbZ6
XnNrJpgyGYYjugsl+catrMkodstrLsk7YvEYcE6YYN0TwZc9kjJ5f3ydQnI35Y/s
EQPtP7DdA8aLaOC1ra2Nakm2ZW+pkygPMQIhAI2NF0GuR7NjD7lXx6gnVyk3p6gR
l7u+BNIhHFVJP2/9AoIBAQCvGDoQ9S6So58RDz15ghYjpdNSzCBtA6ixYszesSJU
DksnEDV34AEB2C8/uvzcSIca3314dDsE2R0ubTrh4J/2JNbNE9M5UYEaJh0oK7LW
h7YZ2XI5j08/aAApRsR84kcZdE3r+QYFHTuEnoc0ADkC3J9uIuQwl/CgTkw56OBP
MmA1GD79/MeYc/mvJujujWG0Y+tyuQCORzcYccEpYR8q6kf1r7+IUy1L8r4XFIwM
oW9eB4XyTrA8wKtWQfEpSAo+PX59hfafuOG8wKUPbTANSFK2ePQRJO/6T81rofOF
Bz9oeTjZV0f0EkJIcF14V2rksGVT0kAHndBw73w27ofj
-----END DSA PARAMETERS-----

0 comments on commit dcd20cc

Please sign in to comment.