diff --git a/Configure b/Configure index ce92fd517..28a81e843 100755 --- a/Configure +++ b/Configure @@ -271,9 +271,13 @@ $config{builddir} = abs2rel($blddir, $blddir); # echo -n 'holy hand grenade of antioch' | openssl sha256 $config{FIPSKEY} = 'f4556650ac31d35461610bac4ed81b1a181b2d8a43ea2854cbae22ca74560813'; -# echo -n "Tongsuo in hand, no worries about compliance" | tongsuo sm3 -$config{SMTCKEY} = - '5b3d9ad84fd72961e63f27a3d5da2bb663e2ed9c7b761b8ad6d041ebc68f5098'; +$config{SMTCPUBKEY} = +'-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAERjiZ5ubxrnOZnjhvqvuJ5UcdRI64 +sBEVwF0UztQK9eYzqOsFEm0PKkCjoYkdmiZ+Und0agHk94eFKhtUYsu0bw== +-----END PUBLIC KEY-----'; +$config{SMTCPUBKEY} =~ s|\n|\\n|g; + # Collect reconfiguration information if needed my @argvcopy=@ARGV; @@ -796,7 +800,7 @@ my %cmdvars = (); # Stores FOO='blah' type arguments my %unsupported_options = (); my %deprecated_options = (); # If you change this, update apps/version.c -my @known_seed_sources = qw(getrandom devrandom os egd none rdcpu librandom rtc); +my @known_seed_sources = qw(getrandom devrandom os egd none rdcpu librandom rtcode rtmem); my @seed_sources = (); while (@argvcopy) { @@ -1021,15 +1025,13 @@ while (@argvcopy) die "FIPS key too long (64 bytes max)\n" if length $1 > 64; } - elsif (/^--smtc-key=(.*)$/) + elsif (/^--smtc-pubkey=(.*)$/) { - $user{SMTCKEY}=lc($1); - die "Non-hex character in SMTC key\n" - if $user{SMTCKEY} =~ /[^a-f0-9]/; - die "SMTC key must have even number of characters\n" - if length $1 & 1; - die "SMTC key too long (64 bytes max)\n" - if length $1 > 64; + open my $fh, "<", $1 or die "Can't open $1: $!\n"; + $user{SMTCPUBKEY} = <$fh>; + close $fh; + chomp $user{SMTCPUBKEY}; + $user{SMTCPUBKEY} =~ s|\n|\\n|g; } elsif (/^--banner=(.*)$/) { diff --git a/apps/mod.c b/apps/mod.c index 65cf4220e..87f551adc 100644 --- a/apps/mod.c +++ b/apps/mod.c @@ -7,7 +7,8 @@ * https://github.com/Tongsuo-Project/Tongsuo/blob/master/LICENSE.txt */ #include - +#include +#include #include "apps.h" #include "progs.h" #include @@ -21,20 +22,17 @@ #include "internal/smtc_names.h" #include "../providers/smtc/smtckey.h" -#define PASSWD_BUF_SIZE 1024 +#define PASSWD_BUF_SIZE 65 #define BUFSIZE 4096 typedef struct { const char *section; const char *module_path; -#ifndef OPENSSL_NO_SMTC_DEBUG - int verify_pass; -#endif int show_selftest; unsigned char admin_salt[SM3_DIGEST_LENGTH]; unsigned char admin_pass[SM3_DIGEST_LENGTH]; - unsigned char module_mac[EVP_MAX_MD_SIZE]; - size_t module_mac_len; + unsigned char *sig; + size_t siglen; } SMTC_CONF; typedef enum OPTION_choice { @@ -45,11 +43,11 @@ typedef enum OPTION_choice { OPT_MODULE, OPT_PROV_NAME, OPT_SECTION_NAME, - OPT_OUT, + OPT_SIGFILE, + OPT_NEW, + OPT_CONFIG, OPT_SHOW_SELFTEST, -#ifndef OPENSSL_NO_SMTC_DEBUG - OPT_NO_PASS, -#endif + OPT_PASS, OPT_R_ENUM } OPTION_CHOICE; @@ -63,60 +61,70 @@ const OPTIONS mod_options[] = { OPT_SECTION_NAME, 's', "SMTC Provider config section name (optional)"}, - {"show_selftest", OPT_SHOW_SELFTEST, '-', "Show self test"}, -#ifndef OPENSSL_NO_SMTC_DEBUG - {"no_pass", OPT_NO_PASS, '-', "Do not setup password"}, -#endif + {"show_selftest", OPT_SHOW_SELFTEST, '-', "Show self test"}, + {"pass", OPT_PASS, '-', "Setup password"}, + OPT_SECTION("Input"), + {"config", OPT_CONFIG, '>', "Config file"}, + {"sigfile", OPT_SIGFILE, '<', "Signature file"}, OPT_SECTION("Output"), - {"out", OPT_OUT, '>', "Output config file, used when generating"}, + {"new", OPT_NEW, '>', "Output config file, used when generating"}, {NULL}}; -static int setup_password(unsigned char *admin_salt, unsigned char *admin_pass) +static int check_passwd(const char *passwd, size_t len) { - int ret = 0; - char passwd[PASSWD_BUF_SIZE]; - EVP_MD_CTX *mctx = NULL; + size_t i; + int upper = 0, lower = 0, digit = 0; - if (EVP_read_pw_string(passwd, sizeof(passwd), "Setup password: ", 1) != 0) - goto end; + if (len < 8 || len > 64) + return 0; - if (RAND_bytes(admin_salt, SM3_DIGEST_LENGTH) <= 0) - goto end; + for (i = 0; i < len; i++) { + if (isupper(passwd[i])) + upper = 1; + else if (islower(passwd[i])) + lower = 1; + else if (isdigit(passwd[i])) + digit = 1; + else + return 0; + } - if ((mctx = EVP_MD_CTX_new()) == NULL - || !EVP_DigestInit_ex(mctx, EVP_sm3(), NULL) - || !EVP_DigestUpdate(mctx, admin_salt, SM3_DIGEST_LENGTH) - || !EVP_DigestUpdate(mctx, passwd, strlen(passwd)) - || !EVP_DigestFinal_ex(mctx, admin_pass, NULL)) - goto end; + if (upper + lower + digit < 3) + return 0; - ret = 1; -end: - EVP_MD_CTX_free(mctx); - return ret; + return 1; } -static int do_mac(EVP_MAC_CTX *ctx, unsigned char *tmp, BIO *in, - unsigned char *out, size_t *out_len) +static int setup_password(unsigned char *admin_salt, unsigned char *admin_pass) { int ret = 0; - int i; - size_t outsz = *out_len; + char passwd[PASSWD_BUF_SIZE] = {0}; + SM3_CTX ctx; + + srand(time(NULL)); + + if (EVP_read_pw_string_min(passwd, 8, sizeof(passwd) - 1, + "Setup password: ", 1) != 0) + goto end; - if (!EVP_MAC_init(ctx, NULL, 0, NULL)) - goto err; - if (EVP_MAC_CTX_get_mac_size(ctx) > outsz) + if (!check_passwd(passwd, strlen(passwd))) { + BIO_printf(bio_err, "Passwords should be 8-64 characters in length and" + "must contain numbers, uppercase and lowercase letters\n"); goto end; - while ((i = BIO_read(in, (char *)tmp, BUFSIZE)) != 0) { - if (i < 0 || !EVP_MAC_update(ctx, tmp, i)) - goto err; } -end: - if (!EVP_MAC_final(ctx, out, out_len, outsz)) - goto err; + + snprintf((char *)admin_salt, SM3_DIGEST_LENGTH, "SALT%d%d%d%d", rand(), + rand(), rand(), rand()); + + if (!SM3_Init(&ctx) + || !SM3_Update(&ctx, admin_salt, SM3_DIGEST_LENGTH) + || !SM3_Update(&ctx, passwd, strlen(passwd)) + || !SM3_Final(admin_pass, &ctx)) + goto end; + ret = 1; -err: +end: return ret; } @@ -156,8 +164,8 @@ static int write_config_smtc_section(BIO *out, SMTC_CONF *sc) || BIO_printf(out, "activate = 1\n") <= 0 || BIO_printf(out, "%s = %s\n", OSSL_PROV_SMTC_PARAM_MODULE_PATH, sc->module_path) <= 0 - || !print_hex(out, OSSL_PROV_SMTC_PARAM_MODULE_MAC, sc->module_mac, - sc->module_mac_len)) + || !print_hex(out, OSSL_PROV_SMTC_PARAM_MODULE_SIG, sc->sig, + sc->siglen)) goto end; if (sc->show_selftest) { @@ -170,22 +178,6 @@ static int write_config_smtc_section(BIO *out, SMTC_CONF *sc) goto end; } -#ifndef OPENSSL_NO_SMTC_DEBUG - if (sc->verify_pass == 0) { - if (BIO_printf(out, "%s = 0\n", OSSL_PROV_SMTC_PARAM_MODULE_VERIFY_PASS) - <= 0) - goto end; - } else { -#endif - if (!print_hex(out, OSSL_PROV_SMTC_PARAM_ADMIN_SALT, sc->admin_salt, - sizeof(sc->admin_salt)) - || !print_hex(out, OSSL_PROV_SMTC_PARAM_ADMIN_PASS, - sc->admin_pass, sizeof(sc->admin_pass))) - goto end; -#ifndef OPENSSL_NO_SMTC_DEBUG - } -#endif - ret = 1; end: return ret; @@ -220,32 +212,22 @@ static CONF *generate_config_and_load(const char *prov_name, SMTC_CONF *sc) int mod_main(int argc, char **argv) { int ret = 1; -#ifndef OPENSSL_NO_SMTC_DEBUG - int no_pass = 0; -#endif + int new = 0, pass = 0; char *prog; + unsigned char *sig = NULL; + size_t siglen = 0; + const char *sigfile = NULL; OPTION_CHOICE o; int self_test = 0; BIO *module_bio = NULL, *fout = NULL; char *out_fname = NULL; - EVP_MAC *mac = NULL; - const char *mac_name = "HMAC"; - const char *prov_name = "smtc"; + const char *prov_name = "smtc", *conf_file = NULL; SMTC_CONF sc = { .section = "smtc_sect", .show_selftest = 0, -#ifndef OPENSSL_NO_SMTC_DEBUG - .verify_pass = 1, -#endif }; - STACK_OF(OPENSSL_STRING) *opts = NULL; - unsigned char *read_buffer = NULL; - EVP_MAC_CTX *ctx = NULL, *ctx2 = NULL; CONF *conf = NULL; - if ((opts = sk_OPENSSL_STRING_new_null()) == NULL) - goto end; - prog = opt_init(argc, argv, mod_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { @@ -273,13 +255,17 @@ int mod_main(int argc, char **argv) case OPT_SHOW_SELFTEST: sc.show_selftest = 1; break; -#ifndef OPENSSL_NO_SMTC_DEBUG - case OPT_NO_PASS: - no_pass = 1; - sc.verify_pass = 0; + case OPT_PASS: + pass = 1; + break; + case OPT_SIGFILE: + sigfile = opt_arg(); + break; + case OPT_CONFIG: + conf_file = opt_arg(); break; -#endif - case OPT_OUT: + case OPT_NEW: + new = 1; out_fname = opt_arg(); break; case OPT_R_CASES: @@ -315,84 +301,68 @@ int mod_main(int argc, char **argv) } } -#ifndef OPENSSL_NO_SMTC_DEBUG - if (!no_pass) -#endif - if (!setup_password(sc.admin_salt, sc.admin_pass)) + if (new) { + if (sigfile == NULL) { + BIO_printf(bio_err, "No signature file specified\n"); goto end; + } - if (sc.module_path == NULL) - goto opthelp; - - if (!sk_OPENSSL_STRING_push(opts, "digest:SM3")) - goto end; - if (!sk_OPENSSL_STRING_push(opts, "hexkey:" SMTC_KEY_STRING)) - goto end; - - module_bio = bio_open_default(sc.module_path, 'r', FORMAT_BINARY); - if (module_bio == NULL) { - BIO_printf(bio_err, "Failed to open module file\n"); - goto end; - } - - read_buffer = app_malloc(BUFSIZE, "I/O buffer"); - if (read_buffer == NULL) - goto end; - - mac = EVP_MAC_fetch(app_get0_libctx(), mac_name, app_get0_propq()); - if (mac == NULL) { - BIO_printf(bio_err, "Unable to get MAC of type %s\n", mac_name); - goto end; - } + BIO *sigbio = BIO_new_file(sigfile, "rb"); - ctx = EVP_MAC_CTX_new(mac); - if (ctx == NULL) { - BIO_printf(bio_err, "Unable to create MAC CTX for module check\n"); - goto end; - } + if (sigbio == NULL) { + BIO_printf(bio_err, "Can't open signature file %s\n", sigfile); + goto end; + } + siglen = bio_to_mem(&sig, 4096, sigbio); + BIO_free(sigbio); + if (siglen < 0) { + BIO_printf(bio_err, "Error reading signature data\n"); + goto end; + } + sc.sig = sig; + sc.siglen = siglen; - if (opts != NULL) { - int ok = 1; - OSSL_PARAM *params - = app_params_new_from_opts(opts, EVP_MAC_settable_ctx_params(mac)); + if (sc.module_path == NULL) + goto opthelp; - if (params == NULL) + conf = generate_config_and_load(prov_name, &sc); + if (conf == NULL) goto end; - if (!EVP_MAC_CTX_set_params(ctx, params)) { - BIO_printf(bio_err, "MAC parameter error\n"); - ERR_print_errors(bio_err); - ok = 0; + fout = out_fname == NULL ? dup_bio_out(FORMAT_TEXT) + : bio_open_default(out_fname, 'w', FORMAT_TEXT); + if (fout == NULL) { + BIO_printf(bio_err, "Failed to open file\n"); + goto end; } - app_params_free(params); - if (!ok) + if (!write_config_smtc_section(fout, &sc)) goto end; - } - ctx2 = EVP_MAC_CTX_dup(ctx); - if (ctx2 == NULL) { - BIO_printf(bio_err, "Unable to create MAC CTX for install indicator\n"); + BIO_printf(bio_err, "INSTALL PASSED\n"); + + ret = 0; goto end; } - sc.module_mac_len = sizeof(sc.module_mac); - if (!do_mac(ctx, read_buffer, module_bio, sc.module_mac, &sc.module_mac_len)) - goto end; + if (conf_file != NULL) { + fout = bio_open_default(conf_file, 'a', FORMAT_TEXT); + if (fout == NULL) { + BIO_printf(bio_err, "Failed to open config %s\n", conf_file); + goto end; + } - conf = generate_config_and_load(prov_name, &sc); - if (conf == NULL) - goto end; + if (pass) { + if (!setup_password(sc.admin_salt, sc.admin_pass)) + goto end; - fout = out_fname == NULL ? dup_bio_out(FORMAT_TEXT) - : bio_open_default(out_fname, 'w', FORMAT_TEXT); - if (fout == NULL) { - BIO_printf(bio_err, "Failed to open file\n"); - goto end; + if (!print_hex(fout, OSSL_PROV_SMTC_PARAM_ADMIN_SALT, + sc.admin_salt, + sizeof(sc.admin_salt)) + || !print_hex(fout, OSSL_PROV_SMTC_PARAM_ADMIN_PASS, + sc.admin_pass, sizeof(sc.admin_pass))) + goto end; + } } - if (!write_config_smtc_section(fout, &sc)) - goto end; - - BIO_printf(bio_err, "INSTALL PASSED\n"); ret = 0; end: @@ -400,13 +370,9 @@ int mod_main(int argc, char **argv) ERR_print_errors(bio_err); cleanup: + OPENSSL_free(sig); BIO_free(fout); BIO_free(module_bio); - sk_OPENSSL_STRING_free(opts); - EVP_MAC_free(mac); - EVP_MAC_CTX_free(ctx2); - EVP_MAC_CTX_free(ctx); - OPENSSL_free(read_buffer); if (conf != NULL) { NCONF_free(conf); CONF_modules_unload(1); diff --git a/apps/openssl.c b/apps/openssl.c index e23515772..293a698f0 100644 --- a/apps/openssl.c +++ b/apps/openssl.c @@ -28,6 +28,9 @@ #include "apps.h" #include "progs.h" +/* Special sentinel to exit the program. */ +#define EXIT_THE_PROGRAM (-1) + /* * The LHASH callbacks ("hash" & "cmp") have been replaced by functions with * the base prototypes (we cast each variable inside the function to the @@ -236,11 +239,12 @@ int main(int argc, char *argv[]) { FUNCTION f, *fp; LHASH_OF(FUNCTION) *prog = NULL; - char *pname; - const char *fname; + char *p, *pname; + char buf[1024]; + const char *prompt, *fname; ARGS arg; int global_help = 0; - int ret = 0; + int first, n, i, ret = 0; arg.argv = NULL; arg.size = 0; @@ -289,11 +293,81 @@ int main(int argc, char *argv[]) argv[0] = pname; } - /* If there's a command, run with that, otherwise "help". */ - ret = argc == 0 || global_help - ? do_cmd(prog, 1, help_argv) - : do_cmd(prog, argc, argv); + if (global_help) { + ret = do_cmd(prog, 1, help_argv); + goto end; + } + + if (argc != 0) { + ret = do_cmd(prog, argc, argv); + goto end; + } + + /* interactive mode */ + for (;;) { + ret = 0; + /* Read a line, continue reading if line ends with \ */ + for (p = buf, n = sizeof(buf), i = 0, first = 1; n > 0; first = 0) { + prompt = first ? "Tongsuo> " : "> "; + p[0] = '\0'; +#ifndef READLINE + fputs(prompt, stdout); + fflush(stdout); + if (!fgets(p, n, stdin)) + goto end; + if (p[0] == '\0') + goto end; + i = strlen(p); + if (i <= 1) + break; + if (p[i - 2] != '\\') + break; + i -= 2; + p += i; + n -= i; +#else + { + extern char *readline(const char *); + extern void add_history(const char *cp); + char *text; + + text = readline(prompt); + if (text == NULL) + goto end; + i = strlen(text); + if (i == 0 || i > n) + break; + if (text[i - 1] != '\\') { + p += strlen(strcpy(p, text)); + free(text); + add_history(buf); + break; + } + + text[i - 1] = '\0'; + p += strlen(strcpy(p, text)); + free(text); + n -= i; + } +#endif + } + if (!chopup_args(&arg, buf)) { + BIO_printf(bio_err, "Can't parse (no memory?)\n"); + break; + } + + ret = do_cmd(prog, arg.argc, arg.argv); + if (ret == EXIT_THE_PROGRAM) { + ret = 0; + goto end; + } + if (ret != 0) + BIO_printf(bio_err, "error in %s\n", arg.argv[0]); + (void)BIO_flush(bio_out); + (void)BIO_flush(bio_err); + } + ret = 1; end: OPENSSL_free(default_config_file); lh_FUNCTION_free(prog); @@ -396,28 +470,6 @@ static int do_cmd(LHASH_OF(FUNCTION) *prog, int argc, char *argv[]) if (argc <= 0 || argv[0] == NULL) return 0; -#ifdef SMTC_MODULE - /* Every app should run smtc self test firstly except mod, version and help */ - if (strcmp(argv[0], "mod") != 0 - && strcmp(argv[0], "version") != 0 - && strcmp(argv[0], "help") != 0) { - if (OSSL_PROVIDER_available(app_get0_libctx(), "smtc")) { - OSSL_PROVIDER *prov = OSSL_PROVIDER_load(app_get0_libctx(), "smtc"); - if (prov == NULL) { - BIO_printf(bio_err, "Failed to load smtc provider\n"); - return 0; - } - - if (OSSL_PROVIDER_self_test(prov) != 1) { - OSSL_PROVIDER_unload(prov); - BIO_printf(bio_err, "smtc self test failed\n"); - return 0; - } - - OSSL_PROVIDER_unload(prov); - } - } -#endif memset(&f, 0, sizeof(f)); f.name = argv[0]; fp = lh_FUNCTION_retrieve(prog, &f); @@ -451,6 +503,11 @@ static int do_cmd(LHASH_OF(FUNCTION) *prog, int argc, char *argv[]) return 1; } + if (strcmp(argv[0], "quit") == 0 || strcmp(argv[0], "q") == 0 || + strcmp(argv[0], "exit") == 0 || strcmp(argv[0], "bye") == 0) + /* Special value to mean "exit the program. */ + return EXIT_THE_PROGRAM; + BIO_printf(bio_err, "Invalid command '%s'; type \"help\" for a list.\n", argv[0]); return 1; diff --git a/apps/rand.c b/apps/rand.c index cbf495d5b..89390ecb1 100644 --- a/apps/rand.c +++ b/apps/rand.c @@ -17,10 +17,11 @@ #include #include #include +#include "crypto/rand.h" typedef enum OPTION_choice { OPT_COMMON, - OPT_OUT, OPT_ENGINE, OPT_BASE64, OPT_HEX, + OPT_OUT, OPT_ENGINE, OPT_BASE64, OPT_HEX, OPT_ENTROPY, OPT_R_ENUM, OPT_PROV_ENUM } OPTION_CHOICE; @@ -37,6 +38,7 @@ const OPTIONS rand_options[] = { {"out", OPT_OUT, '>', "Output file"}, {"base64", OPT_BASE64, '-', "Base64 encode output"}, {"hex", OPT_HEX, '-', "Hex encode output"}, + {"entropy", OPT_ENTROPY, '-', "Output entropy instead of random data"}, OPT_R_OPTIONS, OPT_PROV_OPTIONS, @@ -52,7 +54,8 @@ int rand_main(int argc, char **argv) BIO *out = NULL; char *outfile = NULL, *prog; OPTION_CHOICE o; - int format = FORMAT_BINARY, i, num = -1, r, ret = 1; + unsigned char *ent_buf = NULL; + int format = FORMAT_BINARY, i, num = -1, r, ret = 1, entropy = 0; prog = opt_init(argc, argv, rand_options); while ((o = opt_next()) != OPT_EOF) { @@ -82,6 +85,9 @@ int rand_main(int argc, char **argv) case OPT_HEX: format = FORMAT_TEXT; break; + case OPT_ENTROPY: + entropy = 1; + break; case OPT_PROV_CASES: if (!opt_provider(o)) goto end; @@ -120,9 +126,22 @@ int rand_main(int argc, char **argv) chunk = num; if (chunk > (int)sizeof(buf)) chunk = sizeof(buf); - r = RAND_bytes(buf, chunk); + + if (entropy) + r = ossl_rand_get_entropy(NULL, &ent_buf, 0, chunk, chunk); + else + r = RAND_bytes(buf, chunk); + if (r <= 0) goto end; + + if (entropy) { + memcpy(buf, ent_buf, r); + chunk = r; + ossl_rand_cleanup_entropy(NULL, ent_buf, r); + ent_buf = NULL; + } + if (format != FORMAT_TEXT) { if (BIO_write(out, buf, chunk) != chunk) goto end; diff --git a/crypto/ec/ec_key.c b/crypto/ec/ec_key.c index eb14f4e40..00014ecb9 100644 --- a/crypto/ec/ec_key.c +++ b/crypto/ec/ec_key.c @@ -322,7 +322,7 @@ static int ec_generate_key(EC_KEY *eckey, int pairwise_test) eckey->dirty_cnt++; -#ifdef FIPS_MODULE +#if defined(FIPS_MODULE) || defined(SMTC_MODULE) pairwise_test = 1; #endif /* FIPS_MODULE */ diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index bfe7a985e..6e2a996ab 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -1,4 +1,4 @@ -# Copyright 1999-2023 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 1999-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 @@ -651,7 +651,6 @@ ESS_R_ESS_SIGNING_CERT_V2_ADD_ERROR:101:ess signing cert v2 add error ESS_R_MISSING_SIGNING_CERTIFICATE_ATTRIBUTE:108:\ missing signing certificate attribute EVP_R_AES_KEY_SETUP_FAILED:143:aes key setup failed -EVP_R_ARIA_KEY_SETUP_FAILED:176:aria key setup failed EVP_R_BAD_ALGORITHM_NAME:200:bad algorithm name EVP_R_BAD_DECRYPT:100:bad decrypt EVP_R_BAD_KEY_LENGTH:195:bad key length @@ -989,6 +988,7 @@ PROV_R_FIPS_MODULE_IN_ERROR_STATE:225:fips module in error state PROV_R_GENERATE_ERROR:191:generate error PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE:165:\ illegal or unsupported padding mode +PROV_R_INCORRECT_PASSWORD:231:incorrect password PROV_R_INDICATOR_INTEGRITY_FAILURE:210:indicator integrity failure PROV_R_INSUFFICIENT_DRBG_STRENGTH:181:insufficient drbg strength PROV_R_INVALID_AAD:108:invalid aad diff --git a/crypto/info.c b/crypto/info.c index 69142d396..4d41c10c1 100644 --- a/crypto/info.c +++ b/crypto/info.c @@ -152,8 +152,11 @@ DEFINE_RUN_ONCE_STATIC(init_info_strings) #ifdef OPENSSL_RAND_SEED_OS add_seeds_string("os-specific"); #endif -#ifdef OPENSSL_RAND_SEED_RTC - add_seeds_string("real-time-clock"); +#ifdef OPENSSL_RAND_SEED_RTCODE + add_seeds_string("real-time-code"); +#endif +#ifdef OPENSSL_RAND_SEED_RTMEM + add_seeds_string("real-time-memory"); #endif seed_sources = seeds; } diff --git a/crypto/provider_predefined.c b/crypto/provider_predefined.c index 938c1ba9a..1d60e7484 100644 --- a/crypto/provider_predefined.c +++ b/crypto/provider_predefined.c @@ -17,13 +17,21 @@ OSSL_provider_init_fn ossl_fips_intern_provider_init; #ifdef STATIC_LEGACY OSSL_provider_init_fn ossl_legacy_provider_init; #endif -#ifdef STATIC_SMTC +#ifdef SMTC_MODULE +# ifdef STATIC_SMTC OSSL_provider_init_fn ossl_smtc_provider_init; +# endif +OSSL_provider_init_fn ossl_smtc_intern_provider_init; #endif const OSSL_PROVIDER_INFO ossl_predefined_providers[] = { #ifdef FIPS_MODULE { "fips", NULL, ossl_fips_intern_provider_init, NULL, 1 }, +#elif defined(SMTC_MODULE) + { "smtc-int", NULL, ossl_smtc_intern_provider_init, NULL, 1 }, +# ifdef STATIC_SMTC + { "smtc", NULL, ossl_smtc_provider_init, NULL, 0 }, +# endif #else { "default", NULL, ossl_default_provider_init, NULL, 1 }, # ifdef STATIC_LEGACY @@ -31,9 +39,6 @@ const OSSL_PROVIDER_INFO ossl_predefined_providers[] = { # endif { "base", NULL, ossl_base_provider_init, NULL, 0 }, { "null", NULL, ossl_null_provider_init, NULL, 0 }, -# ifdef STATIC_SMTC - { "smtc", NULL, ossl_smtc_provider_init, NULL, 0 }, -# endif #endif { NULL, NULL, NULL, NULL, 0 } }; diff --git a/include/crypto/rand_pool.h b/include/crypto/rand_pool.h index f4d1d954b..75b9918a1 100644 --- a/include/crypto/rand_pool.h +++ b/include/crypto/rand_pool.h @@ -32,9 +32,15 @@ * The factor 1.5 below is the pessimistic estimate for the extra amount * of entropy required when no get_nonce() callback is defined. */ -# define RAND_POOL_FACTOR 256 -# define RAND_POOL_MAX_LENGTH (RAND_POOL_FACTOR * \ - 3 * (RAND_DRBG_STRENGTH / 16)) + +# ifdef TONGSUO_RAND_GM_SRNG +/* As required by GM/T 0105-2021 section 5.3 */ +# define RAND_POOL_MAX_LENGTH 4096 +# else +# define RAND_POOL_FACTOR 256 +# define RAND_POOL_MAX_LENGTH (RAND_POOL_FACTOR * \ + 3 * (RAND_DRBG_STRENGTH / 16)) +# endif /* * = (RAND_POOL_FACTOR * \ * 1.5 * (RAND_DRBG_STRENGTH / 8)) @@ -57,7 +63,12 @@ * with 40 bytes. The value of forty eight is comfortably above this which * allows some slack in the platform specific values used. */ -# define RAND_POOL_MIN_ALLOCATION(secure) ((secure) ? 16 : 48) +# ifdef TONGSUO_RAND_GM_SRNG +/* GM/T 0105-2021 DRNG requires the entropy pool should at least 512 bytes. */ +# define RAND_POOL_MIN_ALLOCATION(secure) ((secure) ? 512 : 1024) +# else +# define RAND_POOL_MIN_ALLOCATION(secure) ((secure) ? 16 : 48) +# endif /* * The 'random pool' acts as a dumb container for collecting random diff --git a/include/internal/smtc_names.h b/include/internal/smtc_names.h index fe67aae5c..2e84ac8b4 100644 --- a/include/internal/smtc_names.h +++ b/include/internal/smtc_names.h @@ -14,7 +14,7 @@ # include # define OSSL_PROV_SMTC_PARAM_MODULE_PATH "module-path" -# define OSSL_PROV_SMTC_PARAM_MODULE_MAC "module-mac" +# define OSSL_PROV_SMTC_PARAM_MODULE_SIG "module-sig" # define OSSL_PROV_SMTC_PARAM_ADMIN_PASS "admin-pass" # define OSSL_PROV_SMTC_PARAM_ADMIN_SALT "admin-salt" # define OSSL_PROV_SMTC_PARAM_SHOW_SELFTEST "show-selftest" @@ -23,7 +23,7 @@ # define OSSL_PROV_SMTC_PARAM_RANDOMNESS_POWERON_TEST "randomness-poweron-test" # ifndef OPENSSL_NO_SMTC_DEBUG -# define OSSL_PROV_SMTC_PARAM_MODULE_VERIFY_MAC "verify-mac" +# define OSSL_PROV_SMTC_PARAM_MODULE_VERIFY_SIG "verify-sig" # define OSSL_PROV_SMTC_PARAM_MODULE_VERIFY_PASS "verify-pass" # endif diff --git a/include/openssl/proverr.h b/include/openssl/proverr.h index ad67a8f89..e940ecb42 100644 --- a/include/openssl/proverr.h +++ b/include/openssl/proverr.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-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 @@ -48,6 +48,7 @@ # define PROV_R_FIPS_MODULE_IN_ERROR_STATE 225 # define PROV_R_GENERATE_ERROR 191 # define PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE 165 +# define PROV_R_INCORRECT_PASSWORD 231 # define PROV_R_INDICATOR_INTEGRITY_FAILURE 210 # define PROV_R_INSUFFICIENT_DRBG_STRENGTH 181 # define PROV_R_INVALID_AAD 108 diff --git a/include/openssl/self_test.h b/include/openssl/self_test.h index 357e1a9d2..f6d822de1 100644 --- a/include/openssl/self_test.h +++ b/include/openssl/self_test.h @@ -42,6 +42,7 @@ extern "C" { /* Test event sub categories */ # define OSSL_SELF_TEST_DESC_NONE "None" # define OSSL_SELF_TEST_DESC_INTEGRITY_HMAC "HMAC" +# define OSSL_SELF_TEST_DESC_INTEGRITY_VERIFY "Verify_Integrity" # define OSSL_SELF_TEST_DESC_PCT_RSA_PKCS1 "RSA" # define OSSL_SELF_TEST_DESC_PCT_ECDSA "ECDSA" # define OSSL_SELF_TEST_DESC_PCT_DSA "DSA" @@ -56,6 +57,8 @@ extern "C" { # define OSSL_SELF_TEST_DESC_SIGN_DSA "DSA" # define OSSL_SELF_TEST_DESC_SIGN_RSA "RSA" # define OSSL_SELF_TEST_DESC_SIGN_SM2 "SM2" +# define OSSL_SELF_TEST_DESC_SIGN_SM2_SIGN "SM2_Sign" +# define OSSL_SELF_TEST_DESC_SIGN_SM2_VERIFY "SM2_Verify" # define OSSL_SELF_TEST_DESC_SIGN_ECDSA "ECDSA" # define OSSL_SELF_TEST_DESC_DRBG_CTR "CTR" # define OSSL_SELF_TEST_DESC_DRBG_HASH "HASH" diff --git a/providers/build.info b/providers/build.info index 072bce04c..d99af04ab 100644 --- a/providers/build.info +++ b/providers/build.info @@ -152,7 +152,6 @@ IF[{- !$disabled{smtc} -}] SOURCE[$SMTCGOAL]=smtc.ld GENERATE[smtc.ld]=../util/providers.num ENDIF - SOURCE[$LIBSMTC]=prov_running.c ENDIF DEFINE[$SMTCGOAL]=SMTC_MODULE diff --git a/providers/common/provider_err.c b/providers/common/provider_err.c index 344c12211..66c869b70 100644 --- a/providers/common/provider_err.c +++ b/providers/common/provider_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-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 @@ -62,6 +62,8 @@ static const ERR_STRING_DATA PROV_str_reasons[] = { {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_GENERATE_ERROR), "generate error"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE), "illegal or unsupported padding mode"}, + {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INCORRECT_PASSWORD), + "incorrect password"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INDICATOR_INTEGRITY_FAILURE), "indicator integrity failure"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INSUFFICIENT_DRBG_STRENGTH), diff --git a/providers/implementations/rands/drbg_hash.c b/providers/implementations/rands/drbg_hash.c index 617e75848..9798a03ff 100644 --- a/providers/implementations/rands/drbg_hash.c +++ b/providers/implementations/rands/drbg_hash.c @@ -309,8 +309,10 @@ static int drbg_hash_reseed(PROV_DRBG *drbg, adin, adin_len)) return 0; } else { - /* (Step 1-2) V = Hash_df(0x01 || V || entropy_input || additional_input) */ - /* V about to be updated so use C as output instead */ + /* + * (Step 1-2) V=Hash_df(0x01 || V || entropy_input || additional_input) + * V about to be updated so use C as output instead + */ if (!hash_df(drbg, hash->C, 0x01, hash->V, drbg->seedlen, ent, ent_len, adin, adin_len)) return 0; diff --git a/providers/implementations/rands/drbg_local.h b/providers/implementations/rands/drbg_local.h index a0877e379..4e8728409 100644 --- a/providers/implementations/rands/drbg_local.h +++ b/providers/implementations/rands/drbg_local.h @@ -50,12 +50,22 @@ # define DRBG_MAX_LENGTH INT32_MAX /* The default nonce */ -#ifdef CHARSET_EBCDIC -# define DRBG_DEFAULT_PERS_STRING { 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x53, \ +#ifdef TONGSUO_RAND_GM_SRNG +# ifdef CHARSET_EBCDIC +# define DRBG_DEFAULT_PERS_STRING { 0x54, 0x6f, 0x6e, 0x67, 0x73, 0x75, \ + 0x6f, 0x20, 0x47, 0x4d, 0x2f, 0x54, 0x20, 0x30, 0x31, 0x30, 0x35, 0x2d, \ + 0x32, 0x30, 0x32, 0x31, 0x20, 0x53, 0x52, 0x4e, 0x47, 0x00}; +# else +# define DRBG_DEFAULT_PERS_STRING "Tongsuo GM/T 0105-2021 SRNG" +# endif +#else +# ifdef CHARSET_EBCDIC +# define DRBG_DEFAULT_PERS_STRING { 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x53, \ 0x4c, 0x20, 0x4e, 0x49, 0x53, 0x54, 0x20, 0x53, 0x50, 0x20, 0x38, 0x30, \ 0x30, 0x2d, 0x39, 0x30, 0x41, 0x20, 0x44, 0x52, 0x42, 0x47, 0x00}; -#else -# define DRBG_DEFAULT_PERS_STRING "OpenSSL NIST SP 800-90A DRBG" +# else +# define DRBG_DEFAULT_PERS_STRING "OpenSSL NIST SP 800-90A DRBG" +# endif #endif typedef struct prov_drbg_st PROV_DRBG; diff --git a/providers/implementations/rands/seeding/rand_unix.c b/providers/implementations/rands/seeding/rand_unix.c index 6fb13195a..d9ca2616d 100644 --- a/providers/implementations/rands/seeding/rand_unix.c +++ b/providers/implementations/rands/seeding/rand_unix.c @@ -102,7 +102,8 @@ static uint64_t get_timer_bits(void); # undef OPENSSL_RAND_SEED_RDTSC # undef OPENSSL_RAND_SEED_RDCPU # undef OPENSSL_RAND_SEED_EGD -# undef OPENSSL_RAND_SEED_RTC +# undef OPENSSL_RAND_SEED_RTCODE +# undef OPENSSL_RAND_SEED_RTMEM #endif #if defined(OPENSSL_SYS_UEFI) && !defined(OPENSSL_RAND_SEED_NONE) @@ -606,8 +607,8 @@ void ossl_rand_pool_keep_random_devices_open(int keep) # endif /* defined(OPENSSL_RAND_SEED_DEVRANDOM) */ -# if defined(OPENSSL_RAND_SEED_RTC) -static size_t ossl_prov_acquire_entropy_from_rtc1(RAND_POOL *pool) +# if defined(OPENSSL_RAND_SEED_RTCODE) +static size_t ossl_prov_acquire_entropy_from_rtcode(RAND_POOL *pool) { size_t i, k, bytes_needed; struct timespec ts; @@ -635,8 +636,9 @@ static size_t ossl_prov_acquire_entropy_from_rtc1(RAND_POOL *pool) } return ossl_rand_pool_entropy_available(pool); } - -static size_t ossl_prov_acquire_entropy_from_rtc2(RAND_POOL *pool) +# endif +# if defined(OPENSSL_RAND_SEED_RTMEM) +static size_t ossl_prov_acquire_entropy_from_rtmem(RAND_POOL *pool) { size_t i, k, bytes_needed; struct timespec ts; @@ -804,12 +806,14 @@ size_t ossl_pool_acquire_entropy(RAND_POOL *pool) } # endif -# if defined(OPENSSL_RAND_SEED_RTC) - entropy_available = ossl_prov_acquire_entropy_from_rtc1(pool); +# if defined(OPENSSL_RAND_SEED_RTCODE) + entropy_available = ossl_prov_acquire_entropy_from_rtcode(pool); if (entropy_available > 0) return entropy_available; +# endif - entropy_available = ossl_prov_acquire_entropy_from_rtc2(pool); +# if defined(OPENSSL_RAND_SEED_RTMEM) + entropy_available = ossl_prov_acquire_entropy_from_rtmem(pool); if (entropy_available > 0) return entropy_available; # endif diff --git a/providers/implementations/rands/smtc_rng.c b/providers/implementations/rands/smtc_rng.c index e7c3aace0..f083f18be 100644 --- a/providers/implementations/rands/smtc_rng.c +++ b/providers/implementations/rands/smtc_rng.c @@ -28,6 +28,7 @@ typedef struct smtc_crng_test_global_st { CRYPTO_RWLOCK *lock; + EVP_MD_CTX *md_ctx; unsigned char last_bit; size_t cnt; } SMTC_CRNG_TEST_GLOBAL; @@ -40,11 +41,62 @@ static int get_bit(const unsigned char *buf, int m) return (buf[m / 8] << (m % 8) >> 7) & 1; } +/* Modified based on hash_df() in drbg_hash.c */ +static int sm3_df(EVP_MD_CTX *ctx, unsigned char *out, size_t outlen, + const unsigned char *in, size_t inlen) +{ + unsigned char vtmp[EVP_MAX_MD_SIZE]; + /* tmp = counter || num_bits_returned */ + unsigned char tmp[1 + 4]; + int tmp_sz = 0; + size_t blocklen = EVP_MD_get_size(EVP_sm3()); + size_t num_bits_returned = outlen * 8; + + /* counter = 1 (tmp[0] is the 8 bit counter) */ + tmp[tmp_sz++] = 1; + /* tmp[1..4] is the fixed 32 bit no_of_bits_to_return */ + tmp[tmp_sz++] = (unsigned char)((num_bits_returned >> 24) & 0xff); + tmp[tmp_sz++] = (unsigned char)((num_bits_returned >> 16) & 0xff); + tmp[tmp_sz++] = (unsigned char)((num_bits_returned >> 8) & 0xff); + tmp[tmp_sz++] = (unsigned char)(num_bits_returned & 0xff); + + for (;;) { + /* + * out = out || Hash(tmp || in) + * (where tmp = counter || num_bits_returned) + */ + if (!(EVP_DigestInit_ex(ctx, EVP_sm3(), NULL) + && EVP_DigestUpdate(ctx, tmp, tmp_sz) + && EVP_DigestUpdate(ctx, in, inlen))) + return 0; + + if (outlen < blocklen) { + if (!EVP_DigestFinal(ctx, vtmp, NULL)) + return 0; + memcpy(out, vtmp, outlen); + OPENSSL_cleanse(vtmp, blocklen); + break; + } else if(!EVP_DigestFinal(ctx, out, NULL)) { + return 0; + } + + outlen -= blocklen; + if (outlen == 0) + break; + + tmp[0]++; + out += blocklen; + } + + return 1; +} + static void rand_smtc_crng_ossl_ctx_free(void *vcrngt_glob) { SMTC_CRNG_TEST_GLOBAL *smtc_glob = vcrngt_glob; CRYPTO_THREAD_lock_free(smtc_glob->lock); + EVP_MD_CTX_free(smtc_glob->md_ctx); OPENSSL_free(smtc_glob); } @@ -55,6 +107,11 @@ static void *rand_smtc_crng_ossl_ctx_new(OSSL_LIB_CTX *ctx) if (smtc_glob == NULL) return NULL; + if ((smtc_glob->md_ctx = EVP_MD_CTX_new()) == NULL) { + OPENSSL_free(smtc_glob); + return NULL; + } + if ((smtc_glob->lock = CRYPTO_THREAD_lock_new()) == NULL) { OPENSSL_free(smtc_glob); return NULL; @@ -73,8 +130,7 @@ static const OSSL_LIB_CTX_METHOD rand_smtc_ossl_ctx_method = { * GM/T 0105-2021 Appendix D.2, Repeat Count Test */ static int smtc_rng_repeat_count_test(SMTC_CRNG_TEST_GLOBAL *crngt, - unsigned char *pout, size_t len, - OSSL_SELF_TEST *st) + unsigned char *pout, size_t len) { size_t i = 0; @@ -92,7 +148,7 @@ static int smtc_rng_repeat_count_test(SMTC_CRNG_TEST_GLOBAL *crngt, crngt->cnt++; if (crngt->cnt >= REPEAT_COUNT_TEST_THRESHOLD) { crngt->cnt = 0; - OSSL_SELF_TEST_oncorrupt_byte(st, &pout[i / 8]); + ossl_set_error_state(OSSL_SELF_TEST_TYPE_CRNG); return 0; } } else { @@ -108,14 +164,16 @@ size_t ossl_smtc_get_entropy(PROV_DRBG *drbg, unsigned char **pout, int entropy, size_t min_len, size_t max_len, int prediction_resistance) { - int crng_test_pass = 0; + unsigned char buf[CRNGT_BUFSIZ]; + int crng_test_pass = 1; OSSL_CALLBACK *stcb = NULL; void *stcbarg = NULL; + unsigned char *ent, *entp, *entbuf; + unsigned char *p = NULL; OSSL_SELF_TEST *st = NULL; - size_t ret - = ossl_prov_get_entropy(drbg->provctx, pout, entropy, min_len, max_len); - if (ret == 0) - return 0; + size_t bytes_needed; + size_t r = 0, s, t, n; + size_t ret; OSSL_LIB_CTX *libctx = ossl_prov_ctx_get0_libctx(drbg->provctx); SMTC_CRNG_TEST_GLOBAL *crngt_glob = ossl_lib_ctx_get_data( @@ -127,6 +185,21 @@ size_t ossl_smtc_get_entropy(PROV_DRBG *drbg, unsigned char **pout, int entropy, if (!CRYPTO_THREAD_write_lock(crngt_glob->lock)) return 0; + /* + * Calculate how many bytes of seed material we require, rounded up + * to the nearest byte. If the entropy is of less than full quality, + * the amount required should be scaled up appropriately here. + */ + bytes_needed = (entropy + 7) / 8; + if (bytes_needed < min_len) + bytes_needed = min_len; + if (bytes_needed > max_len) + goto unlock_return; + + entp = ent = OPENSSL_secure_malloc(bytes_needed); + if (ent == NULL) + goto unlock_return; + OSSL_SELF_TEST_get_callback(libctx, &stcb, &stcbarg); if (stcb != NULL) { st = OSSL_SELF_TEST_new(stcb, stcbarg); @@ -136,16 +209,51 @@ size_t ossl_smtc_get_entropy(PROV_DRBG *drbg, unsigned char **pout, int entropy, OSSL_SELF_TEST_DESC_RNG); } - if (!smtc_rng_repeat_count_test(crngt_glob, *pout, ret, st)) { - ret = 0; - goto err; - } + for (t = bytes_needed; t > 0;) { + /* Care needs to be taken to avoid overrunning the buffer */ + s = t >= CRNGT_BUFSIZ ? CRNGT_BUFSIZ : t; + entbuf = t >= CRNGT_BUFSIZ ? entp : buf; + + n = ossl_prov_get_entropy(drbg->provctx, &p, 0, CRNGT_BUFSIZ, + CRNGT_BUFSIZ); + if (n == CRNGT_BUFSIZ) { + if (OSSL_SELF_TEST_oncorrupt_byte(st, p)) + memset(p, 0, n); + + if (!smtc_rng_repeat_count_test(crngt_glob, p, n)) { + crng_test_pass = 0; + goto err; + } + + if (!sm3_df(crngt_glob->md_ctx, entbuf, CRNGT_BUFSIZ, p, + CRNGT_BUFSIZ)) + goto err; - crng_test_pass = 1; + ossl_prov_cleanup_entropy(drbg->provctx, p, n); + } + + if (n != 0) { + ossl_prov_cleanup_entropy(drbg->provctx, p, n); + p = NULL; + goto err; + } -err: + if (t < CRNGT_BUFSIZ) + memcpy(entp, buf, t); + + entp += s; + t -= s; + } + r = bytes_needed; + *pout = ent; + ent = NULL; + + err: OSSL_SELF_TEST_onend(st, crng_test_pass); OSSL_SELF_TEST_free(st); + OPENSSL_secure_clear_free(ent, bytes_needed); + + unlock_return: CRYPTO_THREAD_unlock(crngt_glob->lock); - return ret; + return r; } diff --git a/providers/prov_running.c b/providers/prov_running.c index 379fd5d25..e51b7024f 100644 --- a/providers/prov_running.c +++ b/providers/prov_running.c @@ -10,6 +10,7 @@ #include #include "prov/providercommon.h" +#ifndef SMTC_MODULE /* By default, our providers don't have an error state */ void ossl_set_error_state(const char *type) { @@ -20,3 +21,4 @@ int ossl_prov_is_running(void) { return 1; } +#endif diff --git a/providers/smtc/self_test.c b/providers/smtc/self_test.c index 76e90ca3f..3d09424a3 100644 --- a/providers/smtc/self_test.c +++ b/providers/smtc/self_test.c @@ -14,6 +14,7 @@ #include #include "internal/cryptlib.h" #include +#include #include #include "crypto/evp.h" #include "internal/e_os.h" @@ -29,14 +30,12 @@ /* The size of a temp buffer used to read in data */ #define INTEGRITY_BUF_SIZE (4096) -#define MAX_MD_SIZE 64 -#define MAC_NAME "HMAC" -#define DIGEST_NAME "SM3" +static int SMTC_conditional_error_check = 1; static CRYPTO_RWLOCK *self_test_lock = NULL; static CRYPTO_RWLOCK *smtc_state_lock = NULL; static int smtc_state = SMTC_STATE_INIT; -static unsigned char fixed_key[32] = { SMTC_KEY_ELEMENTS }; +static unsigned char pubkey[] = SMTC_KEY_STRING; static CRYPTO_ONCE smtc_self_test_init = CRYPTO_ONCE_STATIC_INIT; DEFINE_RUN_ONCE_STATIC(do_smtc_self_test_init) @@ -52,7 +51,7 @@ DEFINE_RUN_ONCE_STATIC(do_smtc_self_test_init) } /* - * Calculate the HMAC SM3 of data read using a BIO and read_cb, and verify + * Verify the signatre(SM2withSM3) of data read using a BIO and read_cb, and verify * the result matches the expected value. * Return 1 if verified, or 0 if it fails. */ @@ -62,47 +61,49 @@ static int verify_integrity(OSSL_CORE_BIO *bio, OSSL_FUNC_BIO_read_ex_fn read_ex const char *event_type) { int ret = 0, status; - unsigned char out[MAX_MD_SIZE]; + BIO *pkey_bio = NULL; unsigned char buf[INTEGRITY_BUF_SIZE]; - size_t bytes_read = 0, out_len = 0; - EVP_MAC *mac = NULL; - EVP_MAC_CTX *ctx = NULL; - OSSL_PARAM params[2], *p = params; + size_t bytes_read = 0; + EVP_MD_CTX *mctx = NULL; + EVP_PKEY *pkey = NULL; - OSSL_SELF_TEST_onbegin(ev, event_type, OSSL_SELF_TEST_DESC_INTEGRITY_HMAC); + OSSL_SELF_TEST_onbegin(ev, event_type, + OSSL_SELF_TEST_DESC_INTEGRITY_VERIFY); - mac = EVP_MAC_fetch(libctx, MAC_NAME, NULL); - if (mac == NULL) + pkey_bio = BIO_new_mem_buf(pubkey, sizeof(pubkey)); + if (pkey_bio == NULL) goto err; - ctx = EVP_MAC_CTX_new(mac); - if (ctx == NULL) + + pkey = PEM_read_bio_PUBKEY_ex(pkey_bio, NULL, NULL, NULL, libctx, NULL); + if (pkey == NULL) goto err; - *p++ = OSSL_PARAM_construct_utf8_string("digest", DIGEST_NAME, 0); - *p = OSSL_PARAM_construct_end(); + mctx = EVP_MD_CTX_new(); + if (mctx == NULL) + goto err; - if (!EVP_MAC_init(ctx, fixed_key, sizeof(fixed_key), params)) + if (EVP_DigestVerifyInit(mctx, NULL, EVP_sm3(), NULL, pkey) != 1) goto err; while (1) { status = read_ex_cb(bio, buf, sizeof(buf), &bytes_read); if (status != 1) break; - if (!EVP_MAC_update(ctx, buf, bytes_read)) + if (EVP_DigestVerifyUpdate(mctx, buf, bytes_read) != 1) goto err; } - if (!EVP_MAC_final(ctx, out, &out_len, sizeof(out))) - goto err; - OSSL_SELF_TEST_oncorrupt_byte(ev, out); - if (expected_len != out_len - || memcmp(expected, out, out_len) != 0) + OSSL_SELF_TEST_oncorrupt_byte(ev, expected); + + if (EVP_DigestVerifyFinal(mctx, expected, expected_len) != 1) goto err; + ret = 1; err: + BIO_free(pkey_bio); + EVP_PKEY_free(pkey); + EVP_MD_CTX_free(mctx); OSSL_SELF_TEST_onend(ev, ret); - EVP_MAC_CTX_free(ctx); - EVP_MAC_free(mac); return ret; } @@ -132,8 +133,10 @@ static int verify_password(OSSL_LIB_CTX *libctx, unsigned char *password, || !EVP_DigestFinal_ex(mctx, buf, NULL)) goto end; - if (memcmp(buf, password, pass_len)) + if (memcmp(buf, password, pass_len)) { + ossl_sleep(1000); goto end; + } ret = 1; end: @@ -177,7 +180,7 @@ static int get_bit(const unsigned char *buf, int m) static int ossl_smtc_rng_poweron_test(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) { int res = 0, i; - int W = 1024, C = 670, cnt; + int W = 1024, C = 664, cnt; unsigned char buf[W / 8]; size_t left = sizeof(buf); size_t len, entropy_len; @@ -244,10 +247,10 @@ int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test) { int ok = 0; int loclstate; - long checksum_len; + long siglen; long pass_len, salt_len; OSSL_CORE_BIO *bio_module = NULL; - unsigned char *module_checksum = NULL; + unsigned char *module_sig = NULL; unsigned char *password = NULL, *salt = NULL; OSSL_SELF_TEST *ev = NULL; @@ -285,25 +288,24 @@ int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test) goto end; #ifndef OPENSSL_NO_SMTC_DEBUG - if (st->verify_mac == NULL || atoi(st->verify_mac) != 0) + if (st->verify_sig == NULL || atoi(st->verify_sig) != 0) #endif { - if (st->module_filename == NULL || st->module_checksum_data == NULL) { + if (st->module_filename == NULL || st->module_sig == NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_CONFIG_DATA); goto end; } bio_module = ossl_prov_bio_new_file(st->module_filename, "rb"); - module_checksum = OPENSSL_hexstr2buf(st->module_checksum_data, - &checksum_len); - if (bio_module == NULL || module_checksum == NULL) { + module_sig = OPENSSL_hexstr2buf(st->module_sig, &siglen); + if (bio_module == NULL || module_sig == NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CONFIG_DATA); goto end; } - if (!verify_integrity(bio_module, ossl_prov_bio_read_ex, - module_checksum, checksum_len, st->libctx, - ev, OSSL_SELF_TEST_TYPE_MODULE_INTEGRITY)) { + if (!verify_integrity(bio_module, ossl_prov_bio_read_ex, module_sig, + siglen, st->libctx, ev, + OSSL_SELF_TEST_TYPE_MODULE_INTEGRITY)) { ERR_raise(ERR_LIB_PROV, PROV_R_MODULE_INTEGRITY_FAILURE); goto end; } @@ -352,14 +354,14 @@ int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test) } if (!verify_password(st->libctx, password, pass_len, salt, salt_len)) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CONFIG_DATA); + ERR_raise(ERR_LIB_PROV, PROV_R_INCORRECT_PASSWORD); goto end; } } ok = 1; end: OSSL_SELF_TEST_free(ev); - OPENSSL_free(module_checksum); + OPENSSL_free(module_sig); if (st != NULL) ossl_prov_bio_free(bio_module); @@ -373,7 +375,25 @@ int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test) return ok; } -int smtc_prov_is_running(void) +void SELF_TEST_disable_conditional_error_state(void) +{ + SMTC_conditional_error_check = 0; +} + + +void ossl_set_error_state(const char *type) +{ + int cond_test = (type != NULL && strcmp(type, OSSL_SELF_TEST_TYPE_PCT) == 0); + + if (!cond_test || (SMTC_conditional_error_check == 1)) { + smtc_set_state(SMTC_STATE_ERROR); + ERR_raise(ERR_LIB_PROV, PROV_R_FIPS_MODULE_ENTERING_ERROR_STATE); + } else { + ERR_raise(ERR_LIB_PROV, PROV_R_FIPS_MODULE_CONDITIONAL_ERROR); + } +} + +int ossl_prov_is_running(void) { int res; diff --git a/providers/smtc/self_test.h b/providers/smtc/self_test.h index 3001fa92b..f45eff52f 100644 --- a/providers/smtc/self_test.h +++ b/providers/smtc/self_test.h @@ -19,7 +19,7 @@ typedef struct self_test_post_params_st { const char *module_filename; /* Module file to perform MAC on */ - const char *module_checksum_data; /* Expected module MAC integrity */ + const char *module_sig; /* Signature of module */ const char *show_selftest; /* Output selftest results */ const char *admin_pass; /* Admin password */ const char *admin_salt; /* Salt of password */ @@ -27,7 +27,7 @@ typedef struct self_test_post_params_st { const char *rng_continuous_test; /* 熵源连续健康测试 */ const char *randomness_poweron_test; /* 随机数上电自检 */ #ifndef OPENSSL_NO_SMTC_DEBUG - const char *verify_mac; + const char *verify_sig; const char *verify_pass; #endif diff --git a/providers/smtc/self_test_data.inc b/providers/smtc/self_test_data.inc index be618233b..02183a432 100644 --- a/providers/smtc/self_test_data.inc +++ b/providers/smtc/self_test_data.inc @@ -105,7 +105,10 @@ typedef struct st_kat_sign_st { const char *desc; const char *algorithm; const char *mdalgorithm; + int sign; const ST_KAT_PARAM *key; + const unsigned char *dgst; + size_t dgst_len; const unsigned char *sig_expected; /* Set to NULL if this value changes */ size_t sig_expected_len; } ST_KAT_SIGN; @@ -703,6 +706,21 @@ static const ST_KAT_PARAM sm2_key[] = { ST_KAT_PARAM_OCTET(OSSL_PKEY_PARAM_PUB_KEY, sm2_pub), ST_KAT_PARAM_END() }; + +static const unsigned char dgst[] = { + 0xD7, 0xAD, 0x39, 0x7F, 0x6F, 0xFA, 0x5D, 0x4F, 0x7F, 0x11, 0xE7, 0x21, + 0x7F, 0x24, 0x16, 0x07, 0xDC, 0x30, 0x61, 0x8C, 0x23, 0x6D, 0x2C, 0x09, + 0xC1, 0xB9, 0xEA, 0x8F, 0xDA, 0xDE, 0xE2, 0xE8, +}; + +static const unsigned char sig_expected[] = { + 0x30, 0x46, 0x02, 0x21, 0x00, 0xAB, 0x1D, 0xB6, 0x4D, 0xE7, 0xC4, 0x0E, + 0xDB, 0xDE, 0x66, 0x51, 0xC9, 0xB8, 0xEB, 0xDB, 0x80, 0x46, 0x73, 0xDB, + 0x83, 0x6E, 0x5D, 0x5C, 0x7F, 0xE1, 0x5D, 0xCF, 0x9E, 0xD2, 0x72, 0x50, + 0x37, 0x02, 0x21, 0x00, 0xEB, 0xA7, 0x14, 0x45, 0x1F, 0xF6, 0x9B, 0x0B, + 0xB9, 0x30, 0xB3, 0x79, 0xE1, 0x92, 0xE7, 0xCD, 0x5F, 0xA6, 0xE3, 0xC4, + 0x1C, 0x7F, 0xBD, 0x83, 0x03, 0xB7, 0x99, 0xAB, 0x54, 0xA5, 0x46, 0x21, +}; #endif static const unsigned char sm2_asym_plaintext_encrypt[] = { @@ -729,15 +747,26 @@ static const unsigned char sm2_asym_expected_encrypt[] = { static const ST_KAT_SIGN st_kat_sign_tests[] = { #ifndef OPENSSL_NO_SM2 { - OSSL_SELF_TEST_DESC_SIGN_SM2, + OSSL_SELF_TEST_DESC_SIGN_SM2_SIGN, "SM2", "SM3", + 1, sm2_key, + ITM(dgst), /* * The SM2 signature changes each time due to it using a random k. * So there is no expected KAT for this case. */ }, + { + OSSL_SELF_TEST_DESC_SIGN_SM2_VERIFY, + "SM2", + "SM3", + 0, + sm2_pub_key, + ITM(dgst), + ITM(sig_expected), + }, #endif }; @@ -747,7 +776,7 @@ static const ST_KAT_ASYM_CIPHER st_kat_asym_cipher_tests[] = { OSSL_SELF_TEST_DESC_ASYM_SM2_ENC, "SM2", 1, - sm2_pub_key, + sm2_key, sm2_enc_params, ITM(sm2_asym_plaintext_encrypt), /* diff --git a/providers/smtc/self_test_kats.c b/providers/smtc/self_test_kats.c index 4c4c95177..c13414b28 100644 --- a/providers/smtc/self_test_kats.c +++ b/providers/smtc/self_test_kats.c @@ -369,11 +369,6 @@ static int self_test_sign(const ST_KAT_SIGN *t, unsigned char sig[256]; BN_CTX *bnctx = NULL; size_t siglen = sizeof(sig); - static const unsigned char dgst[] = { - 0x7f, 0x83, 0xb1, 0x65, 0x7f, 0xf1, 0xfc, 0x53, 0xb9, 0x2d, 0xc1, 0x81, - 0x48, 0xa1, 0xd6, 0x5d, 0xfc, 0x2d, 0x4b, 0x1f, 0xa3, 0xd6, 0x77, 0x28, - 0x4a, 0xdd, 0xd2, 0x00, 0x12, 0x6d, 0x90, 0x69 - }; const char *typ = OSSL_SELF_TEST_TYPE_KAT_SIGNATURE; if (t->sig_expected == NULL) @@ -393,7 +388,7 @@ static int self_test_sign(const ST_KAT_SIGN *t, goto err; params = OSSL_PARAM_BLD_to_param(bld); - /* Create a EVP_PKEY_CTX to load the DSA key into */ + /* Create a EVP_PKEY_CTX to load the key into */ kctx = EVP_PKEY_CTX_new_from_name(libctx, t->algorithm, ""); if (kctx == NULL || params == NULL) goto err; @@ -403,8 +398,7 @@ static int self_test_sign(const ST_KAT_SIGN *t, /* Create a EVP_PKEY_CTX to use for the signing operation */ sctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, NULL); - if (sctx == NULL - || EVP_PKEY_sign_init(sctx) <= 0) + if (sctx == NULL) goto err; /* set signature parameters */ @@ -412,27 +406,42 @@ static int self_test_sign(const ST_KAT_SIGN *t, t->mdalgorithm, strlen(t->mdalgorithm) + 1)) goto err; + params_sig = OSSL_PARAM_BLD_to_param(bld); - if (EVP_PKEY_CTX_set_params(sctx, params_sig) <= 0) + if (params_sig == NULL) goto err; - if (EVP_PKEY_sign(sctx, sig, &siglen, dgst, sizeof(dgst)) <= 0 - || EVP_PKEY_verify_init(sctx) <= 0 + if (t->sign) { + if (EVP_PKEY_sign_init(sctx) <= 0) + goto err; + + if (EVP_PKEY_CTX_set_params(sctx, params_sig) <= 0) + goto err; + + if (EVP_PKEY_sign(sctx, sig, &siglen, t->dgst, t->dgst_len) <= 0) + goto err; + + OSSL_SELF_TEST_oncorrupt_byte(st, sig); + + if (t->sig_expected != NULL + && (siglen != t->sig_expected_len + || memcmp(sig, t->sig_expected, t->sig_expected_len) != 0)) + goto err; + } + + if (EVP_PKEY_verify_init(sctx) <= 0 || EVP_PKEY_CTX_set_params(sctx, params_sig) <= 0) goto err; - /* - * Used by RSA, for other key types where the signature changes, we - * can only use the verify. - */ - if (t->sig_expected != NULL - && (siglen != t->sig_expected_len - || memcmp(sig, t->sig_expected, t->sig_expected_len) != 0)) - goto err; + if (!t->sign) { + memcpy(sig, t->sig_expected, t->sig_expected_len); + siglen = t->sig_expected_len; + } OSSL_SELF_TEST_oncorrupt_byte(st, sig); - if (EVP_PKEY_verify(sctx, sig, siglen, dgst, sizeof(dgst)) <= 0) + if (EVP_PKEY_verify(sctx, sig, siglen, t->dgst, t->dgst_len) <= 0) goto err; + ret = 1; err: BN_CTX_free(bnctx); @@ -483,13 +492,6 @@ static int self_test_asym_cipher(const ST_KAT_ASYM_CIPHER *t, OSSL_SELF_TEST *st || EVP_PKEY_fromdata(keyctx, &key, EVP_PKEY_KEYPAIR, keyparams) <= 0) goto err; - /* Create a EVP_PKEY_CTX to use for the encrypt or decrypt operation */ - encctx = EVP_PKEY_CTX_new_from_pkey(libctx, key, NULL); - if (encctx == NULL - || (t->encrypt && EVP_PKEY_encrypt_init(encctx) <= 0) - || (!t->encrypt && EVP_PKEY_decrypt_init(encctx) <= 0)) - goto err; - /* Add any additional parameters such as padding */ if (t->postinit != NULL) { initbld = OSSL_PARAM_BLD_new(); @@ -500,19 +502,46 @@ static int self_test_asym_cipher(const ST_KAT_ASYM_CIPHER *t, OSSL_SELF_TEST *st initparams = OSSL_PARAM_BLD_to_param(initbld); if (initparams == NULL) goto err; - if (EVP_PKEY_CTX_set_params(encctx, initparams) <= 0) + } + /* Create a EVP_PKEY_CTX to use for the encrypt or decrypt operation */ + encctx = EVP_PKEY_CTX_new_from_pkey(libctx, key, NULL); + if (encctx == NULL) + goto err; + + if (t->encrypt) { + if (EVP_PKEY_encrypt_init(encctx) <= 0 + || EVP_PKEY_CTX_set_params(encctx, initparams) <= 0 + || EVP_PKEY_encrypt(encctx, out, &outlen, t->in, t->in_len) <= 0) + goto err; + + OSSL_SELF_TEST_oncorrupt_byte(st, out); + if (t->expected != NULL + && (outlen != t->expected_len + || memcmp(out, t->expected, t->expected_len) != 0)) goto err; } + if (EVP_PKEY_decrypt_init(encctx) <= 0 + || EVP_PKEY_CTX_set_params(encctx, initparams) <= 0) + goto err; + if (t->encrypt) { - if (EVP_PKEY_encrypt(encctx, out, &outlen, - t->in, t->in_len) <= 0) + unsigned char out2[256]; + size_t outlen2; + + memcpy(out2, out, outlen); + outlen2 = outlen; + outlen = sizeof(out); + + if (EVP_PKEY_decrypt(encctx, out, &outlen, + out2, outlen2) <= 0) goto err; } else { if (EVP_PKEY_decrypt(encctx, out, &outlen, t->in, t->in_len) <= 0) goto err; } + /* Check the KAT */ OSSL_SELF_TEST_oncorrupt_byte(st, out); if (t->expected != NULL diff --git a/providers/smtc/smtckey.h.in b/providers/smtc/smtckey.h.in index a6e30ed7a..d44e62ba4 100644 --- a/providers/smtc/smtckey.h.in +++ b/providers/smtc/smtckey.h.in @@ -1,7 +1,7 @@ /* * {- join("\n * ", @autowarntext) -} * - * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved. + * Copyright 2023-2024 The Tongsuo 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 @@ -9,10 +9,4 @@ * https://github.com/Tongsuo-Project/Tongsuo/blob/master/LICENSE.txt */ -/* - * The SMTC validation HMAC key, usable as an array initializer. - */ -#define SMTC_KEY_ELEMENTS \ - {- join(', ', map { "0x$_" } unpack("(A2)*", $config{SMTCKEY})) -} - -#define SMTC_KEY_STRING "{- $config{SMTCKEY} -}" +#define SMTC_KEY_STRING "{- $config{SMTCPUBKEY} -}" diff --git a/providers/smtc/smtcprov.c b/providers/smtc/smtcprov.c index db5a92398..7112b9a8e 100644 --- a/providers/smtc/smtcprov.c +++ b/providers/smtc/smtcprov.c @@ -25,6 +25,13 @@ #include "internal/core.h" #include "internal/smtc_names.h" + +/* From GM/T 0105-2021 (Sec 6) */ +#define L1_RESEED_INTERVAL (1 << 20) +#define L1_RESEED_TIME_INTERVAL (10 * 60) /* 10 minutes */ +#define L2_RESEED_INTERVAL (1 << 10) +#define L2_RESEED_TIME_INTERVAL (60) /* 1 minute */ + /* * Forward declarations to ensure that interface functions are correctly * defined. @@ -98,9 +105,9 @@ static int smtc_get_params_from_core(SMTC_GLOBAL *fgbl) (char **)&fgbl->selftest_params.module_filename, sizeof(fgbl->selftest_params.module_filename)); *p++ = OSSL_PARAM_construct_utf8_ptr( - OSSL_PROV_SMTC_PARAM_MODULE_MAC, - (char **)&fgbl->selftest_params.module_checksum_data, - sizeof(fgbl->selftest_params.module_checksum_data)); + OSSL_PROV_SMTC_PARAM_MODULE_SIG, + (char **)&fgbl->selftest_params.module_sig, + sizeof(fgbl->selftest_params.module_sig)); *p++ = OSSL_PARAM_construct_utf8_ptr( OSSL_PROV_SMTC_PARAM_SHOW_SELFTEST, (char **)&fgbl->selftest_params.show_selftest, @@ -127,9 +134,9 @@ static int smtc_get_params_from_core(SMTC_GLOBAL *fgbl) sizeof(fgbl->selftest_params.randomness_poweron_test)); #ifndef OPENSSL_NO_SMTC_DEBUG *p++ = OSSL_PARAM_construct_utf8_ptr( - OSSL_PROV_SMTC_PARAM_MODULE_VERIFY_MAC, - (char **)&fgbl->selftest_params.verify_mac, - sizeof(fgbl->selftest_params.verify_mac)); + OSSL_PROV_SMTC_PARAM_MODULE_VERIFY_SIG, + (char **)&fgbl->selftest_params.verify_sig, + sizeof(fgbl->selftest_params.verify_sig)); *p++ = OSSL_PARAM_construct_utf8_ptr( OSSL_PROV_SMTC_PARAM_MODULE_VERIFY_PASS, (char **)&fgbl->selftest_params.verify_pass, @@ -164,7 +171,7 @@ static int smtc_get_params(void *provctx, OSSL_PARAM params[]) if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, TONGSUO_FULL_VERSION_STR)) return 0; p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_STATUS); - if (p != NULL && !OSSL_PARAM_set_int(p, smtc_prov_is_running())) + if (p != NULL && !OSSL_PARAM_set_int(p, ossl_prov_is_running())) return 0; return 1; } @@ -286,8 +293,13 @@ static const OSSL_ALGORITHM smtc_digests[] = { static const OSSL_ALGORITHM_CAPABLE smtc_ciphers[] = { #ifndef OPENSSL_NO_SM4 + ALG(PROV_NAMES_SM4_ECB, ossl_sm4128ecb_functions), ALG(PROV_NAMES_SM4_CBC, ossl_sm4128cbc_functions), + ALG(PROV_NAMES_SM4_CFB, ossl_sm4128cfb128_functions), + ALG(PROV_NAMES_SM4_OFB, ossl_sm4128ofb128_functions), + ALG(PROV_NAMES_SM4_CTR, ossl_sm4128ctr_functions), ALG(PROV_NAMES_SM4_GCM, ossl_sm4128gcm_functions), + ALG(PROV_NAMES_SM4_CCM, ossl_sm4128ccm_functions), #endif /* OPENSSL_NO_SM4 */ {{NULL, NULL, NULL}, NULL}}; @@ -307,6 +319,7 @@ static const OSSL_ALGORITHM smtc_kdfs[] = { static const OSSL_ALGORITHM smtc_rands[] = { { PROV_NAMES_HASH_DRBG, "provider=smtc", ossl_drbg_hash_functions }, + { PROV_NAMES_SEED_SRC, "provider=smtc", ossl_seed_src_functions }, { PROV_NAMES_TEST_RAND, "provider=smtc", ossl_test_rng_functions }, { NULL, NULL, NULL } }; @@ -396,20 +409,28 @@ static const OSSL_ALGORITHM *smtc_query(void *provctx, int operation_id, return NULL; } +static void smtc_teardown(void *provctx) +{ + BIO_free(bio_err); + BIO_meth_free(ossl_prov_ctx_get0_core_bio_method(provctx)); + OSSL_LIB_CTX_free(PROV_LIBCTX_OF(provctx)); + ossl_prov_ctx_free(provctx); +} + static void smtc_intern_teardown(void *provctx) { BIO_free(bio_err); + BIO_meth_free(ossl_prov_ctx_get0_core_bio_method(provctx)); /* * We know that the library context is the same as for the outer provider, * so no need to destroy it here. */ - BIO_meth_free(ossl_prov_ctx_get0_core_bio_method(provctx)); ossl_prov_ctx_free(provctx); } /* Functions we provide to the core */ static const OSSL_DISPATCH smtc_dispatch_table[] = { - { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))smtc_intern_teardown }, + { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))smtc_teardown }, { OSSL_FUNC_PROVIDER_GETTABLE_PARAMS, (void (*)(void))smtc_gettable_params }, { OSSL_FUNC_PROVIDER_GET_PARAMS, (void (*)(void))smtc_get_params }, { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))smtc_query }, @@ -419,6 +440,58 @@ static const OSSL_DISPATCH smtc_dispatch_table[] = { { 0, NULL } }; +/* Functions we provide to ourself */ +static const OSSL_DISPATCH intern_dispatch_table[] = { + { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))smtc_intern_teardown }, + { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))smtc_query }, + { 0, NULL } +}; + +/* + * The internal init function used when the SMTC module uses EVP to call + * another algorithm also in the SMTC module. This is a recursive call that has + * been made from within the SMTC module itself. To make this work, we populate + * the provider context of this inner instance with the same library context + * that was used in the EVP call that initiated this recursive call. + */ +OSSL_provider_init_fn ossl_smtc_intern_provider_init; +int ossl_smtc_intern_provider_init(const OSSL_CORE_HANDLE *handle, + const OSSL_DISPATCH *in, + const OSSL_DISPATCH **out, + void **provctx) +{ + OSSL_FUNC_core_get_libctx_fn *c_internal_get_libctx = NULL; + + for (; in->function_id != 0; in++) { + switch (in->function_id) { + case OSSL_FUNC_CORE_GET_LIBCTX: + c_internal_get_libctx = OSSL_FUNC_core_get_libctx(in); + break; + default: + break; + } + } + + if (c_internal_get_libctx == NULL) + return 0; + + if ((*provctx = ossl_prov_ctx_new()) == NULL) + return 0; + + /* + * Using the parent library context only works because we are a built-in + * internal provider. This is not something that most providers would be + * able to do. + */ + ossl_prov_ctx_set0_libctx(*provctx, + (OSSL_LIB_CTX *)c_internal_get_libctx(handle)); + ossl_prov_ctx_set0_handle(*provctx, handle); + + *out = intern_dispatch_table; + return 1; +} + +OSSL_provider_init_fn OSSL_provider_init_int; int OSSL_provider_init_int(const OSSL_CORE_HANDLE *handle, const OSSL_DISPATCH *in, const OSSL_DISPATCH **out, @@ -430,6 +503,10 @@ int OSSL_provider_init_int(const OSSL_CORE_HANDLE *handle, OSSL_LIB_CTX *libctx = NULL; OSSL_FUNC_core_get_libctx_fn *c_internal_get_libctx = NULL; SELF_TEST_POST_PARAMS selftest_params; + EVP_RAND_CTX *pub_drbg, *pri_drbg; + unsigned int reseed_interval = L2_RESEED_INTERVAL; + time_t reseed_time_interval = L2_RESEED_TIME_INTERVAL; + OSSL_PARAM params[3]; memset(&selftest_params, 0, sizeof(selftest_params)); @@ -466,12 +543,11 @@ int OSSL_provider_init_int(const OSSL_CORE_HANDLE *handle, if (ret != 1) return 0; - if ((*provctx = ossl_prov_ctx_new()) == NULL - || (corebiometh = ossl_bio_prov_init_bio_method()) == NULL) { - ossl_prov_ctx_free(*provctx); - *provctx = NULL; + if ((*provctx = ossl_prov_ctx_new()) == NULL) return 0; - } + + if ((corebiometh = ossl_bio_prov_init_bio_method()) == NULL) + goto err; if ((fgbl = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_SMTC_PROV_INDEX, &smtc_prov_ossl_ctx_method)) == NULL) @@ -494,15 +570,41 @@ int OSSL_provider_init_int(const OSSL_CORE_HANDLE *handle, goto err; } + ossl_prov_cache_exported_algorithms(smtc_ciphers, exported_ciphers); + + if (!SELF_TEST_post(&fgbl->selftest_params, 0)) { + ERR_raise(ERR_LIB_PROV, PROV_R_SELF_TEST_POST_FAILURE); + goto err; + } + + pub_drbg = RAND_get0_public(libctx); + if (pub_drbg == NULL) + goto err; + + pri_drbg = RAND_get0_private(libctx); + if (pri_drbg == NULL) + goto err; + + params[0] = OSSL_PARAM_construct_uint(OSSL_DRBG_PARAM_RESEED_REQUESTS, + &reseed_interval); + params[1] = OSSL_PARAM_construct_time_t(OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL, + &reseed_time_interval); + params[2] = OSSL_PARAM_construct_end(); + + if (!EVP_RAND_CTX_set_params(pub_drbg, params) + || !EVP_RAND_CTX_set_params(pri_drbg, params)) + goto err; + ossl_prov_ctx_set0_libctx(*provctx, libctx); ossl_prov_ctx_set0_handle(*provctx, handle); ossl_prov_ctx_set0_core_bio_method(*provctx, corebiometh); *out = smtc_dispatch_table; - ossl_prov_cache_exported_algorithms(smtc_ciphers, exported_ciphers); + return 1; err: - smtc_intern_teardown(*provctx); + BIO_meth_free(corebiometh); + smtc_teardown(*provctx); *provctx = NULL; OSSL_LIB_CTX_free(libctx); return 0;