From fa48fc7bfdf8ac16e77c381b356ab47950b9e2ce Mon Sep 17 00:00:00 2001 From: K1 Date: Wed, 28 Feb 2024 16:54:10 +0800 Subject: [PATCH] =?UTF-8?q?SMTC=E6=94=B9=E8=BF=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 根据GM/T 0105-2021设置参数值. 完整性验证机制采用SM2签名. SMTC随机数获取熵后,使用扩展函数sm3_df(). rand app supports get entropy from specified source. Rename rtc1 to rtcode, rtc2 to rtmem. Support acquiring entropy from specified entropy source. imporve self_test_drbg, test instantiate, reseed and generate. Support atf-slibce engine. --- Configure | 41 +- apps/mod.c | 423 +++++++++++------- apps/openssl.c | 115 +++-- apps/rand.c | 66 ++- crypto/ec/ec_key.c | 2 +- crypto/err/openssl.txt | 4 +- crypto/info.c | 10 +- crypto/provider_core.c | 1 + crypto/provider_predefined.c | 13 +- crypto/rand/prov_seed.c | 28 ++ crypto/rand/rand_lib.c | 5 + crypto/rand/rand_pool.c | 8 + crypto/trace.c | 5 +- crypto/tsapi/tsapi_lib.c | 148 ++++++ include/crypto/rand.h | 15 + include/crypto/rand_pool.h | 23 +- include/internal/cryptlib.h | 4 + include/internal/smtc_names.h | 18 +- include/openssl/core_dispatch.h | 3 + include/openssl/proverr.h | 3 +- include/openssl/rand.h | 1 + include/openssl/self_test.h | 3 + include/openssl/trace.h | 3 +- include/openssl/tsapi.h | 32 ++ providers/build.info | 1 - providers/common/include/prov/provider_util.h | 8 +- providers/common/provider_err.c | 4 +- providers/implementations/rands/drbg_hash.c | 18 +- providers/implementations/rands/drbg_local.h | 32 +- .../implementations/rands/seeding/rand_unix.c | 113 ++++- .../implementations/rands/seeding/rand_win.c | 110 ++--- providers/implementations/rands/smtc_rng.c | 165 +++++-- providers/prov_running.c | 2 + providers/smtc/self_test.c | 400 +++++++++++------ providers/smtc/self_test.h | 16 +- providers/smtc/self_test_data.inc | 116 ++++- providers/smtc/self_test_kats.c | 121 +++-- providers/smtc/smtckey.h.in | 11 +- providers/smtc/smtcprov.c | 233 ++++++++-- util/libcrypto.num | 1 + 40 files changed, 1732 insertions(+), 593 deletions(-) create mode 100644 crypto/tsapi/tsapi_lib.c create mode 100644 include/openssl/tsapi.h diff --git a/Configure b/Configure index ce92fd517..3de2cbc61 100755 --- a/Configure +++ b/Configure @@ -271,9 +271,14 @@ $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{SMTCPASSWD} = 'TSsmtc0028'; +$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; @@ -404,6 +409,7 @@ my @dtls = qw(dtls1 dtls1_2); my @disablables = ( "acvp-tests", "afalgeng", + "atf_slibce", "asan", "asm", "async", @@ -588,8 +594,9 @@ our %disabled = ( # "what" => "comment" "zkp-gadget" => "default", "zkp-transcript" => "default", "bn-method" => "default", - "smtc" => "default", - "smtc-debug" => "default", + "smtc" => "default", + "smtc-debug" => "default", + "atf_slibce" => "default", ); # Note: => pair form used for aesthetics, not to truly make a hash table @@ -796,7 +803,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 rtsock); my @seed_sources = (); while (@argvcopy) { @@ -1021,15 +1028,21 @@ 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 (/^--smtc-passwd=(.*)$/) + { + $user{SMTCPASSWD} = $1; + die "Invalid character in SMTC password (A-Z, a-z, 0-9)\n" + if $user{SMTCPASSWD} =~ /[^A-Za-z0-9]/; + die "Invalid SMTC password length (8 ~ 64 bytes)\n" + if length $1 < 8 or length $1 > 64; } elsif (/^--banner=(.*)$/) { diff --git a/apps/mod.c b/apps/mod.c index 65cf4220e..a87a91636 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 @@ -19,22 +20,20 @@ #include #include #include "internal/smtc_names.h" +#include "internal/cryptlib.h" #include "../providers/smtc/smtckey.h" -#define PASSWD_BUF_SIZE 1024 -#define BUFSIZE 4096 +#define BUFSIZE 4096 +#define SMTC_AUTH_PASSWD_MAX_LEN 64 +#define SMTC_AUTH_KEY_LEN 64 +#define SMTC_AUTH_SALT_LEN 64 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 { @@ -42,14 +41,16 @@ typedef enum OPTION_choice { OPT_EOF = 0, OPT_HELP, OPT_TEST, + OPT_RESET, OPT_MODULE, OPT_PROV_NAME, OPT_SECTION_NAME, - OPT_OUT, + OPT_SIGFILE, + OPT_NEW, + OPT_KEK, + OPT_ENGINE, OPT_SHOW_SELFTEST, -#ifndef OPENSSL_NO_SMTC_DEBUG - OPT_NO_PASS, -#endif + OPT_PASS, OPT_R_ENUM } OPTION_CHOICE; @@ -57,67 +58,103 @@ const OPTIONS mod_options[] = { OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, {"test", OPT_TEST, '-', "Self test"}, + {"reset", OPT_RESET, '-', "Reset module, clear salt and password"}, {"module", OPT_MODULE, '<', "File name of the provider module"}, {"provider_name", OPT_PROV_NAME, 's', "SMTC provider name"}, {"section_name", 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"}, + {"kek", OPT_KEK, 's', "The key for encrypting HMAC key"}, + {"engine", OPT_ENGINE, 's', "Use the engine e, possibly a hardware device"}, + OPT_SECTION("Input"), + {"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) == 0) + 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(EVP_PKEY *kek, unsigned char *auth_salt, + unsigned char **auth_key, size_t *auth_key_len) { - int ret = 0; - int i; - size_t outsz = *out_len; + int ok = 0; + EVP_PKEY_CTX *ctx = NULL; + char passwd[SMTC_AUTH_PASSWD_MAX_LEN + 1] = {0}; + unsigned char key[SMTC_AUTH_KEY_LEN]; + unsigned char *enc_key = NULL; + size_t outlen; + + if (EVP_read_pw_string_min(passwd, 8, sizeof(passwd) - 1, + "Setup password: ", 1) != 0) + goto end; + + if (!check_passwd(passwd, strlen(passwd))) { + BIO_printf(bio_err, "Passwords should be 8-64 characters in length and" + "must contain number, uppercase and lowercase letter\n"); + goto end; + } - if (!EVP_MAC_init(ctx, NULL, 0, NULL)) - goto err; - if (EVP_MAC_CTX_get_mac_size(ctx) > outsz) + if (RAND_bytes(auth_salt, SMTC_AUTH_SALT_LEN) != 1) goto end; - while ((i = BIO_read(in, (char *)tmp, BUFSIZE)) != 0) { - if (i < 0 || !EVP_MAC_update(ctx, tmp, i)) - goto err; + + if (PKCS5_PBKDF2_HMAC(passwd, strlen(passwd), auth_salt, SMTC_AUTH_SALT_LEN, + 10000, EVP_sm3(), SMTC_AUTH_KEY_LEN, key) != 1) + goto end; + + if (kek) { + ctx = EVP_PKEY_CTX_new(kek, NULL); + if (ctx == NULL) + goto end; + + if (EVP_PKEY_encrypt_init(ctx) != 1) + goto end; + + if (EVP_PKEY_encrypt(ctx, NULL, &outlen, key, SMTC_AUTH_KEY_LEN) != 1) + goto end; + + enc_key = OPENSSL_malloc(outlen); + + if (EVP_PKEY_encrypt(ctx, enc_key, &outlen, key, SMTC_AUTH_KEY_LEN) != 1) + goto end; + + *auth_key = enc_key; + enc_key = NULL; + *auth_key_len = outlen; } + + ok = 1; end: - if (!EVP_MAC_final(ctx, out, out_len, outsz)) - goto err; - ret = 1; -err: - return ret; + EVP_PKEY_CTX_free(ctx); + OPENSSL_free(enc_key); + return ok; } static int write_config_header(BIO *out, const char *prov_name, @@ -130,17 +167,25 @@ static int write_config_header(BIO *out, const char *prov_name, && BIO_printf(out, "%s = %s\n\n", prov_name, section); } -static int print_hex(BIO *bio, const char *label, const unsigned char *val, - size_t len) +static int print_kv(BIO *bio, const char *k, const unsigned char *v, + size_t vlen) { int ret; - char *hexstr = NULL; + char *hexv = NULL; + + if (v) { + hexv = OPENSSL_buf2hexstr(v, (long)vlen); + if (hexv == NULL) + return 0; + } + + if (hexv == NULL) { + ret = BIO_printf(bio, "%s = ", k); + } else { + ret = BIO_printf(bio, "%s = %s\n", k, hexv); + OPENSSL_free(hexv); + } - hexstr = OPENSSL_buf2hexstr(val, (long)len); - if (hexstr == NULL) - return 0; - ret = BIO_printf(bio, "%s = %s\n", label, hexstr); - OPENSSL_free(hexstr); return ret; } @@ -156,8 +201,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_kv(out, OSSL_PROV_SMTC_PARAM_MODULE_SIG, sc->sig, + sc->siglen)) goto end; if (sc->show_selftest) { @@ -170,22 +215,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; @@ -219,32 +248,32 @@ 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 ret = 1, ok = 0, reset = 0, i, j; + int new = 0, pass = 0; char *prog; + unsigned char *sig = NULL; + int 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 *eng_name = NULL; const char *prov_name = "smtc"; + const char *conf_file = SMTC_MODULE_CONF; 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; + long eline; + const char *kek_file = NULL; + EVP_PKEY *kek = NULL; + ENGINE *engine = NULL; + STACK_OF(OPENSSL_CSTRING) *section_names = NULL; + unsigned char auth_salt[SMTC_AUTH_SALT_LEN]; + unsigned char *auth_key = NULL; + size_t auth_key_len; prog = opt_init(argc, argv, mod_options); while ((o = opt_next()) != OPT_EOF) { @@ -261,6 +290,9 @@ int mod_main(int argc, char **argv) case OPT_TEST: self_test = 1; break; + case OPT_RESET: + reset = 1; + break; case OPT_PROV_NAME: prov_name = opt_arg(); break; @@ -273,15 +305,23 @@ 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; -#endif - case OPT_OUT: + case OPT_SIGFILE: + sigfile = opt_arg(); + break; + case OPT_NEW: + new = 1; out_fname = opt_arg(); break; + case OPT_KEK: + kek_file = opt_arg(); + break; + case OPT_ENGINE: + eng_name = opt_arg(); + engine = setup_engine(eng_name, 1); + break; case OPT_R_CASES: if (!opt_rand(o)) goto end; @@ -291,6 +331,52 @@ int mod_main(int argc, char **argv) argc = opt_num_rest(); argv = opt_rest(); + if (reset) { + conf = NCONF_new(NCONF_default()); + + if (NCONF_load(conf, conf_file, &eline) != 1) { + BIO_printf(bio_err, "Failed to load config file %s\n", conf_file); + goto end; + } + + section_names = NCONF_get_section_names(conf); + for (i = 0; i < sk_OPENSSL_CSTRING_num(section_names); i++) { + STACK_OF(CONF_VALUE) *sect = NCONF_get_section(conf, + sk_OPENSSL_CSTRING_value(section_names, i)); + + for (j = 0; j < sk_CONF_VALUE_num(sect); j++) { + CONF_VALUE *cv = sk_CONF_VALUE_value(sect, j); + + if (strcmp(cv->name, OSSL_PROV_SMTC_PARAM_AUTH_SALT) == 0 + || strcmp(cv->name, OSSL_PROV_SMTC_PARAM_AUTH_KEY) == 0 + || strcmp(cv->name, OSSL_PROV_SMTC_PARAM_AUTH_KEK) == 0) + cv->value = NULL; + } + } + sk_OPENSSL_CSTRING_free(section_names); + + fout = bio_open_default(conf_file, 'w', FORMAT_TEXT); + if (fout == NULL) { + BIO_printf(bio_err, "Failed to open config %s\n", conf_file); + goto end; + } + + if (NCONF_dump_bio(conf, fout) != 1) { + BIO_printf(bio_err, "Failed to write config file %s\n", + conf_file); + goto end; + } + + NCONF_free(conf); + conf = NULL; + BIO_free_all(fout); + fout = NULL; + + ok = 1; + + goto end; + } + if (self_test) { if (OSSL_PROVIDER_available(app_get0_libctx(), "smtc")) { OSSL_PROVIDER *prov = OSSL_PROVIDER_load(app_get0_libctx(), "smtc"); @@ -307,7 +393,7 @@ int mod_main(int argc, char **argv) OSSL_PROVIDER_unload(prov); - ret = 0; + ok = 1; goto end; } else { BIO_printf(bio_err, "SMTC provider not available\n"); @@ -315,98 +401,97 @@ 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; + BIO *sigbio = BIO_new_file(sigfile, "rb"); - if (!sk_OPENSSL_STRING_push(opts, "digest:SM3")) - goto end; - if (!sk_OPENSSL_STRING_push(opts, "hexkey:" SMTC_KEY_STRING)) - 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; - 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; - } + if (sc.module_path == NULL) + goto opthelp; - read_buffer = app_malloc(BUFSIZE, "I/O buffer"); - if (read_buffer == NULL) - goto end; + conf = generate_config_and_load(prov_name, &sc); + if (conf == 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; - } + 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 (!write_config_smtc_section(fout, &sc)) + goto end; + + BIO_printf(bio_err, "INSTALL PASSED\n"); - ctx = EVP_MAC_CTX_new(mac); - if (ctx == NULL) { - BIO_printf(bio_err, "Unable to create MAC CTX for module check\n"); + ok = 1; goto end; } - if (opts != NULL) { - int ok = 1; - OSSL_PARAM *params - = app_params_new_from_opts(opts, EVP_MAC_settable_ctx_params(mac)); - - if (params == NULL) + if (pass) { + 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; - - if (!EVP_MAC_CTX_set_params(ctx, params)) { - BIO_printf(bio_err, "MAC parameter error\n"); - ERR_print_errors(bio_err); - ok = 0; } - app_params_free(params); - if (!ok) + + kek = load_key(kek_file, FORMAT_PEM, 0, NULL, engine, + "key encryption key"); + if (kek == NULL) goto end; - } - ctx2 = EVP_MAC_CTX_dup(ctx); - if (ctx2 == NULL) { - BIO_printf(bio_err, "Unable to create MAC CTX for install indicator\n"); - goto end; - } + if (!setup_password(kek, auth_salt, &auth_key, &auth_key_len)) + 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 (!print_kv(fout, OSSL_PROV_SMTC_PARAM_AUTH_SALT, + auth_salt, + sizeof(auth_salt)) + || !print_kv(fout, OSSL_PROV_SMTC_PARAM_AUTH_KEY, + auth_key, auth_key_len) + || !print_kv(fout, OSSL_PROV_SMTC_PARAM_AUTH_KEK, + NULL, 0)) + goto end; - conf = generate_config_and_load(prov_name, &sc); - if (conf == NULL) - goto end; + if (!PEM_write_bio_PrivateKey(fout, kek, NULL, NULL, 0, NULL, NULL)) + 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 (engine && !print_kv(fout, OSSL_PROV_SMTC_PARAM_ENGINE, + (const unsigned char *)eng_name, strlen(eng_name))) + goto end; } - if (!write_config_smtc_section(fout, &sc)) - goto end; - BIO_printf(bio_err, "INSTALL PASSED\n"); - - ret = 0; + ok = 1; end: - if (ret == 1) + if (ok == 0) { ERR_print_errors(bio_err); + ret = 1; + } else { + ret = 0; + } cleanup: - BIO_free(fout); + release_engine(engine); + EVP_PKEY_free(kek); + OPENSSL_free(auth_key); + OPENSSL_free(sig); + BIO_free_all(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..ede4c0cba 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_SOURCE, OPT_R_ENUM, OPT_PROV_ENUM } OPTION_CHOICE; @@ -37,6 +38,8 @@ 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"}, + {"source", OPT_SOURCE, 's', "Specify the entropy source"}, OPT_R_OPTIONS, OPT_PROV_OPTIONS, @@ -46,13 +49,47 @@ const OPTIONS rand_options[] = { {NULL} }; +static int opt_rand_source(const char *name) +{ + int ret = 0; + + if (strcmp(name, "getrandom") == 0) + ret = RAND_ENTROPY_SOURCE_GETRANDOM; + else if (strcmp(name, "devrandom") == 0) + ret = RAND_ENTROPY_SOURCE_DEVRANDOM; + else if (strcmp(name, "rdtsc") == 0) + ret = RAND_ENTROPY_SOURCE_RDTSC; + else if (strcmp(name, "rdcpu") == 0) + ret = RAND_ENTROPY_SOURCE_RDCPU; + else if (strcmp(name, "egd") == 0) + ret = RAND_ENTROPY_SOURCE_EGD; + else if (strcmp(name, "bcryptgenrandom") == 0) + ret = RAND_ENTROPY_SOURCE_BCRYPTGENRANDOM; + else if (strcmp(name, "cryptgenrandom_def_prov") == 0) + ret = RAND_ENTROPY_SOURCE_CRYPTGENRANDOM_DEF_PROV; + else if (strcmp(name, "cryptgenrandom_intel_prov") == 0) + ret = RAND_ENTROPY_SOURCE_CRYPTGENRANDOM_INTEL_PROV; + else if (strcmp(name, "rtcode") == 0) + ret = RAND_ENTROPY_SOURCE_RTCODE; + else if (strcmp(name, "rtmem") == 0) + ret = RAND_ENTROPY_SOURCE_RTMEM; + else if (strcmp(name, "rtsock") == 0) + ret = RAND_ENTROPY_SOURCE_RTSOCK; + else + BIO_printf(bio_err, "Unknown entropy source '%s'\n", name); + + return ret; +} + int rand_main(int argc, char **argv) { ENGINE *e = NULL; BIO *out = NULL; + int source = 0; 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 +119,13 @@ int rand_main(int argc, char **argv) case OPT_HEX: format = FORMAT_TEXT; break; + case OPT_ENTROPY: + entropy = 1; + break; + case OPT_SOURCE: + source |= opt_rand_source(opt_arg()); + RAND_set_entropy_source(source); + break; case OPT_PROV_CASES: if (!opt_provider(o)) goto end; @@ -114,15 +158,29 @@ int rand_main(int argc, char **argv) } while (num > 0) { - unsigned char buf[4096]; + /* When getting entropy from EGD, buf size must be less than 256 */ + unsigned char buf[255]; int chunk; 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..419c31290 100644 --- a/crypto/info.c +++ b/crypto/info.c @@ -152,8 +152,14 @@ 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 +#ifdef OPENSSL_RAND_SEED_RTSOCK + add_seeds_string("real-time-socket"); #endif seed_sources = seeds; } diff --git a/crypto/provider_core.c b/crypto/provider_core.c index 177358f05..d9698d72d 100644 --- a/crypto/provider_core.c +++ b/crypto/provider_core.c @@ -172,6 +172,7 @@ struct ossl_provider_st { OSSL_FUNC_provider_self_test_fn *self_test; OSSL_FUNC_provider_query_operation_fn *query_operation; OSSL_FUNC_provider_unquery_operation_fn *unquery_operation; + OSSL_FUNC_provider_reset_fn *reset; /* * Cache of bit to indicate of query_operation() has been called on diff --git a/crypto/provider_predefined.c b/crypto/provider_predefined.c index 938c1ba9a..e20fbe4c7 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) + { "inner-smtc", 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/crypto/rand/prov_seed.c b/crypto/rand/prov_seed.c index afa85ab76..486153ec8 100644 --- a/crypto/rand/prov_seed.c +++ b/crypto/rand/prov_seed.c @@ -38,6 +38,34 @@ size_t ossl_rand_get_entropy(ossl_unused OSSL_CORE_HANDLE *handle, return ret; } +size_t ossl_rand_get_entropy_from_source(unsigned int source, + unsigned char **pout, int entropy, + size_t min_len, size_t max_len) +{ + size_t ret = 0; + size_t entropy_available; + RAND_POOL *pool; + + pool = ossl_rand_pool_new(entropy, 1, min_len, max_len); + if (pool == NULL) { + ERR_raise(ERR_LIB_RAND, ERR_R_MALLOC_FAILURE); + return 0; + } + + pool->entropy_source = source; + + /* Get entropy by polling system entropy sources. */ + entropy_available = ossl_pool_acquire_entropy(pool); + + if (entropy_available > 0) { + ret = ossl_rand_pool_length(pool); + *pout = ossl_rand_pool_detach(pool); + } + + ossl_rand_pool_free(pool); + return ret; +} + void ossl_rand_cleanup_entropy(ossl_unused OSSL_CORE_HANDLE *handle, unsigned char *buf, size_t len) { diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c index a00514e52..aeecde663 100644 --- a/crypto/rand/rand_lib.c +++ b/crypto/rand/rand_lib.c @@ -808,6 +808,11 @@ void ossl_random_add_conf_module(void) CONF_module_add("random", random_conf_init, random_conf_deinit); } +void RAND_set_entropy_source(unsigned int type) +{ + ossl_rand_pool_set_default_entropy_source(type); +} + int RAND_set_DRBG_type(OSSL_LIB_CTX *ctx, const char *drbg, const char *propq, const char *cipher, const char *digest) { diff --git a/crypto/rand/rand_pool.c b/crypto/rand/rand_pool.c index 55f14be60..4dae4a93c 100644 --- a/crypto/rand/rand_pool.c +++ b/crypto/rand/rand_pool.c @@ -16,6 +16,8 @@ #include "internal/thread_once.h" #include "crypto/rand_pool.h" +static unsigned int default_entropy_source = 0xFFFFFFFF; + /* * Allocate memory and initialize a new random pool */ @@ -49,6 +51,7 @@ RAND_POOL *ossl_rand_pool_new(int entropy_requested, int secure, pool->entropy_requested = entropy_requested; pool->secure = secure; + pool->entropy_source = default_entropy_source; return pool; err: @@ -410,3 +413,8 @@ int ossl_rand_pool_add_end(RAND_POOL *pool, size_t len, size_t entropy) return 1; } + +void ossl_rand_pool_set_default_entropy_source(unsigned int source) +{ + default_entropy_source = source; +} diff --git a/crypto/trace.c b/crypto/trace.c index d790409a2..051b72425 100644 --- a/crypto/trace.c +++ b/crypto/trace.c @@ -138,7 +138,10 @@ static const struct trace_category_st trace_categories[] = { TRACE_CATEGORY_(STORE), TRACE_CATEGORY_(DECODER), TRACE_CATEGORY_(ENCODER), - TRACE_CATEGORY_(REF_COUNT) + TRACE_CATEGORY_(REF_COUNT), +#ifdef SMTC_MODULE + TRACE_CATEGORY_(SMTC), +#endif }; const char *OSSL_trace_get_category_name(int num) diff --git a/crypto/tsapi/tsapi_lib.c b/crypto/tsapi/tsapi_lib.c new file mode 100644 index 000000000..2ed03d521 --- /dev/null +++ b/crypto/tsapi/tsapi_lib.c @@ -0,0 +1,148 @@ +/* + * Copyright 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 + * in the file LICENSE in the source distribution or at + * https://github.com/Tongsuo-Project/Tongsuo/blob/master/LICENSE.txt + */ + +#include + +int TSAPI_sm2_encrypt(EVP_PKEY *key, const unsigned char *in, size_t inlen, + unsigned char *out, size_t *outlen) +{ + EVP_PKEY_CTX *ctx = NULL; + int ok = 0; + + if (key == NULL || in == NULL || outlen == NULL) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + ctx = EVP_PKEY_CTX_new(key, NULL); + if (ctx == NULL) + return 0; + + if (EVP_PKEY_encrypt_init(ctx) <= 0 + || EVP_PKEY_encrypt(ctx, out, outlen, in, inlen) <= 0) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_EVP_LIB); + goto end; + } + + ok = 1; +end: + EVP_PKEY_CTX_free(ctx); + return ok; +} + +int TSAPI_sm2_decrypt(EVP_PKEY *key, const unsigned char *in, size_t inlen, + unsigned char *out, size_t *outlen) +{ + EVP_PKEY_CTX *ctx = NULL; + int ok = 0; + + if (key == NULL || in == NULL || outlen == NULL) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + ctx = EVP_PKEY_CTX_new(key, NULL); + if (ctx == NULL) + return 0; + + if (EVP_PKEY_decrypt_init(ctx) <= 0 + || EVP_PKEY_decrypt(ctx, out, outlen, in, inlen) <= 0) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_EVP_LIB); + goto end; + } + + ok = 1; +end: + EVP_PKEY_CTX_free(ctx); + return ok; +} + +int TSAPI_sm2_sign(EVP_PKEY *key, const unsigned char *tbs, size_t tbslen, + unsigned char *sig, size_t *siglen) +{ + EVP_PKEY_CTX *ctx = NULL; + int ok = 0; + + if (key == NULL || tbs == NULL || siglen == NULL) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + ctx = EVP_PKEY_CTX_new(key, NULL); + if (ctx == NULL) + return 0; + + if (EVP_PKEY_sign_init(ctx) <= 0 + || EVP_PKEY_sign(ctx, sig, siglen, tbs, tbslen) <= 0) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_EVP_LIB); + goto end; + } + + ok = 1; +end: + EVP_PKEY_CTX_free(ctx); + return ok; +} + +int TSAPI_sm2_verify(EVP_PKEY *key, const unsigned char *tbs, size_t tbslen, + const unsigned char *sig, size_t siglen) +{ + EVP_PKEY_CTX *ctx = NULL; + int ok = 0; + + if (key == NULL || tbs == NULL || sig == NULL) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + ctx = EVP_PKEY_CTX_new(key, NULL); + if (ctx == NULL) + return 0; + + if (EVP_PKEY_verify_init(ctx) <= 0 + || EVP_PKEY_verify(ctx, sig, siglen, tbs, tbslen) <= 0) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_EVP_LIB); + goto end; + } + + ok = 1; +end: + EVP_PKEY_CTX_free(ctx); + return ok; +} + +int TSAPI_sm4_encrypt(const EVP_CIPHER *mode, const unsigned char *key, + size_t keylen, const unsigned char *iv, EVP_PKEY *kek, + const unsigned char *in, size_t inlen, unsigned char *out, + size_t *outlen) +{ + EVP_CIPHER_CTX *ctx = NULL; + int ok = 0; + + if (mode == NULL || key == NULL || in == NULL || outlen == NULL) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + ctx = EVP_CIPHER_CTX_new(); + if (ctx == NULL) + return 0; + + if (EVP_EncryptInit_ex(ctx, mode, NULL, key, iv) <= 0 + || EVP_EncryptUpdate(ctx, out, outlen, in, inlen) <= 0 + || EVP_EncryptFinal_ex(ctx, out + *outlen, outlen) <= 0) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_EVP_LIB); + goto end; + } + + ok = 1; +end: + EVP_CIPHER_CTX_free(ctx); + return ok; +} diff --git a/include/crypto/rand.h b/include/crypto/rand.h index fa3b5b2b9..7b062cf93 100644 --- a/include/crypto/rand.h +++ b/include/crypto/rand.h @@ -32,6 +32,18 @@ # endif # endif +#define RAND_ENTROPY_SOURCE_GETRANDOM 0x0001 +#define RAND_ENTROPY_SOURCE_DEVRANDOM 0x0002 +#define RAND_ENTROPY_SOURCE_RDTSC 0x0004 +#define RAND_ENTROPY_SOURCE_RDCPU 0x0008 +#define RAND_ENTROPY_SOURCE_EGD 0x0010 +#define RAND_ENTROPY_SOURCE_BCRYPTGENRANDOM 0x0020 +#define RAND_ENTROPY_SOURCE_CRYPTGENRANDOM_DEF_PROV 0x0040 +#define RAND_ENTROPY_SOURCE_CRYPTGENRANDOM_INTEL_PROV 0x0080 +#define RAND_ENTROPY_SOURCE_RTCODE 0x0100 +#define RAND_ENTROPY_SOURCE_RTMEM 0x0200 +#define RAND_ENTROPY_SOURCE_RTSOCK 0x0400 + /* * Defines related to seed sources */ @@ -111,6 +123,9 @@ void ossl_random_add_conf_module(void); size_t ossl_rand_get_entropy(ossl_unused OSSL_CORE_HANDLE *handle, unsigned char **pout, int entropy, size_t min_len, size_t max_len); +size_t ossl_rand_get_entropy_from_source(unsigned int source, + unsigned char **pout, int entropy, + size_t min_len, size_t max_len); void ossl_rand_cleanup_entropy(ossl_unused OSSL_CORE_HANDLE *handle, unsigned char *buf, size_t len); size_t ossl_rand_get_nonce(ossl_unused OSSL_CORE_HANDLE *handle, diff --git a/include/crypto/rand_pool.h b/include/crypto/rand_pool.h index f4d1d954b..7be677965 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 @@ -80,6 +91,8 @@ typedef struct rand_pool_st { size_t alloc_len; /* current number of bytes allocated */ size_t entropy; /* current entropy count in bits */ size_t entropy_requested; /* requested entropy count in bits */ + + unsigned int entropy_source; } RAND_POOL; RAND_POOL *ossl_rand_pool_new(int entropy_requested, int secure, @@ -105,5 +118,5 @@ int ossl_rand_pool_add(RAND_POOL *pool, const unsigned char *buffer, size_t len, size_t entropy); unsigned char *ossl_rand_pool_add_begin(RAND_POOL *pool, size_t len); int ossl_rand_pool_add_end(RAND_POOL *pool, size_t len, size_t entropy); - +void ossl_rand_pool_set_default_entropy_source(unsigned int source); #endif /* OSSL_PROVIDER_RAND_POOL_H */ diff --git a/include/internal/cryptlib.h b/include/internal/cryptlib.h index bfd035781..18ad940c3 100644 --- a/include/internal/cryptlib.h +++ b/include/internal/cryptlib.h @@ -70,6 +70,10 @@ DEFINE_LHASH_OF(MEM); # define X509_PRIVATE_DIR OPENSSLDIR "/private" # define CTLOG_FILE OPENSSLDIR "/ct_log_list.cnf" +# ifdef SMTC_MODULE +# define SMTC_MODULE_CONF OPENSSLDIR "/smtcmodule.cnf" +# endif + # define X509_CERT_DIR_EVP "SSL_CERT_DIR" # define X509_CERT_FILE_EVP "SSL_CERT_FILE" # define CTLOG_FILE_EVP "CTLOG_FILE" diff --git a/include/internal/smtc_names.h b/include/internal/smtc_names.h index fe67aae5c..97525ee58 100644 --- a/include/internal/smtc_names.h +++ b/include/internal/smtc_names.h @@ -13,17 +13,19 @@ # include -# define OSSL_PROV_SMTC_PARAM_MODULE_PATH "module-path" -# define OSSL_PROV_SMTC_PARAM_MODULE_MAC "module-mac" -# 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" -# define OSSL_PROV_SMTC_PARAM_RNG_POWERON_TEST "rng-poweron-test" -# define OSSL_PROV_SMTC_PARAM_RNG_CONTINUOUS_TEST "rng-continuous-test" +# define OSSL_PROV_SMTC_PARAM_MODULE_PATH "module-path" +# define OSSL_PROV_SMTC_PARAM_MODULE_SIG "module-sig" +# define OSSL_PROV_SMTC_PARAM_AUTH_KEY "auth-key" +# define OSSL_PROV_SMTC_PARAM_AUTH_SALT "auth-salt" +# define OSSL_PROV_SMTC_PARAM_AUTH_KEK "auth-kek" +# define OSSL_PROV_SMTC_PARAM_ENGINE "engine" +# define OSSL_PROV_SMTC_PARAM_SHOW_SELFTEST "show-selftest" +# define OSSL_PROV_SMTC_PARAM_RNG_POWERON_TEST "rng-poweron-test" +# define OSSL_PROV_SMTC_PARAM_RNG_CONTINUOUS_TEST "rng-continuous-test" # 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/core_dispatch.h b/include/openssl/core_dispatch.h index 99fcda002..d285f6548 100644 --- a/include/openssl/core_dispatch.h +++ b/include/openssl/core_dispatch.h @@ -249,6 +249,9 @@ OSSL_CORE_MAKE_FUNC(int, provider_get_capabilities, (void *provctx, # define OSSL_FUNC_PROVIDER_SELF_TEST 1031 OSSL_CORE_MAKE_FUNC(int, provider_self_test, (void *provctx)) +# define OSSL_FUNC_PROVIDER_RESET 1032 +OSSL_CORE_MAKE_FUNC(int, provider_reset, (void *provctx)) + /* Operations */ # define OSSL_OP_DIGEST 1 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/rand.h b/include/openssl/rand.h index ad3054fd5..1673631c7 100644 --- a/include/openssl/rand.h +++ b/include/openssl/rand.h @@ -87,6 +87,7 @@ int RAND_set_DRBG_type(OSSL_LIB_CTX *ctx, const char *drbg, const char *propq, const char *cipher, const char *digest); int RAND_set_seed_source_type(OSSL_LIB_CTX *ctx, const char *seed, const char *propq); +void RAND_set_entropy_source(unsigned int source); void RAND_seed(const void *buf, int num); void RAND_keep_random_devices_open(int keep); 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/include/openssl/trace.h b/include/openssl/trace.h index 282001336..d2a2d52ed 100644 --- a/include/openssl/trace.h +++ b/include/openssl/trace.h @@ -57,8 +57,9 @@ extern "C" { # define OSSL_TRACE_CATEGORY_DECODER 15 # define OSSL_TRACE_CATEGORY_ENCODER 16 # define OSSL_TRACE_CATEGORY_REF_COUNT 17 +# define OSSL_TRACE_CATEGORY_SMTC 18 /* Count of available categories. */ -# define OSSL_TRACE_CATEGORY_NUM 18 +# define OSSL_TRACE_CATEGORY_NUM 19 /* Returns the trace category number for the given |name| */ int OSSL_trace_get_category_num(const char *name); diff --git a/include/openssl/tsapi.h b/include/openssl/tsapi.h new file mode 100644 index 000000000..83edfbaa0 --- /dev/null +++ b/include/openssl/tsapi.h @@ -0,0 +1,32 @@ +/* + * Copyright 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 + * in the file LICENSE in the source distribution or at + * https://github.com/Tongsuo-Project/Tongsuo/blob/master/LICENSE.txt + */ + +#ifndef TONGSUO_API_H +# define TONGSUO_API_H +# pragma once + +# include +# ifndef OPENSSL_NO_DEPRECATED_3_0 +# define HEADER_TSAPI_H +# endif + +# include + +# ifdef __cplusplus +extern "C" { +# endif + + + +# ifdef __cplusplus +} +# endif + +#endif + 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/include/prov/provider_util.h b/providers/common/include/prov/provider_util.h index dfe91f29b..b74e1373c 100644 --- a/providers/common/include/prov/provider_util.h +++ b/providers/common/include/prov/provider_util.h @@ -7,8 +7,11 @@ * https://www.openssl.org/source/license.html */ -#include -#include +#ifndef OSSL_PROV_PROVIDER_UTIL_H +# define OSSL_PROV_PROVIDER_UTIL_H + +# include +# include typedef struct { /* @@ -136,3 +139,4 @@ typedef struct ag_capable_st { */ void ossl_prov_cache_exported_algorithms(const OSSL_ALGORITHM_CAPABLE *in, OSSL_ALGORITHM *out); +#endif 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..d473c6530 100644 --- a/providers/implementations/rands/drbg_hash.c +++ b/providers/implementations/rands/drbg_hash.c @@ -35,9 +35,6 @@ static OSSL_FUNC_rand_gettable_ctx_params_fn drbg_hash_gettable_ctx_params; static OSSL_FUNC_rand_get_ctx_params_fn drbg_hash_get_ctx_params; static OSSL_FUNC_rand_verify_zeroization_fn drbg_hash_verify_zeroization; -/* 888 bits from SP800-90Ar1 10.1 table 2 */ -#define HASH_PRNG_MAX_SEEDLEN (888/8) - /* 440 bits from SP800-90Ar1 10.1 table 2 */ #define HASH_PRNG_SMALL_SEEDLEN (440/8) @@ -45,15 +42,6 @@ static OSSL_FUNC_rand_verify_zeroization_fn drbg_hash_verify_zeroization; #define MAX_BLOCKLEN_USING_SMALL_SEEDLEN (256/8) #define INBYTE_IGNORE ((unsigned char)0xFF) -typedef struct rand_drbg_hash_st { - PROV_DIGEST digest; - EVP_MD_CTX *ctx; - size_t blocklen; - unsigned char V[HASH_PRNG_MAX_SEEDLEN]; - unsigned char C[HASH_PRNG_MAX_SEEDLEN]; - /* Temporary value storage: should always exceed max digest length */ - unsigned char vtmp[HASH_PRNG_MAX_SEEDLEN]; -} PROV_DRBG_HASH; /* * SP800-90Ar1 10.3.1 Derivation function using a Hash Function (Hash_df). @@ -309,8 +297,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..bcdef411b 100644 --- a/providers/implementations/rands/drbg_local.h +++ b/providers/implementations/rands/drbg_local.h @@ -18,6 +18,7 @@ # include "internal/nelem.h" # include "internal/numbers.h" # include "prov/provider_ctx.h" +# include "prov/provider_util.h" /* How many times to read the TSC as a randomness source. */ # define TSC_READ_COUNT 4 @@ -49,13 +50,26 @@ */ # define DRBG_MAX_LENGTH INT32_MAX +/* 888 bits from SP800-90Ar1 10.1 table 2 */ +#define HASH_PRNG_MAX_SEEDLEN (888/8) + /* 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; @@ -178,6 +192,16 @@ struct prov_drbg_st { OSSL_CALLBACK *cleanup_nonce_fn; }; +typedef struct rand_drbg_hash_st { + PROV_DIGEST digest; + EVP_MD_CTX *ctx; + size_t blocklen; + unsigned char V[HASH_PRNG_MAX_SEEDLEN]; + unsigned char C[HASH_PRNG_MAX_SEEDLEN]; + /* Temporary value storage: should always exceed max digest length */ + unsigned char vtmp[HASH_PRNG_MAX_SEEDLEN]; +} PROV_DRBG_HASH; + PROV_DRBG *ossl_rand_drbg_new (void *provctx, void *parent, const OSSL_DISPATCH *parent_dispatch, int (*dnew)(PROV_DRBG *ctx), diff --git a/providers/implementations/rands/seeding/rand_unix.c b/providers/implementations/rands/seeding/rand_unix.c index 6fb13195a..48b111530 100644 --- a/providers/implementations/rands/seeding/rand_unix.c +++ b/providers/implementations/rands/seeding/rand_unix.c @@ -102,7 +102,14 @@ 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 +# undef OPENSSL_RAND_SEED_RTSOCK +#endif + +#if defined(OPENSSL_RAND_SEED_RTSOCK) +# include +# include #endif #if defined(OPENSSL_SYS_UEFI) && !defined(OPENSSL_RAND_SEED_NONE) @@ -606,8 +613,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 +642,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; @@ -667,6 +675,43 @@ static size_t ossl_prov_acquire_entropy_from_rtc2(RAND_POOL *pool) } # endif +# if defined(OPENSSL_RAND_SEED_RTSOCK) +static size_t ossl_prov_acquire_entropy_from_rtsock(RAND_POOL *pool) +{ + int fd[2], ret; + long data; + size_t i, bytes_needed; + struct timespec ts; + unsigned char v; + + bytes_needed = ossl_rand_pool_bytes_needed(pool, 4 /*entropy_factor*/); + + for (i = 0; i < bytes_needed; i++) { + ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fd); + if (ret == -1) + break; + + data = random(); + (void)write(fd[0], &data, sizeof(data)); + (void)read(fd[1], &data, sizeof(data)); + + /* sleep for 1/65536 of a second (15 us). */ + ts.tv_sec = 0; + ts.tv_nsec = 15000; + nanosleep(&ts, NULL); + + /* Get wall clock time, take 8 bits. */ + clock_gettime(CLOCK_REALTIME, &ts); + v = (unsigned char)(ts.tv_nsec & 0xFF); + ossl_rand_pool_add(pool, &v, sizeof(v), 2); + + close(fd[0]); + close(fd[1]); + } + + return ossl_rand_pool_entropy_available(pool); +} +# endif /* * Try the various seeding methods in turn, exit when successful. * @@ -694,7 +739,7 @@ size_t ossl_pool_acquire_entropy(RAND_POOL *pool) (void)entropy_available; /* avoid compiler warning */ # if defined(OPENSSL_RAND_SEED_GETRANDOM) - { + if (pool->entropy_source & RAND_ENTROPY_SOURCE_GETRANDOM) { size_t bytes_needed; unsigned char *buffer; ssize_t bytes; @@ -713,10 +758,11 @@ size_t ossl_pool_acquire_entropy(RAND_POOL *pool) break; } } + + entropy_available = ossl_rand_pool_entropy_available(pool); + if (entropy_available > 0) + return entropy_available; } - entropy_available = ossl_rand_pool_entropy_available(pool); - if (entropy_available > 0) - return entropy_available; # endif # if defined(OPENSSL_RAND_SEED_LIBRANDOM) @@ -726,7 +772,8 @@ size_t ossl_pool_acquire_entropy(RAND_POOL *pool) # endif # if defined(OPENSSL_RAND_SEED_DEVRANDOM) - if (wait_random_seeded()) { + if ((pool->entropy_source & RAND_ENTROPY_SOURCE_DEVRANDOM) + && wait_random_seeded()) { size_t bytes_needed; unsigned char *buffer; size_t i; @@ -766,19 +813,23 @@ size_t ossl_pool_acquire_entropy(RAND_POOL *pool) # endif # if defined(OPENSSL_RAND_SEED_RDTSC) - entropy_available = ossl_prov_acquire_entropy_from_tsc(pool); - if (entropy_available > 0) - return entropy_available; + if (pool->entropy_source & RAND_ENTROPY_SOURCE_RDTSC) { + entropy_available = ossl_prov_acquire_entropy_from_tsc(pool); + if (entropy_available > 0) + return entropy_available; + } # endif # if defined(OPENSSL_RAND_SEED_RDCPU) - entropy_available = ossl_prov_acquire_entropy_from_cpu(pool); - if (entropy_available > 0) - return entropy_available; + if (pool->entropy_source & RAND_ENTROPY_SOURCE_RDCPU) { + entropy_available = ossl_prov_acquire_entropy_from_cpu(pool); + if (entropy_available > 0) + return entropy_available; + } # endif # if defined(OPENSSL_RAND_SEED_EGD) - { + if (pool->entropy_source & RAND_ENTROPY_SOURCE_EGD) { static const char *paths[] = { DEVRANDOM_EGD, NULL }; size_t bytes_needed; unsigned char *buffer; @@ -804,14 +855,28 @@ 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 (entropy_available > 0) - return entropy_available; +# if defined(OPENSSL_RAND_SEED_RTCODE) + if (pool->entropy_source & RAND_ENTROPY_SOURCE_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 (entropy_available > 0) - return entropy_available; +# if defined(OPENSSL_RAND_SEED_RTMEM) + if (pool->entropy_source & RAND_ENTROPY_SOURCE_RTMEM) { + entropy_available = ossl_prov_acquire_entropy_from_rtmem(pool); + if (entropy_available > 0) + return entropy_available; + } +# endif + +# if defined(OPENSSL_RAND_SEED_RTSOCK) + if (pool->entropy_source & RAND_ENTROPY_SOURCE_RTSOCK) { + entropy_available = ossl_prov_acquire_entropy_from_rtsock(pool); + if (entropy_available > 0) + return entropy_available; + } # endif return ossl_rand_pool_entropy_available(pool); diff --git a/providers/implementations/rands/seeding/rand_win.c b/providers/implementations/rands/seeding/rand_win.c index 704705425..6bf741a28 100644 --- a/providers/implementations/rands/seeding/rand_win.c +++ b/providers/implementations/rands/seeding/rand_win.c @@ -53,69 +53,79 @@ size_t ossl_pool_acquire_entropy(RAND_POOL *pool) # ifdef OPENSSL_RAND_SEED_RDTSC - entropy_available = ossl_prov_acquire_entropy_from_tsc(pool); - if (entropy_available > 0) - return entropy_available; + if (pool->entropy_source & RAND_ENTROPY_SOURCE_RDTSC) { + entropy_available = ossl_prov_acquire_entropy_from_tsc(pool); + if (entropy_available > 0) + return entropy_available; + } # endif # ifdef OPENSSL_RAND_SEED_RDCPU - entropy_available = ossl_prov_acquire_entropy_from_cpu(pool); - if (entropy_available > 0) - return entropy_available; + if (pool->entropy_source & RAND_ENTROPY_SOURCE_RDCPU) { + entropy_available = ossl_prov_acquire_entropy_from_cpu(pool); + if (entropy_available > 0) + return entropy_available; + } # endif # ifdef USE_BCRYPTGENRANDOM - bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); - buffer = ossl_rand_pool_add_begin(pool, bytes_needed); - if (buffer != NULL) { - size_t bytes = 0; - if (BCryptGenRandom(NULL, buffer, bytes_needed, - BCRYPT_USE_SYSTEM_PREFERRED_RNG) == STATUS_SUCCESS) - bytes = bytes_needed; - - ossl_rand_pool_add_end(pool, bytes, 8 * bytes); - entropy_available = ossl_rand_pool_entropy_available(pool); - } - if (entropy_available > 0) - return entropy_available; -# else - bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); - buffer = ossl_rand_pool_add_begin(pool, bytes_needed); - if (buffer != NULL) { - size_t bytes = 0; - /* poll the CryptoAPI PRNG */ - if (CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL, - CRYPT_VERIFYCONTEXT | CRYPT_SILENT) != 0) { - if (CryptGenRandom(hProvider, bytes_needed, buffer) != 0) + if (pool->entropy_source & RAND_ENTROPY_SOURCE_BCRYPTGENRANDOM) { + bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); + buffer = ossl_rand_pool_add_begin(pool, bytes_needed); + if (buffer != NULL) { + size_t bytes = 0; + if (BCryptGenRandom(NULL, buffer, bytes_needed, + BCRYPT_USE_SYSTEM_PREFERRED_RNG) == STATUS_SUCCESS) bytes = bytes_needed; - CryptReleaseContext(hProvider, 0); + ossl_rand_pool_add_end(pool, bytes, 8 * bytes); + entropy_available = ossl_rand_pool_entropy_available(pool); } - - ossl_rand_pool_add_end(pool, bytes, 8 * bytes); - entropy_available = ossl_rand_pool_entropy_available(pool); + if (entropy_available > 0) + return entropy_available; + } +# else + if (pool->entropy_source & RAND_ENTROPY_SOURCE_CRYPTGENRANDOM_DEF_PROV) { + bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); + buffer = ossl_rand_pool_add_begin(pool, bytes_needed); + if (buffer != NULL) { + size_t bytes = 0; + /* poll the CryptoAPI PRNG */ + if (CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT | CRYPT_SILENT) != 0) { + if (CryptGenRandom(hProvider, bytes_needed, buffer) != 0) + bytes = bytes_needed; + + CryptReleaseContext(hProvider, 0); + } + + ossl_rand_pool_add_end(pool, bytes, 8 * bytes); + entropy_available = ossl_rand_pool_entropy_available(pool); + } + if (entropy_available > 0) + return entropy_available; } - if (entropy_available > 0) - return entropy_available; - - bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); - buffer = ossl_rand_pool_add_begin(pool, bytes_needed); - if (buffer != NULL) { - size_t bytes = 0; - /* poll the Pentium PRG with CryptoAPI */ - if (CryptAcquireContextW(&hProvider, NULL, - INTEL_DEF_PROV, PROV_INTEL_SEC, - CRYPT_VERIFYCONTEXT | CRYPT_SILENT) != 0) { - if (CryptGenRandom(hProvider, bytes_needed, buffer) != 0) - bytes = bytes_needed; - CryptReleaseContext(hProvider, 0); + if (pool->entropy_source & RAND_ENTROPY_SOURCE_CRYPTGENRANDOM_INTEL_PROV) { + bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); + buffer = ossl_rand_pool_add_begin(pool, bytes_needed); + if (buffer != NULL) { + size_t bytes = 0; + /* poll the Pentium PRG with CryptoAPI */ + if (CryptAcquireContextW(&hProvider, NULL, + INTEL_DEF_PROV, PROV_INTEL_SEC, + CRYPT_VERIFYCONTEXT | CRYPT_SILENT) != 0) { + if (CryptGenRandom(hProvider, bytes_needed, buffer) != 0) + bytes = bytes_needed; + + CryptReleaseContext(hProvider, 0); + } + ossl_rand_pool_add_end(pool, bytes, 8 * bytes); + entropy_available = ossl_rand_pool_entropy_available(pool); } - ossl_rand_pool_add_end(pool, bytes, 8 * bytes); - entropy_available = ossl_rand_pool_entropy_available(pool); + if (entropy_available > 0) + return entropy_available; } - if (entropy_available > 0) - return entropy_available; # endif return ossl_rand_pool_entropy_available(pool); diff --git a/providers/implementations/rands/smtc_rng.c b/providers/implementations/rands/smtc_rng.c index e7c3aace0..7d03ab86c 100644 --- a/providers/implementations/rands/smtc_rng.c +++ b/providers/implementations/rands/smtc_rng.c @@ -24,20 +24,62 @@ #include "prov/seeding.h" #include "crypto/evp.h" -#define REPEAT_COUNT_TEST_THRESHOLD 26 typedef struct smtc_crng_test_global_st { CRYPTO_RWLOCK *lock; - unsigned char last_bit; + EVP_MD_CTX *md_ctx; + int sample; size_t cnt; } SMTC_CRNG_TEST_GLOBAL; -static int get_bit(const unsigned char *buf, int m) +/* 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) { - if (m < 0) - return 0; + 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; - return (buf[m / 8] << (m % 8) >> 7) & 1; + tmp[0]++; + out += blocklen; + } + + return 1; } static void rand_smtc_crng_ossl_ctx_free(void *vcrngt_glob) @@ -45,6 +87,7 @@ 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,11 +98,19 @@ 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; } + smtc_glob->sample = -1; + smtc_glob->cnt = 0; + return smtc_glob; } @@ -69,34 +120,26 @@ static const OSSL_LIB_CTX_METHOD rand_smtc_ossl_ctx_method = { rand_smtc_crng_ossl_ctx_free, }; +/* 1 + ceil(20 / 2) */ +#define REPEAT_COUNT_TEST_THRESHOLD 11 /* * 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) + const unsigned char *entropy, size_t len) { - size_t i = 0; + size_t i; - if (len <= 0) + if (entropy == NULL || len == 0) return 0; - if (crngt->cnt == 0) { - crngt->last_bit = get_bit(pout, 0); - crngt->cnt = i = 1; - } - - for (; i < len * 8; i++) { - unsigned char bit = get_bit(pout, i); - if (bit == crngt->last_bit) { + for (i = 0; i < len; i++) { + if (entropy[i] == crngt->sample) { crngt->cnt++; - if (crngt->cnt >= REPEAT_COUNT_TEST_THRESHOLD) { - crngt->cnt = 0; - OSSL_SELF_TEST_oncorrupt_byte(st, &pout[i / 8]); + if (crngt->cnt >= REPEAT_COUNT_TEST_THRESHOLD) return 0; - } } else { - crngt->last_bit = bit; + crngt->sample = entropy[i]; crngt->cnt = 1; } } @@ -108,14 +151,15 @@ 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; OSSL_LIB_CTX *libctx = ossl_prov_ctx_get0_libctx(drbg->provctx); SMTC_CRNG_TEST_GLOBAL *crngt_glob = ossl_lib_ctx_get_data( @@ -127,6 +171,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. Since the min entropy is 2 bits per byte, the + * entropy factor is 4. + */ + bytes_needed = (entropy + 7) / 8 * 4; + 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 +195,52 @@ 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)) { + ossl_set_error_state(OSSL_SELF_TEST_TYPE_CRNG); + crng_test_pass = 0; + goto err; + } + + if (!sm3_df(crngt_glob->md_ctx, entbuf, CRNGT_BUFSIZ, p, + CRNGT_BUFSIZ)) + goto err; + + ossl_prov_cleanup_entropy(drbg->provctx, p, n); + } + + if (n != 0) { + ossl_prov_cleanup_entropy(drbg->provctx, p, n); + p = NULL; + goto err; + } - crng_test_pass = 1; + if (t < CRNGT_BUFSIZ) + memcpy(entp, buf, t); -err: + 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..d2dd1cf4d 100644 --- a/providers/smtc/self_test.c +++ b/providers/smtc/self_test.c @@ -8,14 +8,19 @@ */ #include +#include #include #include #include +#include #include +#include #include "internal/cryptlib.h" #include +#include #include #include "crypto/evp.h" +#include "crypto/rand.h" #include "internal/e_os.h" #include "internal/thread_once.h" #include "prov/providercommon.h" @@ -28,15 +33,23 @@ #include "../../crypto/evp/evp_local.h" /* 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" +#define INTEGRITY_BUF_SIZE 4096 +#define SMTC_PASSWD_LEN 64 +#define SMTC_AUTH_SALT_LEN 64 +#define SMTC_AUTH_KEY_LEN 64 +#define SMTC_AUTH_ID "SMTC" +#define SMTC_AUTH_TEXT1 "login" +#define SMTC_AUTH_TEXT2 "_admin_" + +#define SMTC_AUTH_TIMEOUT 60 + +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 unsigned char smtc_passwd[] = {SMTC_DEFAULT_PASSWORD_ELEMENTS}; static CRYPTO_ONCE smtc_self_test_init = CRYPTO_ONCE_STATIC_INIT; DEFINE_RUN_ONCE_STATIC(do_smtc_self_test_init) @@ -52,7 +65,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,83 +75,199 @@ 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; } #define PASSWD_BUF_SIZE 1024 -static int verify_password(OSSL_LIB_CTX *libctx, unsigned char *password, - size_t pass_len, unsigned char *salt, - size_t salt_len) +static int do_auth(time_t ts, const char *text2, unsigned char *mac, + size_t mac_len, const unsigned char *mac_key, + size_t mac_key_len) { - int ret = 0; - char passphrase[PASSWD_BUF_SIZE]; - EVP_MD_CTX *mctx = NULL; - unsigned char buf[EVP_MAX_MD_SIZE]; + int ok = 0; + time_t now = time(NULL); + char buf[128]; + unsigned char md[EVP_MAX_MD_SIZE]; + unsigned int md_len; + int buflen; + + if (ts > now || now - ts > SMTC_AUTH_TIMEOUT) + return 0; + + if (text2 == NULL || strcmp(text2, SMTC_AUTH_TEXT2) != 0) + return 0; + + buflen = snprintf(buf, sizeof(buf), "%ld%s%s", ts, SMTC_AUTH_ID, + SMTC_AUTH_TEXT1); + if (buflen < 0 || buflen >= (int)sizeof(buf)) + return 0; + + if (HMAC(EVP_sm3(), mac_key, mac_key_len, (const unsigned char *)buf, + buflen, md, &md_len) == NULL) + goto end; + + if (md_len != mac_len || memcmp(md, mac, md_len) != 0) { + OSSL_TRACE(SMTC, "Incorrect password\n"); + goto end; + } + + ok = 1; +end: + return ok; +} + +static int verify_password(OSSL_LIB_CTX *libctx, const char *conf_key, + const char *conf_salt, const char *kek, + const char *eng) +{ + int ok = 0; + time_t ts; + unsigned char buf[128]; + unsigned char *mac_key = NULL, *salt = NULL; + long mac_key_len, salt_len; + char passphrase[SMTC_PASSWD_LEN]; + unsigned char key[SMTC_AUTH_KEY_LEN]; + unsigned char mkey[SMTC_AUTH_KEY_LEN]; + int buflen; + size_t outlen; + unsigned char mac[EVP_MAX_MD_SIZE]; + unsigned int maclen; + ENGINE *engine = NULL; + BIO *bio = NULL; + EVP_PKEY *pkek = NULL; + EVP_PKEY_CTX *ctx = NULL; + + if (conf_key == NULL && conf_salt == NULL) { + if (EVP_read_pw_string(passphrase, sizeof(passphrase), + "Enter password: ", 0) != 0) + goto end; + + if (memcmp(passphrase, smtc_passwd, sizeof(smtc_passwd)) != 0) { + OSSL_TRACE(SMTC, "Incorrect password\n"); + goto end; + } + + ok = 1; + goto end; + } + + if (conf_key == NULL || conf_salt == NULL) + goto end; + + mac_key = OPENSSL_hexstr2buf(conf_key, &mac_key_len); + if (mac_key == NULL) + goto end; - if (password == NULL || pass_len != SM3_DIGEST_LENGTH || salt == NULL - || salt_len != SM3_DIGEST_LENGTH) + salt = OPENSSL_hexstr2buf(conf_salt, &salt_len); + if (salt == NULL || salt_len != SMTC_AUTH_SALT_LEN) goto end; + ts = time(NULL); + if (EVP_read_pw_string(passphrase, sizeof(passphrase), "Enter password: ", 0) != 0) goto end; - if ((mctx = EVP_MD_CTX_new()) == NULL - || !EVP_DigestInit_ex(mctx, EVP_sm3(), NULL) - || !EVP_DigestUpdate(mctx, salt, salt_len) - || !EVP_DigestUpdate(mctx, passphrase, strlen(passphrase)) - || !EVP_DigestFinal_ex(mctx, buf, NULL)) + if (PKCS5_PBKDF2_HMAC(passphrase, strlen(passphrase), salt, salt_len, + 10000, EVP_sm3(), sizeof(key), key) != 1) goto end; - if (memcmp(buf, password, pass_len)) + buflen = snprintf((char *)buf, sizeof(buf), "%ld%s%s", ts, SMTC_AUTH_ID, + SMTC_AUTH_TEXT1); + if (buflen < 0 || buflen >= (int)sizeof(buf)) goto end; - ret = 1; + if (HMAC(EVP_sm3(), key, sizeof(key), buf, buflen, mac, &maclen) == NULL) + goto end; + + if (eng) { + engine = ENGINE_by_id(eng); + if (engine == NULL) + goto end; + } + + if (engine) { + pkek = ENGINE_load_private_key(engine, kek, NULL, NULL); + } else { + bio = BIO_new_mem_buf(kek, strlen(kek)); + if (bio == NULL) + goto end; + + pkek = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL); + } + + if (pkek == NULL) + goto end; + + ctx = EVP_PKEY_CTX_new(pkek, engine); + if (ctx == NULL) + goto end; + + if (EVP_PKEY_decrypt_init(ctx) != 1 + || EVP_PKEY_decrypt(ctx, NULL, &outlen, mac_key, mac_key_len) != 1 + || outlen != sizeof(mkey) + || EVP_PKEY_decrypt(ctx, mkey, &outlen, mac_key, mac_key_len) != 1) + goto end; + + if (do_auth(ts, SMTC_AUTH_TEXT2, mac, maclen, mkey, outlen) != 1) + goto end; + + ok = 1; end: - EVP_MD_CTX_free(mctx); - return ret; + if (!ok) { + OSSL_TRACE(SMTC, "Authentication failed\n"); + ossl_sleep(3000); + } + EVP_PKEY_CTX_free(ctx); + OPENSSL_free(mac_key); + OPENSSL_free(salt); + ENGINE_free(engine); + EVP_PKEY_free(pkek); + BIO_free_all(bio); + return ok; } int smtc_prov_get_state(void) @@ -163,80 +292,95 @@ static void smtc_set_state(int state) } } -static int get_bit(const unsigned char *buf, int m) +/* + * GM/T 0105-2021 Appendix D.3, Adaptive Proportion Test + */ +static int smtc_adaptive_proportion_test(const unsigned char *entropy, + size_t len, int W, int C) { - if (m < 0) + size_t i; + int cnt = 0; + unsigned char sample = 0; + + if (entropy == NULL) return 0; - return (buf[m / 8] << (m % 8) >> 7) & 1; + for (i = 0; i < len; i++) { + if (i % W == 0) { + sample = entropy[i]; + cnt = 1; + } else if (entropy[i] == sample) { + cnt++; + if (cnt >= C) + return 0; + } + } + + return 1; } -/* - * GM/T 0105-2021 Appendix D.3, Adaptive Proportion Test - */ 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; - unsigned char buf[W / 8]; - size_t left = sizeof(buf); - size_t len, entropy_len; - int sample; + int ok = 0; unsigned char *entropy = NULL; - EVP_RAND *rand = NULL; - EVP_RAND_CTX *ctx = NULL; - PROV_DRBG *drbg; + size_t ret, len = 1024, W = 512; OSSL_SELF_TEST_onbegin(st, "Poweron_RNG_Test", "RNG"); - rand = EVP_RAND_fetch(libctx, "HASH-DRBG", NULL); - if (rand == NULL) - goto end; - - ctx = EVP_RAND_CTX_new(rand, NULL); - if (ctx == NULL) +#if defined(OPENSSL_RAND_SEED_RTCODE) + ret = ossl_rand_get_entropy_from_source(RAND_ENTROPY_SOURCE_RTCODE, + &entropy, 0, len, len); + if (ret == len) { + /* Entropy = 2, W = 512, C = 177 */ + if (!smtc_adaptive_proportion_test(entropy, len, W, 177)) + goto end; + } else { goto end; + } - drbg = (PROV_DRBG *)ctx->algctx; - if (drbg == NULL) - goto end; + ossl_rand_cleanup_entropy(NULL, entropy, len); + entropy = NULL; +#endif - while (left > 0) { - entropy_len - = ossl_prov_get_entropy(drbg->provctx, &entropy, left * 8, - drbg->min_entropylen, drbg->max_entropylen); - if (entropy_len == 0) +#if defined(OPENSSL_RAND_SEED_RTMEM) + entropy = NULL; + ret = ossl_rand_get_entropy_from_source(RAND_ENTROPY_SOURCE_RTMEM, + &entropy, 0, len, len); + if (ret == len) { + /* Entropy = 2, W = 512, C = 177 */ + if (!smtc_adaptive_proportion_test(entropy, len, W, 177)) goto end; + } else { + goto end; + } - len = entropy_len > left ? left : entropy_len; - memcpy(buf + (sizeof(buf) - left), entropy, len); - left -= len; + ossl_rand_cleanup_entropy(NULL, entropy, len); + entropy = NULL; +#endif - ossl_prov_cleanup_entropy(drbg->provctx, entropy, entropy_len); - entropy = NULL; +#if defined(OPENSSL_RAND_SEED_RTSOCK) + ret = ossl_rand_get_entropy_from_source(RAND_ENTROPY_SOURCE_RTSOCK, + &entropy, 0, len, len); + if (ret == len) { + /* Entropy = 2, W = 512, C = 177 */ + if (!smtc_adaptive_proportion_test(entropy, len, W, 177)) + goto end; + } else { + goto end; } - sample = get_bit(buf, 0); - cnt = 1; + ossl_rand_cleanup_entropy(NULL, entropy, len); + entropy = NULL; +#endif - for (i = 1; i < W; i++) { - int cur = get_bit(buf, i); - if (cur == sample) { - cnt++; - if (cnt >= C) - goto end; - } else { - sample = cur; - cnt = 1; - } + ok = 1; +end: + if (entropy) { + ossl_rand_cleanup_entropy(NULL, entropy, ret); + entropy = NULL; } - res = 1; -end: - OSSL_SELF_TEST_onend(st, res); - EVP_RAND_CTX_free(ctx); - EVP_RAND_free(rand); - return res; + return ok; } /* This API is triggered either on loading of the SMTC module or on demand */ @@ -244,11 +388,9 @@ int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test) { int ok = 0; int loclstate; - long checksum_len; - long pass_len, salt_len; + long siglen; OSSL_CORE_BIO *bio_module = NULL; - unsigned char *module_checksum = NULL; - unsigned char *password = NULL, *salt = NULL; + unsigned char *module_sig = NULL; OSSL_SELF_TEST *ev = NULL; if (!RUN_ONCE(&smtc_self_test_init, do_smtc_self_test_init)) @@ -285,25 +427,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; } @@ -339,27 +480,16 @@ int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test) if (st->verify_pass == NULL || atoi(st->verify_pass) != 0) #endif if (loclstate == SMTC_STATE_SELFTEST_WHILE_IN_INIT) { - if (st->admin_pass == NULL || st->admin_salt == NULL) { - ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_CONFIG_DATA); - goto end; - } - - password = OPENSSL_hexstr2buf(st->admin_pass, &pass_len); - salt = OPENSSL_hexstr2buf(st->admin_salt, &salt_len); - if (password == NULL || salt == NULL) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CONFIG_DATA); - goto end; - } - - if (!verify_password(st->libctx, password, pass_len, salt, salt_len)) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CONFIG_DATA); + if (!verify_password(st->libctx, st->auth_key, st->auth_salt, st->kek, + st->eng)) { + 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,10 +503,30 @@ 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; + if (!RUN_ONCE(&smtc_self_test_init, do_smtc_self_test_init)) + return 0; + if (!CRYPTO_THREAD_read_lock(smtc_state_lock)) return 0; res = smtc_state == SMTC_STATE_RUNNING diff --git a/providers/smtc/self_test.h b/providers/smtc/self_test.h index 3001fa92b..d06493b45 100644 --- a/providers/smtc/self_test.h +++ b/providers/smtc/self_test.h @@ -19,15 +19,17 @@ 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 */ - const char *rng_poweron_test; /* 熵源上电健康测试 */ - const char *rng_continuous_test; /* 熵源连续健康测试 */ - const char *randomness_poweron_test; /* 随机数上电自检 */ + const char *auth_key; /* key of HMAC, PBKDF(password, salt) */ + const char *auth_salt; /* Salt of PBKDF */ + const char *kek; /* key for encrypting HMAC key */ + const char *eng; /* Engine ID */ + const char *rng_poweron_test; /* Entropy power-on health test */ + const char *rng_continuous_test; /* Entropy continuous health test */ + const char *randomness_poweron_test; /* Random power-on self-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..4bdd8a680 100644 --- a/providers/smtc/self_test_data.inc +++ b/providers/smtc/self_test_data.inc @@ -66,7 +66,7 @@ typedef struct st_kat_kdf_st { size_t expected_len; } ST_KAT_KDF; -typedef struct st_kat_drbg_st { +typedef struct st_kat_smtc_drbg_st { const char *desc; const char *algorithm; const char *param_name; @@ -85,9 +85,17 @@ typedef struct st_kat_drbg_st { size_t entropyaddin1len; const unsigned char *entropyaddin2; size_t entropyaddin2len; + const unsigned char *V; + size_t Vlen; + const unsigned char *C; + size_t Clen; + const unsigned char *V1; + size_t V1len; + const unsigned char *C1; + size_t C1len; const unsigned char *expected; size_t expectedlen; -} ST_KAT_DRBG; +} ST_KAT_SMTC_DRBG; typedef struct st_kat_kas_st { const char *desc; @@ -105,7 +113,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; @@ -364,21 +375,60 @@ static const unsigned char drbg_hash_sm3_pr_addin1[] = { 0xb2, 0x94, 0x73, 0xe2, 0xfd, 0x39, 0x51, 0x2e, 0xad, 0x45, 0x69, 0xee, 0xe3, 0xe3, 0x80, 0x33, 0x14, 0xab, 0xa7, 0xa3 }; +static const unsigned char drbg_hash_sm3_V_expected[] = { + 0xd3, 0x51, 0x2a, 0xe4, 0x49, 0x45, 0x5b, 0xfc, 0x59, 0x63, 0x5c, 0xad, + 0xd2, 0xd9, 0xe0, 0xa3, 0x17, 0x05, 0xbb, 0x0e, 0x11, 0xc1, 0xc8, 0xce, + 0xfe, 0x6f, 0xd8, 0x87, 0x90, 0x0b, 0xfb, 0x95, 0xf0, 0x7c, 0xb2, 0x4c, + 0x85, 0x93, 0x99, 0x66, 0x89, 0x4f, 0xd6, 0x44, 0x6f, 0xb4, 0xfe, 0xb1, + 0xb1, 0x5b, 0x57, 0xd5, 0x88, 0x70, 0x3c, +}; +static const unsigned char drbg_hash_sm3_C_expected[] = { + 0xf6, 0x8a, 0x6f, 0x03, 0x6f, 0x26, 0xbb, 0x90, 0xc4, 0x3d, 0x08, 0x0e, + 0x99, 0x9b, 0x69, 0xba, 0x59, 0xc1, 0x1e, 0xa7, 0xd8, 0xbb, 0xb4, 0xe8, + 0x59, 0xbc, 0x77, 0x69, 0x27, 0x73, 0xbd, 0x66, 0xf4, 0xc2, 0xac, 0xd4, + 0xc7, 0x80, 0xb6, 0xf7, 0xcf, 0xe3, 0x51, 0xff, 0x0e, 0xec, 0x77, 0xed, + 0x45, 0xb3, 0x3b, 0xb1, 0xd6, 0x64, 0xce, +}; +static const unsigned char drbg_hash_sm3_V1_expected[] = { + 0x8a, 0xb9, 0x3c, 0x9d, 0x9f, 0xfc, 0xc0, 0x64, 0x54, 0x58, 0x48, 0x4c, + 0xa0, 0x0c, 0x01, 0x5f, 0x97, 0x24, 0xc7, 0x07, 0xed, 0x2c, 0x67, 0x5d, + 0xc5, 0xce, 0x7c, 0xf7, 0xba, 0x40, 0x96, 0x2a, 0x77, 0x5a, 0x9c, 0x79, + 0xa0, 0x37, 0xbb, 0xec, 0xb4, 0x48, 0xc0, 0xf2, 0x82, 0x03, 0x33, 0x7c, + 0xa9, 0x95, 0xb3, 0x9f, 0x9f, 0x6f, 0x66, +}; +static const unsigned char drbg_hash_sm3_C1_expected[] = { + 0xe7, 0xca, 0x05, 0x6c, 0x83, 0xcb, 0x42, 0x0e, 0x19, 0xf2, 0x9b, 0xdb, + 0x14, 0x11, 0xf3, 0x8a, 0x07, 0x13, 0xf4, 0x58, 0x43, 0x6d, 0xd6, 0x15, + 0x6e, 0xea, 0x6a, 0x77, 0x45, 0x6f, 0x24, 0x1b, 0xcf, 0x04, 0x15, 0xa1, + 0x8e, 0x63, 0x48, 0x67, 0xae, 0x72, 0x4d, 0xa0, 0xbf, 0x26, 0xae, 0x7f, + 0x5e, 0xc0, 0x97, 0x53, 0x4b, 0x33, 0x63, +}; static const unsigned char drbg_hash_sm3_pr_expected[] = { - 0xc0, 0xd1, 0xef, 0x6f, 0x52, 0xf4, 0x2a, 0xd7, 0xa1, 0xaa, 0x91, 0xbc, - 0x11, 0x7b, 0xdc, 0xa0, 0x74, 0xc0, 0xda, 0x26, 0xa9, 0xba, 0xb1, 0x6a, - 0x0e, 0x43, 0xa0, 0x1b, 0x7d, 0xa5, 0x85, 0xa9, 0xb5, 0x1b, 0xa7, 0xa3, - 0x81, 0x03, 0x70, 0x41, 0x38, 0xf9, 0x40, 0xb4, 0x20, 0x11, 0x99, 0x06, - 0x25, 0x14, 0x88, 0x0a, 0xf7, 0xd6, 0x03, 0x5d, 0x08, 0x13, 0xba, 0x7e, - 0x78, 0xb1, 0x76, 0x75, 0x49, 0x29, 0x7a, 0xf9, 0x54, 0x13, 0xcc, 0x6d, - 0x38, 0x63, 0x1a, 0xd5, 0x9f, 0xc4, 0x1a, 0xdb, 0x6d, 0x10, 0x68, 0x8d, - 0xdf, 0x64, 0xdc, 0x7e, 0xe2, 0x4a, 0x16, 0xde, 0x9a, 0x82, 0x11, 0x00, - 0xd5, 0xc9, 0x77, 0xf8, 0x81, 0x64, 0x66, 0xdb, 0x2a, 0x40, 0x27, 0xc0, - 0x61, 0xb2, 0x05, 0xc4, 0xa7, 0x66, 0xa3, 0x64, 0x61, 0x29, 0xb2, 0x3f, - 0x11, 0x8c, 0x50, 0xbf, 0x8b, 0x64, 0xc0, 0x72, -}; - -static const ST_KAT_DRBG st_kat_drbg_tests[] = + 0xbb, 0xb8, 0x89, 0x31, 0x02, 0x7a, 0xf6, 0x59, 0x27, 0xd6, 0x67, 0x98, + 0xe0, 0xd3, 0xc0, 0x49, 0x38, 0x71, 0x2e, 0x4d, 0x85, 0x62, 0x88, 0x2c, + 0xb4, 0xe3, 0x4d, 0x6f, 0x08, 0xa1, 0xac, 0xcc, 0xff, 0x2b, 0x53, 0xca, + 0x38, 0x52, 0x0b, 0xb9, 0xab, 0x58, 0x87, 0x7c, 0x1c, 0x57, 0xf2, 0x36, + 0xfe, 0x6c, 0x81, 0x91, 0x9e, 0x62, 0x88, 0xb1, 0x8c, 0x76, 0x94, 0xc5, + 0x23, 0x36, 0x48, 0xa8, 0x57, 0xcc, 0x2d, 0x7d, 0x02, 0x9b, 0xc3, 0x9d, + 0xd4, 0x6b, 0x60, 0x63, 0x15, 0xfc, 0x1b, 0xa0, 0x04, 0x17, 0x56, 0x31, + 0x78, 0x66, 0x10, 0xe7, 0x22, 0xe7, 0x53, 0x7d, 0x4f, 0xcd, 0x90, 0x02, + 0xd4, 0xfa, 0x1b, 0xda, 0xca, 0x66, 0xd2, 0x25, 0xa2, 0x47, 0x97, 0x87, + 0x26, 0xbc, 0xeb, 0x6c, 0x18, 0x58, 0x62, 0x07, 0x61, 0x45, 0xf0, 0x76, + 0xd5, 0x1a, 0x21, 0xba, 0xfc, 0x42, 0xf2, 0xc6, 0x98, 0x63, 0x49, 0x45, + 0xde, 0xdb, 0xfa, 0x14, 0x34, 0xc7, 0x30, 0xbe, 0x07, 0xfd, 0xee, 0x55, + 0x30, 0xce, 0xab, 0x54, 0x61, 0xee, 0xcd, 0xd9, 0xdd, 0x34, 0x26, 0x47, + 0xed, 0xf4, 0xbb, 0xa8, 0x32, 0xc6, 0xf6, 0xbc, 0x96, 0xc3, 0x56, 0x32, + 0xf1, 0x4d, 0x3b, 0x8f, 0x10, 0x01, 0x02, 0x69, 0x25, 0xff, 0x4a, 0x71, + 0x6e, 0x8d, 0x78, 0xd7, 0x1e, 0xb1, 0xb7, 0x17, 0x3f, 0x30, 0xd4, 0xa0, + 0x85, 0xe8, 0x87, 0xba, 0x63, 0x63, 0x9f, 0x32, 0x52, 0x27, 0x77, 0xcb, + 0x91, 0x01, 0x0d, 0xbd, 0x29, 0x06, 0xa4, 0x7d, 0x51, 0x58, 0xe3, 0xc1, + 0x29, 0x14, 0xeb, 0x51, 0x30, 0x45, 0xb0, 0x19, 0x2b, 0x4b, 0xe3, 0x9d, + 0xea, 0x40, 0x13, 0xb0, 0xcc, 0x9f, 0x2b, 0xda, 0xe3, 0xd7, 0x49, 0xdd, + 0x90, 0x46, 0xcc, 0x32, 0x28, 0xcc, 0xd5, 0x2e, 0x3f, 0x10, 0x79, 0x05, + 0xa9, 0x28, 0xa0, 0x79, +}; + +static const ST_KAT_SMTC_DRBG st_kat_drbg_tests[] = { { OSSL_SELF_TEST_DESC_DRBG_HASH, @@ -390,6 +440,10 @@ static const ST_KAT_DRBG st_kat_drbg_tests[] = ITM(drbg_hash_sm3_pr_entropyinpr1), ITM(drbg_hash_sm3_pr_addin0), ITM(drbg_hash_sm3_pr_addin1), + ITM(drbg_hash_sm3_V_expected), + ITM(drbg_hash_sm3_C_expected), + ITM(drbg_hash_sm3_V1_expected), + ITM(drbg_hash_sm3_C1_expected), ITM(drbg_hash_sm3_pr_expected) }, }; @@ -703,6 +757,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 +798,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 +827,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..9e6e2443e 100644 --- a/providers/smtc/self_test_kats.c +++ b/providers/smtc/self_test_kats.c @@ -12,10 +12,13 @@ #include #include #include +#include "crypto/evp.h" #include "internal/cryptlib.h" #include "internal/nelem.h" #include "self_test.h" #include "self_test_data.inc" +#include "../implementations/rands/drbg_local.h" +#include "../../crypto/evp/evp_local.h" static int self_test_digest(const ST_KAT_DIGEST *t, OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) @@ -247,13 +250,15 @@ static int self_test_kdf(const ST_KAT_KDF *t, OSSL_SELF_TEST *st, return ret; } -static int self_test_drbg(const ST_KAT_DRBG *t, OSSL_SELF_TEST *st, +static int self_test_drbg(const ST_KAT_SMTC_DRBG *t, OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) { int ret = 0; unsigned char out[256]; EVP_RAND *rand; EVP_RAND_CTX *test = NULL, *drbg = NULL; + PROV_DRBG *prov_drbg = NULL; + PROV_DRBG_HASH *hash_drbg = NULL; unsigned int strength = 256; int prediction_resistance = 1; /* Causes a reseed */ OSSL_PARAM drbg_params[3] = { @@ -289,9 +294,6 @@ static int self_test_drbg(const ST_KAT_DRBG *t, OSSL_SELF_TEST *st, drbg_params[0] = OSSL_PARAM_construct_utf8_string(t->param_name, t->param_value, 0); - /* This is only used by HMAC-DRBG but it is ignored by the others */ - drbg_params[1] = - OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_MAC, "HMAC", 0); if (!EVP_RAND_CTX_set_params(drbg, drbg_params)) goto err; @@ -308,6 +310,18 @@ static int self_test_drbg(const ST_KAT_DRBG *t, OSSL_SELF_TEST *st, NULL)) goto err; + prov_drbg = (PROV_DRBG *)drbg->algctx; + if (prov_drbg == NULL) + goto err; + + hash_drbg = (PROV_DRBG_HASH *)prov_drbg->data; + if (hash_drbg == NULL) + goto err; + + if (memcmp(hash_drbg->V, t->V, t->Vlen) != 0 + || memcmp(hash_drbg->C, t->C, t->Clen) != 0) + goto err; + drbg_params[0] = OSSL_PARAM_construct_octet_string(OSSL_RAND_PARAM_TEST_ENTROPY, (void *)t->entropyinpr1, @@ -315,9 +329,13 @@ static int self_test_drbg(const ST_KAT_DRBG *t, OSSL_SELF_TEST *st, if (!EVP_RAND_CTX_set_params(test, drbg_params)) goto err; - if (!EVP_RAND_generate(drbg, out, t->expectedlen, strength, - prediction_resistance, - t->entropyaddin1, t->entropyaddin1len)) + if (EVP_RAND_reseed(drbg, prediction_resistance, + t->entropyinpr1, t->entropyinpr1len, + t->entropyaddin1, t->entropyaddin1len) != 1) + goto err; + + if (memcmp(hash_drbg->V, t->V1, t->V1len) != 0 + || memcmp(hash_drbg->C, t->C1, t->C1len) != 0) goto err; drbg_params[0] = @@ -369,11 +387,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 +406,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 +416,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 +424,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 +510,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 +520,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..68dec4216 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,7 @@ * 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{SMTCPUBKEY} -}" -#define SMTC_KEY_STRING "{- $config{SMTCKEY} -}" +#define SMTC_DEFAULT_PASSWORD_ELEMENTS \ + {- join(', ', map { sprintf '0x%02x', ord($_) } split //, $config{SMTCPASSWD}) -} diff --git a/providers/smtc/smtcprov.c b/providers/smtc/smtcprov.c index db5a92398..e34c8c844 100644 --- a/providers/smtc/smtcprov.c +++ b/providers/smtc/smtcprov.c @@ -8,9 +8,11 @@ */ #include +#include #include #include #include +#include #include #include #include "internal/cryptlib.h" @@ -25,6 +27,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. @@ -58,6 +67,40 @@ typedef struct smtc_global_st { SELF_TEST_POST_PARAMS selftest_params; } SMTC_GLOBAL; +#ifndef OPENSSL_NO_STATIC_ENGINE +# ifndef OPENSSL_NO_ATF_SLIBCE +#define ATF_SLIBCE_CMD_LOAD_str "engine_load" +#define ATF_SLIBCE_CMD_ALLOC_PRSRC_str "engine_alloc_prsrc" + +static CRYPTO_ONCE engine_atf_slibce = CRYPTO_ONCE_STATIC_INIT; +DEFINE_RUN_ONCE_STATIC(ossl_init_engine_atf_slibce) +{ + OSSL_TRACE(SMTC, "engine_load_atf_slibce_int()\n"); + extern ENGINE* engine_atf_slibce_load(const char* engine_name); + + engine = engine_atf_slibce_load("atf_slibce"); + + if (engine == NULL) { + OSSL_TRACE(SMTC, "Failed to load atf_slibce engine\n"); + return 0; + } + + if(!ENGINE_ctrl_cmd_string(pengine, ATF_SLIBCE_CMD_LOAD_str, NULL, 0)){ + OSSL_TRACE(SMTC, "Failed to execute cmd: ATF_SLIBCE_CMD_LOAD_str\n"); + return 0; + } + + if(!ENGINE_ctrl_cmd_string(pengine, ATF_SLIBCE_CMD_ALLOC_PRSRC_str, NULL, 0)){ + OSSL_TRACE(SMTC, "Failed to execute cmd: " + "ATF_SLIBCE_CMD_ALLOC_PRSRC_str\n"); + return 0; + } + + return 1; +} +# endif +#endif + static void *smtc_prov_ossl_ctx_new(OSSL_LIB_CTX *libctx) { SMTC_GLOBAL *fgbl = OPENSSL_zalloc(sizeof(*fgbl)); @@ -91,28 +134,36 @@ static const OSSL_PARAM smtc_param_types[] = { static int smtc_get_params_from_core(SMTC_GLOBAL *fgbl) { - OSSL_PARAM core_params[11], *p = core_params; + OSSL_PARAM core_params[13], *p = core_params; *p++ = OSSL_PARAM_construct_utf8_ptr( OSSL_PROV_SMTC_PARAM_MODULE_PATH, (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, sizeof(fgbl->selftest_params.show_selftest)); *p++ = OSSL_PARAM_construct_utf8_ptr( - OSSL_PROV_SMTC_PARAM_ADMIN_PASS, - (char **)&fgbl->selftest_params.admin_pass, - sizeof(fgbl->selftest_params.admin_pass)); + OSSL_PROV_SMTC_PARAM_AUTH_KEY, + (char **)&fgbl->selftest_params.auth_key, + sizeof(fgbl->selftest_params.auth_key)); + *p++ = OSSL_PARAM_construct_utf8_ptr( + OSSL_PROV_SMTC_PARAM_AUTH_SALT, + (char **)&fgbl->selftest_params.auth_salt, + sizeof(fgbl->selftest_params.auth_salt)); *p++ = OSSL_PARAM_construct_utf8_ptr( - OSSL_PROV_SMTC_PARAM_ADMIN_SALT, - (char **)&fgbl->selftest_params.admin_salt, - sizeof(fgbl->selftest_params.admin_salt)); + OSSL_PROV_SMTC_PARAM_AUTH_KEK, + (char **)&fgbl->selftest_params.kek, + sizeof(fgbl->selftest_params.kek)); + *p++ = OSSL_PARAM_construct_utf8_ptr( + OSSL_PROV_SMTC_PARAM_ENGINE, + (char **)&fgbl->selftest_params.eng, + sizeof(fgbl->selftest_params.eng)); *p++ = OSSL_PARAM_construct_utf8_ptr( OSSL_PROV_SMTC_PARAM_RNG_POWERON_TEST, (char **)&fgbl->selftest_params.rng_poweron_test, @@ -127,9 +178,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 +215,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; } @@ -244,14 +295,22 @@ static void set_self_test_cb(SMTC_GLOBAL *fgbl) static int smtc_self_test(void *provctx) { - SMTC_GLOBAL *fgbl = ossl_lib_ctx_get_data(ossl_prov_ctx_get0_libctx(provctx), - OSSL_LIB_CTX_SMTC_PROV_INDEX, - &smtc_prov_ossl_ctx_method); + SMTC_GLOBAL *fgbl = + ossl_lib_ctx_get_data(ossl_prov_ctx_get0_libctx(provctx), + OSSL_LIB_CTX_SMTC_PROV_INDEX, + &smtc_prov_ossl_ctx_method); set_self_test_cb(fgbl); return SELF_TEST_post(&fgbl->selftest_params, 1) ? 1 : 0; } +static int smtc_reset(void *provctx) +{ + // unload + // clear config + return 1; +} + /* * For the algorithm names, we use the following formula for our primary * names: @@ -286,8 +345,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 +371,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,29 +461,90 @@ 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 }, { OSSL_FUNC_PROVIDER_GET_CAPABILITIES, (void (*)(void))ossl_prov_get_capabilities }, { OSSL_FUNC_PROVIDER_SELF_TEST, (void (*)(void))smtc_self_test }, + { OSSL_FUNC_PROVIDER_RESET, (void (*)(void))smtc_reset }, { 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, @@ -426,10 +552,30 @@ int OSSL_provider_init_int(const OSSL_CORE_HANDLE *handle, { int ret; SMTC_GLOBAL *fgbl; - BIO_METHOD *corebiometh; + BIO_METHOD *corebiometh = NULL; 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]; + struct utmpx *cur; + + setutxent(); + while ((cur = getutxent()) != NULL) { + /* + * Root users are prohibited from logging in to prevent malicious + * tampering. + */ + if (strcmp(cur->ut_user, "root") == 0) { + OSSL_TRACE(SMTC, "root user detected, init failed\n"); + endutxent(); + return 0; + } + } + + endutxent(); memset(&selftest_params, 0, sizeof(selftest_params)); @@ -466,12 +612,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 +639,49 @@ 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; + +#ifndef OPENSSL_NO_STATIC_ENGINE +# ifndef OPENSSL_NO_ATF_SLIBCE + if (!RUN_ONCE(&engine_atf_slibce, ossl_init_engine_atf_slibce)) + goto err; +# endif +#endif + 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; diff --git a/util/libcrypto.num b/util/libcrypto.num index 8a538ff70..f944b42c0 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -5638,3 +5638,4 @@ SM2_THRESHOLD_sign3 5953 3_0_3 EXIST::FUNCTION:SM2_THRESHOLD SM2_THRESHOLD_decrypt1 5954 3_0_3 EXIST::FUNCTION:SM2_THRESHOLD SM2_THRESHOLD_decrypt2 5955 3_0_3 EXIST::FUNCTION:SM2_THRESHOLD SM2_THRESHOLD_decrypt3 5956 3_0_3 EXIST::FUNCTION:SM2_THRESHOLD +RAND_set_entropy_source 5957 3_0_3 EXIST::FUNCTION: