diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5c40b7209..6770edd3f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -209,7 +209,7 @@ jobs: - name: modprobe tls run: sudo modprobe tls - name: config - run: ./config --banner=Configured --strict-warnings no-ec enable-ssl-trace enable-zlib enable-zlib-dynamic enable-crypto-mdebug enable-crypto-mdebug-backtrace enable-egd enable-ktls enable-fips enable-ntls enable-optimize-chacha-choose enable-status enable-crypto-mdebug-count enable-cert-compression enable-delegated-credential enable-bn-method --with-rand-seed=getrandom,rtc && perl configdata.pm --dump + run: ./config --banner=Configured --strict-warnings no-ec enable-ssl-trace enable-zlib enable-zlib-dynamic enable-crypto-mdebug enable-crypto-mdebug-backtrace enable-egd enable-ktls enable-fips enable-ntls enable-optimize-chacha-choose enable-status enable-crypto-mdebug-count enable-cert-compression enable-delegated-credential enable-bn-method --with-rand-seed=rtcode,rtmem,rtsock && perl configdata.pm --dump - name: make run: make -s -j4 - name: make test diff --git a/.github/workflows/compiler-zoo.yml b/.github/workflows/compiler-zoo.yml index 59d37425e..c89fb0b27 100644 --- a/.github/workflows/compiler-zoo.yml +++ b/.github/workflows/compiler-zoo.yml @@ -76,8 +76,7 @@ jobs: - name: config run: | CC=${{ matrix.zoo.cc }} ./config --banner=Configured no-shared \ - -Wall -Werror enable-ntls enable-smtc enable-smtc-debug \ - --strict-warnings + -Wall -Werror enable-ntls --strict-warnings - name: config dump run: ./configdata.pm --dump diff --git a/.github/workflows/run-checker-ci.yml b/.github/workflows/run-checker-ci.yml index 71660df1e..b5f07a7b8 100644 --- a/.github/workflows/run-checker-ci.yml +++ b/.github/workflows/run-checker-ci.yml @@ -32,8 +32,6 @@ jobs: no-tls1_3, enable-trace enable-fips, enable-ntls, - enable-smtc enable-smtc-debug, - enable-ntls enable-smtc enable-smtc-debug, no-ts, no-ui, ] diff --git a/.github/workflows/run-checker-daily.yml b/.github/workflows/run-checker-daily.yml index 1a927a904..7888e6277 100644 --- a/.github/workflows/run-checker-daily.yml +++ b/.github/workflows/run-checker-daily.yml @@ -114,8 +114,6 @@ jobs: enable-zlib-dynamic, no-zlib-dynamic, enable-ntls, - enable-smtc enable-smtc-debug, - enable-ntls enable-smtc enable-smtc-debug, enable-ec_elgamal enable-twisted_ec_elgamal, enable-bulletproofs, enable-bulletproofs enable-nizk enable-zkp-gadget enable-ec_elgamal enable-twisted_ec_elgamal, diff --git a/.github/workflows/run-checker-merge.yml b/.github/workflows/run-checker-merge.yml index c5e0c3853..977e9fa52 100644 --- a/.github/workflows/run-checker-merge.yml +++ b/.github/workflows/run-checker-merge.yml @@ -27,8 +27,6 @@ jobs: enable-weak-ssl-ciphers, enable-zlib, enable-ntls, - enable-smtc enable-smtc-debug, - enable-ntls enable-smtc enable-smtc-debug, ] runs-on: ubuntu-latest steps: diff --git a/Configurations/00-base-templates.conf b/Configurations/00-base-templates.conf index 073867565..5111bbe50 100644 --- a/Configurations/00-base-templates.conf +++ b/Configurations/00-base-templates.conf @@ -50,6 +50,9 @@ my %targets=( my @defs = ( 'OPENSSL_BUILDING_OPENSSL' ); push @defs, "ZLIB" unless $disabled{zlib}; push @defs, "ZLIB_SHARED" unless $disabled{"zlib-dynamic"}; + + push @defs, "SDF_LIB" unless $disabled{"sdf-lib"}; + push @defs, "SDF_LIB_SHARED" unless $disabled{"sdf-lib-dynamic"}; return [ @defs ]; }, includes => @@ -57,6 +60,9 @@ my %targets=( my @incs = (); push @incs, $withargs{zlib_include} if !$disabled{zlib} && $withargs{zlib_include}; + + push @incs, $withargs{sdf_include} + if !$disabled{sdf_lib} && $withargs{sdf_include}; return [ @incs ]; }, }, diff --git a/Configure b/Configure index ce92fd517..1a2543fea 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} = 'Tongsuo123'; +$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; @@ -355,8 +360,6 @@ $config{tongsuo_prerelease} = $config{tongsuo_version} = "$config{tongsuo_major}.$config{tongsuo_minor}.$config{tongsuo_patch}"; $config{tongsuo_full_version} = "$config{tongsuo_version}$config{tongsuo_prerelease}"; -$config{tongsuo_smtc_info} = $version{TONGSUO_SMTC_INFO}; - die "erroneous version information in VERSION.dat: ", "$config{version}, $config{shlib_version}\n" unless (defined $version{MAJOR} @@ -404,6 +407,7 @@ my @dtls = qw(dtls1 dtls1_2); my @disablables = ( "acvp-tests", "afalgeng", + "atf_slibce", "asan", "asm", "async", @@ -474,6 +478,8 @@ my @disablables = ( "smtc-debug", "scrypt", "sctp", + "sdf-lib", + "sdf-lib-dynamic", "secure-memory", "shared", "siphash", @@ -588,8 +594,11 @@ 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", + "sdf-lib" => "default", + "sdf-lib-dynamic" => "default", ); # Note: => pair form used for aesthetics, not to truly make a hash table @@ -679,6 +688,7 @@ my @disable_cascades = ( # SMTC does not support ct for now # SMTC only support builtin module for now sub { !$disabled{"smtc"}} => [ "ct", "module" ], + "sdf-lib" => [ "sdf-lib-dynamic" ], ); # Avoid protocol support holes. Also disable all versions below N, if version @@ -796,7 +806,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) { @@ -914,6 +924,10 @@ while (@argvcopy) { delete $disabled{"zlib"}; } + elsif ($1 eq "sdf-lib-dynamic") + { + delete $disabled{"sdf-lib"}; + } my $algo = $1; delete $disabled{$algo}; @@ -1011,6 +1025,18 @@ while (@argvcopy) push @seed_sources, $x; } } + elsif (/^--with-atf_slibce-lib=(.*)$/) + { + $withargs{atf_slibce_lib}=$1; + } + elsif (/^--with-sdf-lib=(.*)$/) + { + $withargs{sdf_lib}=$1; + } + elsif (/^--with-sdf-include=(.*)$/) + { + $withargs{sdf_include}=$1; + } elsif (/^--fips-key=(.*)$/) { $user{FIPSKEY}=lc($1); @@ -1021,15 +1047,25 @@ 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} = do { local $/; <$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 (/^--smtc-info=(.*)$/) + { + $config{tongsuo_smtc_info} = $1; } elsif (/^--banner=(.*)$/) { diff --git a/VERSION.dat b/VERSION.dat index 3b6f7ac66..d83daf21b 100644 --- a/VERSION.dat +++ b/VERSION.dat @@ -8,5 +8,4 @@ SHLIB_VERSION=3 TONGSUO_MAJOR=8 TONGSUO_MINOR=5 TONGSUO_PATCH=0 -TONGSUO_PRE_RELEASE_TAG=dev -TONGSUO_SMTC_INFO= +TONGSUO_PRE_RELEASE_TAG=dev \ No newline at end of file diff --git a/apps/build.info b/apps/build.info index 56ac5a3a3..80f1868de 100644 --- a/apps/build.info +++ b/apps/build.info @@ -85,6 +85,10 @@ IF[{- !$disabled{apps} -}] DEFINE[openssl]=SMTC_MODULE ENDIF + IF[{- !$disabled{'sdf_lib'} -}] + $OPENSSLSRC=$OPENSSLSRC sdf.c + ENDIF + # The nocheck attribute is picked up by progs.pl as a signal not to look # at that file; some systems may have locked it as the output file, and # therefore don't allow it to be read at the same time, making progs.pl diff --git a/apps/enc.c b/apps/enc.c index a1ec6b723..5b7bc994a 100644 --- a/apps/enc.c +++ b/apps/enc.c @@ -534,6 +534,7 @@ int enc_main(int argc, char **argv) BIO_printf(bio_err, "iv undefined\n"); goto end; } + if (hkey != NULL) { if (!set_hex(hkey, key, EVP_CIPHER_get_key_length(cipher))) { BIO_printf(bio_err, "invalid hex key value\n"); diff --git a/apps/mod.c b/apps/mod.c index 65cf4220e..575667a45 100644 --- a/apps/mod.c +++ b/apps/mod.c @@ -6,35 +6,45 @@ * in the file LICENSE in the source distribution or at * https://github.com/Tongsuo-Project/Tongsuo/blob/master/LICENSE.txt */ -#include +#include "internal/deprecated.h" +#include +#include +#include #include "apps.h" #include "progs.h" #include #include #include +#include #include #include #include #include +#include #include #include "internal/smtc_names.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; + char *sig; + const char *kek; + const char *eng; + const char *syslog; + char *key; + char *salt; + const char *rand_poweron_test; #ifndef OPENSSL_NO_SMTC_DEBUG - int verify_pass; + const char *verify_sig; + const char *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; } SMTC_CONF; typedef enum OPTION_choice { @@ -42,82 +52,131 @@ typedef enum OPTION_choice { OPT_EOF = 0, OPT_HELP, OPT_TEST, + OPT_RESET, OPT_MODULE, OPT_PROV_NAME, - OPT_SECTION_NAME, + OPT_SIGFILE, + OPT_STATUS, + OPT_INSTALL, + OPT_KEK, + OPT_ENGINE, + OPT_PASS, OPT_OUT, - OPT_SHOW_SELFTEST, #ifndef OPENSSL_NO_SMTC_DEBUG - OPT_NO_PASS, + OPT_NO_VERIFY, + OPT_NO_AUTH, + OPT_NO_RAND_POWERON_TEST, #endif - OPT_R_ENUM } OPTION_CHOICE; const OPTIONS mod_options[] = { OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, + {"install", OPT_INSTALL, '-', "Install module, generate config file"}, {"test", OPT_TEST, '-', "Self test"}, - {"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"}, + {"status", OPT_STATUS, '-', "Display the status of the module"}, + {"reset", OPT_RESET, '-', "Reset module, clear salt and password"}, + {"module", OPT_MODULE, 's', "File path of the module"}, + {"provider_name", OPT_PROV_NAME, 's', "Provider name"}, + {"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"}, #ifndef OPENSSL_NO_SMTC_DEBUG - {"no_pass", OPT_NO_PASS, '-', "Do not setup password"}, + {"no_verify", OPT_NO_VERIFY, '-', "Do not verify the integrity of the software"}, + {"no_auth", OPT_NO_AUTH, '-', "No authentication required for user login"}, + {"no_rand_poweron_test", OPT_NO_RAND_POWERON_TEST, '-', "No random poweron test"}, #endif + + OPT_SECTION("Input"), + {"sigfile", OPT_SIGFILE, '<', "Signature file"}, + OPT_SECTION("Output"), {"out", OPT_OUT, '>', "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 + ) { + BIO_printf(bio_err, "Failed to encrypt auth key\n"); + goto end; + } + + *auth_key = enc_key; + enc_key = NULL; + *auth_key_len = outlen; } + + ok = 1; + OSSL_syslog(LOG_NOTICE, "Setup password success\n"); 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,20 +189,6 @@ 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) -{ - int ret; - char *hexstr = NULL; - - 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; -} - /* * Outputs a smtc related config file. * Returns 1 if the config file is written otherwise it returns 0 on error. @@ -156,34 +201,46 @@ 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)) + || BIO_printf(out, "%s = %s\n", OSSL_PROV_SMTC_PARAM_MODULE_SIG, + sc->sig) <= 0) goto end; - if (sc->show_selftest) { - if (BIO_printf(out, "%s = 1\n", OSSL_PROV_SMTC_PARAM_SHOW_SELFTEST) - <= 0) - goto end; - } else { - if (BIO_printf(out, "%s = 0\n", OSSL_PROV_SMTC_PARAM_SHOW_SELFTEST) - <= 0) - goto end; - } + if (sc->kek && BIO_printf(out, "%s = %s\n", OSSL_PROV_SMTC_PARAM_AUTH_KEK, + sc->kek) <= 0) + 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))) + if (sc->eng && BIO_printf(out, "%s = %s\n", OSSL_PROV_SMTC_PARAM_ENGINE, + sc->eng) <= 0) + goto end; + + if (sc->key && BIO_printf(out, "%s = %s\n", OSSL_PROV_SMTC_PARAM_AUTH_KEY, + sc->key) <= 0) + goto end; + + if (sc->salt && BIO_printf(out, "%s = %s\n", OSSL_PROV_SMTC_PARAM_AUTH_SALT, + sc->salt) <= 0) + goto end; + + if (sc->syslog && BIO_printf(out, "%s = %s\n", OSSL_PROV_SMTC_PARAM_SYSLOG, + sc->syslog) <= 0) + goto end; + + if (sc->rand_poweron_test + && BIO_printf(out, "%s = %s\n", + OSSL_PROV_SMTC_PARAM_RANDOMNESS_POWERON_TEST, + sc->rand_poweron_test) <= 0) goto end; + #ifndef OPENSSL_NO_SMTC_DEBUG - } + if (sc->verify_sig && BIO_printf(out, "%s = %s\n", + OSSL_PROV_SMTC_PARAM_MODULE_VERIFY_SIG, + sc->verify_sig) <= 0) + goto end; + + if (sc->verify_pass && BIO_printf(out, "%s = %s\n", + OSSL_PROV_SMTC_PARAM_MODULE_VERIFY_PASS, + sc->verify_pass) <= 0) + goto end; #endif ret = 1; @@ -219,39 +276,45 @@ 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, install = 0, pass = 0; char *prog; + unsigned char *sig = NULL, *auth_key = NULL; + int siglen = 0; + const char *sigfile = NULL, *kek_file = NULL; OPTION_CHOICE o; - int self_test = 0; - BIO *module_bio = NULL, *fout = NULL; - char *out_fname = NULL; - EVP_MAC *mac = NULL; - const char *mac_name = "HMAC"; - const char *prov_name = "smtc"; - SMTC_CONF sc = { - .section = "smtc_sect", - .show_selftest = 0, -#ifndef OPENSSL_NO_SMTC_DEBUG - .verify_pass = 1, + unsigned char buf[BUFSIZE]; + int self_test = 0, get_status = 0, status = 0; + BIO *module_bio = NULL, *fout = NULL, *kek_bio = NULL; +#ifndef OPENSSL_NO_ATF_SLIBCE + const char *eng_name = "atf_slibce"; +#else + const char *eng_name = NULL; #endif - }; - STACK_OF(OPENSSL_STRING) *opts = NULL; - unsigned char *read_buffer = NULL; - EVP_MAC_CTX *ctx = NULL, *ctx2 = NULL; + const char *prov_name = "smtc", *sec_name = "smtc_sect"; + const char *conf_file = OPENSSL_info(OPENSSL_INFO_SMTC_MODULE_CONF); + const char *auth_kek = OPENSSL_info(OPENSSL_INFO_SMTC_AUTH_KEK); + SMTC_CONF sc; CONF *conf = NULL; + long eline; + EVP_PKEY *kek = NULL; + ENGINE *engine = NULL; + unsigned char auth_salt[SMTC_AUTH_SALT_LEN]; + size_t auth_key_len; + OSSL_PROVIDER *prov = NULL; +#ifndef OPENSSL_NO_SMTC_DEBUG + int no_verify = 0, no_auth = 0, no_rand_poweron_test = 0; +#endif - if ((opts = sk_OPENSSL_STRING_new_null()) == NULL) - goto end; + memset(&sc, 0, sizeof(sc)); + sc.section = sec_name; + sc.syslog = "1"; prog = opt_init(argc, argv, mod_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { case OPT_EOF: case OPT_ERR: - opthelp: +opthelp: BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); goto cleanup; case OPT_HELP: @@ -261,155 +324,275 @@ int mod_main(int argc, char **argv) case OPT_TEST: self_test = 1; break; + case OPT_STATUS: + get_status = 1; + break; + case OPT_RESET: + reset = 1; + break; case OPT_PROV_NAME: prov_name = opt_arg(); break; case OPT_MODULE: sc.module_path = opt_arg(); break; - case OPT_SECTION_NAME: - sc.section = opt_arg(); + case OPT_PASS: + pass = 1; break; - case OPT_SHOW_SELFTEST: - sc.show_selftest = 1; + case OPT_SIGFILE: + sigfile = opt_arg(); break; -#ifndef OPENSSL_NO_SMTC_DEBUG - case OPT_NO_PASS: - no_pass = 1; - sc.verify_pass = 0; + case OPT_INSTALL: + install = 1; break; -#endif case OPT_OUT: - out_fname = opt_arg(); + conf_file = opt_arg(); break; - case OPT_R_CASES: - if (!opt_rand(o)) - goto end; + case OPT_KEK: + kek_file = opt_arg(); + break; + case OPT_ENGINE: + eng_name = opt_arg(); + engine = setup_engine(eng_name, 1); + break; +#ifndef OPENSSL_NO_SMTC_DEBUG + case OPT_NO_VERIFY: + no_verify = 1; break; + case OPT_NO_AUTH: + no_auth = 1; + break; + case OPT_NO_RAND_POWERON_TEST: + no_rand_poweron_test = 1; + break; +#endif } } + argc = opt_num_rest(); - argv = opt_rest(); + if (argc != 0) + goto opthelp; - if (self_test) { - 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"); + if (reset || self_test || get_status) { + prov = OSSL_PROVIDER_load(app_get0_libctx(), "smtc"); + if (prov == NULL) { + BIO_printf(bio_err, "Failed to load SMTC provider\n"); + goto end; + } + + if (reset) { + if (OSSL_PROVIDER_reset(prov) != 1) { + BIO_printf(bio_err, "Failed to reset SMTC provider\n"); goto end; } + } + if (self_test) { if (OSSL_PROVIDER_self_test(prov) != 1) { - OSSL_PROVIDER_unload(prov); - BIO_printf(bio_err, "SMTC provider self test failed\n"); + BIO_printf(bio_err, "self test failed\n"); goto end; } - OSSL_PROVIDER_unload(prov); + BIO_printf(bio_out, "self test success\n"); + } + + if (get_status) { + status = OSSL_PROVIDER_status(prov); - ret = 0; - goto end; - } else { - BIO_printf(bio_err, "SMTC provider not available\n"); - goto end; + BIO_printf(bio_out, "status: %sactive\n", status ? "" : "in"); } + + ok = 1; + goto end; } + if (install) { + if (sigfile) { + BIO *sigbio = BIO_new_file(sigfile, "rb"); + + 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 = OPENSSL_buf2hexstr(sig, siglen); + if (sc.sig == NULL) + goto end; + } + #ifndef OPENSSL_NO_SMTC_DEBUG - if (!no_pass) + if (no_verify) + sc.verify_sig = "0"; + + if (no_auth) + sc.verify_pass = "0"; + + if (no_rand_poweron_test) + sc.rand_poweron_test = "0"; #endif - if (!setup_password(sc.admin_salt, sc.admin_pass)) - goto end; + sc.eng = eng_name; - if (sc.module_path == NULL) - goto opthelp; + if (sc.module_path == NULL) + goto opthelp; - if (!sk_OPENSSL_STRING_push(opts, "digest:SM3")) - goto end; - if (!sk_OPENSSL_STRING_push(opts, "hexkey:" SMTC_KEY_STRING)) - goto end; + if (kek_file) { + kek_bio = bio_open_default(kek_file, 'r', FORMAT_TEXT); + if (kek_bio == NULL) { + BIO_printf(bio_err, "Failed to open file %s\n", kek_file); + goto end; + } - module_bio = bio_open_default(sc.module_path, 'r', FORMAT_BINARY); - if (module_bio == NULL) { - BIO_printf(bio_err, "Failed to open module file\n"); - goto end; - } + fout = bio_open_default(auth_kek, 'w', FORMAT_TEXT); + if (fout == NULL) { + BIO_printf(bio_err, "Failed to open file %s\n", auth_kek); + goto end; + } - read_buffer = app_malloc(BUFSIZE, "I/O buffer"); - if (read_buffer == NULL) - goto end; + while (BIO_pending(kek_bio) || !BIO_eof(kek_bio)) { + ret = BIO_read(kek_bio, buf, BUFSIZE); + + if (ret < 0) { + BIO_printf(bio_err, "Read Error in '%s'\n", kek_file); + ERR_print_errors(bio_err); + goto end; + } + if (ret == 0) + break; + + if (BIO_write(fout, buf, ret) != ret) { + BIO_printf(bio_err, "Write Error in '%s'\n", auth_kek); + ERR_print_errors(bio_err); + 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; - } + sc.kek = auth_kek; + } + + conf = generate_config_and_load(prov_name, &sc); + if (conf == NULL) + goto end; + + fout = bio_open_default(conf_file, '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 (pass) { + conf = NCONF_new(NCONF_default()); - if (params == NULL) + if (NCONF_load(conf, conf_file, &eline) != 1) { + BIO_printf(bio_err, "Failed to load config file %s\n", conf_file); goto end; + } + + STACK_OF(CONF_VALUE) *sect = NCONF_get_section(conf, sec_name); + for (i = 0; i < sk_CONF_VALUE_num(sect); i++) { + CONF_VALUE *cv = sk_CONF_VALUE_value(sect, i); + + if (strcmp(cv->name, OSSL_PROV_SMTC_PARAM_MODULE_PATH) == 0) + sc.module_path = cv->value; + else if (strcmp(cv->name, OSSL_PROV_SMTC_PARAM_MODULE_SIG) == 0) + sc.sig = cv->value; + else if (strcmp(cv->name, OSSL_PROV_SMTC_PARAM_AUTH_KEK) == 0) + sc.kek = cv->value; + else if (strcmp(cv->name, OSSL_PROV_SMTC_PARAM_ENGINE) == 0) + sc.eng = cv->value; + else if (strcmp(cv->name, OSSL_PROV_SMTC_PARAM_SYSLOG) == 0) + sc.syslog = cv->value; + else if (strcmp(cv->name, + OSSL_PROV_SMTC_PARAM_RANDOMNESS_POWERON_TEST) == 0) + sc.rand_poweron_test = cv->value; + } - if (!EVP_MAC_CTX_set_params(ctx, params)) { - BIO_printf(bio_err, "MAC parameter error\n"); - ERR_print_errors(bio_err); - ok = 0; + if (sc.eng) { + engine = ENGINE_by_id(sc.eng); + if (engine == NULL) { + BIO_printf(bio_err, "Failed to load engine %s\n", sc.eng); + goto end; + } } - app_params_free(params); - if (!ok) + + kek = load_key(sc.kek, 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)) { + BIO_printf(bio_err, "Failed to setup password!\n"); + 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; + sc.key = OPENSSL_buf2hexstr(auth_key, auth_key_len); + if (sc.key == NULL) + goto end; - conf = generate_config_and_load(prov_name, &sc); - if (conf == NULL) - goto end; + sc.salt = OPENSSL_buf2hexstr(auth_salt, sizeof(auth_salt)); + if (sc.salt == 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 (!write_config_smtc_section(fout, &sc)) - goto end; + fout = bio_open_default(conf_file, 'w', FORMAT_TEXT); + if (fout == NULL) { + BIO_printf(bio_err, "Failed to open file %s\n", conf_file); + goto end; + } - BIO_printf(bio_err, "INSTALL PASSED\n"); + if (!write_config_smtc_section(fout, &sc)) { + BIO_printf(bio_err, "Failed to write config file %s\n", conf_file); + goto end; + } + } - ret = 0; + ok = 1; end: - if (ret == 1) + if (ok == 0) { ERR_print_errors(bio_err); + ret = 1; + } else { + /* Exit the process after reset module */ + if (reset) + ret = -1; + else + ret = 0; + } cleanup: + if (install) + OPENSSL_free(sc.sig); + + if (prov) + OSSL_PROVIDER_unload(prov); + + release_engine(engine); + EVP_PKEY_free(kek); + OPENSSL_free(auth_key); + OPENSSL_free(sig); + OPENSSL_free(sc.key); + OPENSSL_free(sc.salt); BIO_free(fout); BIO_free(module_bio); - sk_OPENSSL_STRING_free(opts); - EVP_MAC_free(mac); - EVP_MAC_CTX_free(ctx2); - EVP_MAC_CTX_free(ctx); - OPENSSL_free(read_buffer); + BIO_free(kek_bio); + if (conf != NULL) { NCONF_free(conf); CONF_modules_unload(1); } + return ret; } 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..47be38976 100644 --- a/apps/rand.c +++ b/apps/rand.c @@ -17,10 +17,12 @@ #include #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 +39,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 +50,48 @@ 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, *p; + int format = FORMAT_BINARY, i, num = -1, r, ret = 1, entropy = 0; + size_t ent_len = 0; prog = opt_init(argc, argv, rand_options); while ((o = opt_next()) != OPT_EOF) { @@ -82,6 +121,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,24 +160,45 @@ 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 (r <= 0) - goto end; + + if (entropy) { + ent_buf = TSAPI_GetEntropy(chunk, &ent_len); + if (ent_buf == NULL) + goto end; + } else { + r = RAND_bytes(buf, chunk); + if (r <= 0) + goto end; + } + + if (entropy) { + p = ent_buf; + chunk = ent_len; + } else { + p = buf; + } + if (format != FORMAT_TEXT) { - if (BIO_write(out, buf, chunk) != chunk) + if (BIO_write(out, p, chunk) != chunk) goto end; } else { for (i = 0; i < chunk; i++) - if (BIO_printf(out, "%02x", buf[i]) != 2) + if (BIO_printf(out, "%02x", p[i]) != 2) goto end; } num -= chunk; + + if (entropy) { + TSAPI_FreeEntropy(ent_buf, ent_len); + ent_buf = NULL; + } } if (format == FORMAT_TEXT) BIO_puts(out, "\n"); @@ -145,5 +212,6 @@ int rand_main(int argc, char **argv) ERR_print_errors(bio_err); release_engine(e); BIO_free_all(out); + TSAPI_FreeEntropy(ent_buf, ent_len); return ret; } diff --git a/apps/s_server.c b/apps/s_server.c index 088e403ab..e6243ed9d 100644 --- a/apps/s_server.c +++ b/apps/s_server.c @@ -1898,8 +1898,6 @@ int s_server_main(int argc, char *argv[]) if (s_key_file == NULL) s_key_file = s_cert_file; - - if (!load_excert(&exc)) goto end; diff --git a/apps/sdf.c b/apps/sdf.c new file mode 100644 index 000000000..357d68ce4 --- /dev/null +++ b/apps/sdf.c @@ -0,0 +1,516 @@ +/* + * 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 "internal/deprecated.h" +#include +#include +#include +#include +#include +#include +#include "apps.h" +#include "progs.h" + +typedef enum OPTION_choice { + OPT_ERR = -1, + OPT_EOF = 0, + OPT_HELP, + OPT_IN, + OPT_INKEY, + OPT_INDEX, + OPT_GENSM2KEY, + OPT_DELSM2KEY, + OPT_UPDATESM2KEY, + OPT_EXPORTSM2PUBKEY, + OPT_EXPORTSM2KEY, + OPT_EXPORTSM2KEYWITHEVLP, + OPT_IMPORTSM2KEY, + OPT_IMPORTSM2KEYWITHEVLP, + OPT_LOGIN, + OPT_ENCRYPT, + OPT_DECRYPT, + OPT_PEERKEY, + OPT_TYPE, + OPT_OUT, + OPT_KEYOUT, + OPT_DEKOUT, + OPT_INDEK, + OPT_IV, + OPT_ISK, + OPT_ISKTYPE, + OPT_ALGORITHM, +} OPTION_CHOICE; + +/* + * Examples: + * + * Encrypt data with SM4 key which is encrypted with ISK: + * sdf -encrypt -algorithm sm4-cbc -inkey sm4key.enc -isk index -isktype sm2 -iv aabbcc -in data.txt -out data.enc + * + * Generate SM2 key pair with the index: + * sdf -gensm2key -index 1 + * + * Delete SM2 key pair with the index: + * sdf -delsm2key -index 1 + * + * Update SM2 key pair with the index: + * sdf -updatesm2key -index 1 + * + * Encrypt data with SM2 key with the index: + * sdf -encrypt -algorithm sm2 -index 1 -in data.txt -out data.enc + * + * Import SM2 key with the index, sm2 key is encrypted by sm4 key(indek), + * sm4 key is encrypted by ISK, default is 0: + * sdf -importsm2keywithevlp -type enc -index 7 -inkey sm2_enc.keyenc -indek sm4.keyenc + * + * Export SM2 key with the index: + * sdf -exportsm2key -index 1 -keyout sm2key.pem + * + * Export SM2 public key with the index: + * sdf -exportsm2pubkey -index 1 -keyout sm2pubkey.pem + */ + +const OPTIONS sdf_options[] = { + OPT_SECTION("General"), + {"help", OPT_HELP, '-', "Display this summary"}, + {"encrypt", OPT_ENCRYPT, '-', "Encrypt file"}, + {"decrypt", OPT_DECRYPT, '-', "Decrypt file"}, + {"importsm2key", OPT_IMPORTSM2KEY, '-', "Import SM2 key with the index"}, + {"importsm2keywithevlp", OPT_IMPORTSM2KEYWITHEVLP, '-', "Import SM2 key with digital envelope"}, + {"gensm2key", OPT_GENSM2KEY, '-', "Generate SM2 key pair with the index"}, + {"delsm2key", OPT_DELSM2KEY, '-', "Delete SM2 key pair with the index"}, + {"updatesm2key", OPT_UPDATESM2KEY, '-', "Update SM2 key pair with the index"}, + {"exportsm2key", OPT_EXPORTSM2KEY, '-', "Export SM2 key with the index"}, + {"exportsm2pubkey", OPT_EXPORTSM2PUBKEY, '-', "Export SM2 public key with the index"}, + {"exportsm2keywithevlp", OPT_EXPORTSM2KEYWITHEVLP, '-', "Export SM2 key with digital envelope"}, + {"login", OPT_LOGIN, 's', "Login with username:password"}, + + OPT_SECTION("Input"), + {"inkey", OPT_INKEY, 's', "Input key file"}, + {"index", OPT_INDEX, 's', "Specify the index of key"}, + {"peerkey", OPT_PEERKEY, 's', "Peer public key file used in exporting SM2 key with digital envelope"}, + {"type", OPT_TYPE, 's', "sign: signature key, enc: encryption key"}, + {"indek", OPT_INDEK, '>', "Input digital envelope key"}, + {"isk", OPT_ISK, 's', "Index of ISK key"}, + {"isktype", OPT_ISKTYPE, 's', "ISK type, sm2: SM2 key, rsa: RSA key"}, + {"iv", OPT_IV, 's', "IV in hex format"}, + {"algorithm", OPT_ALGORITHM, 's', "Algorithm to use"}, + {"in", OPT_IN, '>', "Input file"}, + + OPT_SECTION("Output"), + {"out", OPT_OUT, '>', "Output file"}, + {"keyout", OPT_KEYOUT, '>', "Output key file"}, + {"dekout", OPT_DEKOUT, '>', "Output digital envelope key"}, + + {NULL} +}; + +int sdf_main(int argc, char **argv) +{ + char *prog; + OPTION_CHOICE o; + BIO *outkey = NULL, *outdek = NULL, *key_bio = NULL; + BIO *in = NULL, *out = NULL; + int ret = 1, index = -1, sign = 1, keylen = 0, deklen = 0, mode = 0; + int isk = -1; + int gensm2 = 0, delsm2 = 0, updatesm2 = 0; + int exportsm2pubkey = 0, exportsm2keywithevlp = 0, importsm2keywithevlp = 0; + int exportsm2key = 0, importsm2key = 0, encrypt = 0, decrypt = 0; + unsigned char *inkey = NULL, *indek = NULL, *inbuf = NULL, *outbuf = NULL; + char *p = NULL; + char *login = NULL; + char *outkeyfile = NULL, *peerkey_file = NULL, *indekfile = NULL; + char *outdekfile = NULL, *inkeyfile = NULL; + char *infile = NULL, *outfile = NULL; + const char *user = "admin", *password = "123123", *hexiv = NULL, *algo = NULL; + const char *isktype = "sm2"; + unsigned char *iv = NULL; + EVP_PKEY *pkey = NULL, *peer = NULL; + unsigned char *priv = NULL, *pub = NULL, *outevlp = NULL; + size_t privlen = 0, publen = 0, outevlplen = 0; + int inbuflen = -1; + size_t outbuflen = 0; + + prog = opt_init(argc, argv, sdf_options); + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_EOF: + case OPT_ERR: +opthelp: + BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); + goto end; + case OPT_HELP: + opt_help(sdf_options); + ret = 0; + goto end; + case OPT_IN: + infile = opt_arg(); + break; + case OPT_OUT: + outfile = opt_arg(); + break; + case OPT_INKEY: + inkeyfile = opt_arg(); + break; + case OPT_GENSM2KEY: + gensm2 = 1; + break; + case OPT_DELSM2KEY: + delsm2 = 1; + break; + case OPT_UPDATESM2KEY: + updatesm2 = 1; + break; + case OPT_INDEX: + index = atoi(opt_arg()); + break; + case OPT_LOGIN: + login = opt_arg(); + break; + case OPT_EXPORTSM2KEY: + exportsm2key = 1; + break; + case OPT_EXPORTSM2PUBKEY: + exportsm2pubkey = 1; + break; + case OPT_EXPORTSM2KEYWITHEVLP: + exportsm2keywithevlp = 1; + break; + case OPT_IMPORTSM2KEY: + importsm2key = 1; + break; + case OPT_IMPORTSM2KEYWITHEVLP: + importsm2keywithevlp = 1; + break; + case OPT_PEERKEY: + peerkey_file = opt_arg(); + break; + case OPT_TYPE: + if (strcmp(opt_arg(), "sign") == 0) + sign = 1; + else if (strcmp(opt_arg(), "enc") == 0) + sign = 0; + else + goto opthelp; + break; + case OPT_KEYOUT: + outkeyfile = opt_arg(); + break; + case OPT_INDEK: + indekfile = opt_arg(); + break; + case OPT_DEKOUT: + outdekfile = opt_arg(); + break; + case OPT_ENCRYPT: + encrypt = 1; + break; + case OPT_DECRYPT: + decrypt = 1; + break; + case OPT_IV: + hexiv = opt_arg(); + break; + case OPT_ALGORITHM: + algo = opt_arg(); + break; + case OPT_ISK: + isk = atoi(opt_arg()); + break; + case OPT_ISKTYPE: + isktype = opt_arg(); + break; + } + } + + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; + + if (login) { + user = login; + p = strchr(login, ':'); + if (p == NULL) { + BIO_printf(bio_err, "No password found"); + goto end; + } + + password = p + 1; + *p = '\0'; + } + + if (gensm2) { + if (!TSAPI_GenerateSM2KeyWithIndex(index, sign, user, password)) { + BIO_printf(bio_err, "Failed to generate SM2 key pair with index %d\n", index); + goto end; + } + } + + if (delsm2) { + if (!TSAPI_DelSm2KeyWithIndex(index, sign, user, password)) { + BIO_printf(bio_err, "Failed to delete SM2 key pair with index %d\n", index); + goto end; + } + } + + if (updatesm2) { + if (!TSAPI_UpdateSm2KeyWithIndex(index, sign, user, password)) { + BIO_printf(bio_err, "Failed to update SM2 key pair with index %d\n", index); + goto end; + } + } + + if (outkeyfile) { + outkey = bio_open_default(outkeyfile, 'w', FORMAT_BINARY); + if (outkey == NULL) + goto end; + } + + if (exportsm2key) { + pkey = TSAPI_ExportSM2KeyWithIndex(index, sign, user, password); + if (pkey == NULL) { + BIO_printf(bio_err, "Failed to export SM2 pubkey with index %d\n", index); + goto end; + } + + if (!PEM_write_bio_PrivateKey(outkey, pkey, NULL, NULL, 0, NULL, NULL)) { + BIO_printf(bio_err, "Failed to write SM2 key\n"); + ERR_print_errors(bio_err); + goto end; + } + } + + if (exportsm2pubkey) { + pkey = TSAPI_ExportSM2PubKeyWithIndex(index, sign); + if (pkey == NULL) { + BIO_printf(bio_err, "Failed to export SM2 pubkey with index %d\n", index); + goto end; + } + + if (!PEM_write_bio_PUBKEY(outkey, pkey)) { + BIO_printf(bio_err, "Failed to write SM2 pubkey"); + goto end; + } + } + + if (exportsm2keywithevlp) { + peer = load_pubkey(peerkey_file, FORMAT_PEM, 0, NULL, NULL, "peer key"); + if (peer == NULL) { + BIO_printf(bio_err, "Error reading peer key %s\n", peerkey_file); + return 0; + } + + if (!TSAPI_ExportSM2KeyWithEvlp(index, sign, user, password, peer, &priv, + &privlen, &pub, &publen, &outevlp, + &outevlplen)) { + BIO_printf(bio_err, "Failed to export SM2 key with digital envelope\n"); + goto end; + } + + if (outkey == NULL) { + BIO_printf(bio_err, "No output file specified\n"); + goto end; + } + + if (BIO_write(outkey, pub, publen) != (int)publen + || BIO_write(outkey, priv, privlen) != (int)privlen) { + BIO_printf(bio_err, "Failed to write public or private key\n"); + goto end; + } + + if (outdekfile == NULL) { + BIO_printf(bio_err, "No digital envelope file specified\n"); + goto end; + } + + outdek = bio_open_default(outdekfile, 'w', FORMAT_BINARY); + if (outdek == NULL) + goto end; + + if (BIO_write(outdek, outevlp, outevlplen) != (int)outevlplen) { + BIO_printf(bio_err, "Failed to write digital envelope\n"); + goto end; + } + } + + if (importsm2key) { + pkey = load_key(inkeyfile, FORMAT_PEM, 0, NULL, NULL, "key"); + + if (pkey == NULL) { + BIO_printf(bio_err, "Error reading key %s\n", inkeyfile); + goto end; + } + + if (!TSAPI_ImportSM2Key(index, sign, user, password, pkey)) { + BIO_printf(bio_err, "Failed to import SM2 key\n"); + goto end; + } + } + + if (inkeyfile) { + key_bio = BIO_new(BIO_s_file()); + if (key_bio == NULL) { + BIO_printf(bio_err, "Error creating key BIO\n"); + goto end; + } + + if (BIO_read_filename(key_bio, inkeyfile) <= 0) { + BIO_printf(bio_err, "Error reading key file %s\n", inkeyfile); + goto end; + } + + keylen = bio_to_mem(&inkey, 4096, key_bio); + BIO_free(key_bio); + key_bio = NULL; + + if (keylen < 0) { + BIO_printf(bio_err, "Error reading key\n"); + goto end; + } + } + + if (indekfile) { + key_bio = BIO_new(BIO_s_file()); + if (key_bio == NULL) { + BIO_printf(bio_err, "Error creating key BIO\n"); + goto end; + } + + if (BIO_read_filename(key_bio, indekfile) <= 0) { + BIO_printf(bio_err, "Error reading key file %s\n", indekfile); + goto end; + } + + deklen = bio_to_mem(&indek, 4096, key_bio); + BIO_free(key_bio); + key_bio = NULL; + + if (deklen < 0) { + BIO_printf(bio_err, "Error reading key\n"); + goto end; + } + } + + if (importsm2keywithevlp) { + if (inkey == NULL || indek == NULL) { + BIO_printf(bio_err, "No key or digital envelope specified\n"); + goto end; + } + + if (!TSAPI_ImportSM2KeyWithEvlp(index, sign, user, password, inkey, + keylen, indek, deklen)) { + BIO_printf(bio_err, "Failed to import SM2 key with digital envelope\n"); + goto end; + } + } + + if (infile) { + in = bio_open_default(infile, 'r', FORMAT_BINARY); + if (in == NULL) + goto end; + + /* Note: Only supports files less than 1GB */ + inbuflen = bio_to_mem(&inbuf, 1024 * 1024 * 1024, in); + if (inbuflen < 0) { + BIO_printf(bio_err, "Error reading input\n"); + goto end; + } + } + + if (outfile) { + out = bio_open_default(outfile, 'w', FORMAT_BINARY); + if (out == NULL) + goto end; + } + + if (encrypt || decrypt) { + if (inbuf == NULL || inbuflen < 0 || out == NULL || algo == NULL) { + BIO_printf(bio_err, "No input, output or algorithm specified\n"); + goto end; + } + + if (OPENSSL_strcasecmp(algo, "sm2") == 0) { + if (index < 0) { + BIO_printf(bio_err, "No SM2 key index specified\n"); + goto end; + } + + if (encrypt) + outbuf = TSAPI_SM2EncryptWithISK(index, inbuf, inbuflen, + &outbuflen); + else + outbuf = TSAPI_SM2DecryptWithISK(index, inbuf, inbuflen, + &outbuflen); + } else { + if (OPENSSL_strcasecmp(algo, "sm4-ecb") == 0) + mode = OSSL_SGD_SM4_ECB; + else if (OPENSSL_strcasecmp(algo, "sm4-cbc") == 0) + mode = OSSL_SGD_SM4_CBC; + else if (OPENSSL_strcasecmp(algo, "sm4-cfb") == 0) + mode = OSSL_SGD_SM4_CFB; + else if (OPENSSL_strcasecmp(algo, "sm4-ofb") == 0) + mode = OSSL_SGD_SM4_OFB; + else { + BIO_printf(bio_err, "Unknown algorithm %s\n", algo); + goto end; + } + + if (hexiv) { + iv = OPENSSL_hexstr2buf(hexiv, NULL); + if (iv == NULL) { + BIO_printf(bio_err, "Error reading IV\n"); + goto end; + } + } + + if (OPENSSL_strcasecmp(isktype, "sm2") == 0) { + if (encrypt) { + if ((outbuf = TSAPI_SM4Encrypt(mode, inkey, keylen, isk, iv, + inbuf, inbuflen, &outbuflen)) + == NULL) { + BIO_printf(bio_err, "Failed to encrypt data\n"); + goto end; + } + } else { + if ((outbuf = TSAPI_SM4Decrypt(mode, inkey, keylen, isk, iv, + inbuf, inbuflen, &outbuflen)) + == NULL) { + BIO_printf(bio_err, "Failed to decrypt data\n"); + goto end; + } + } + } else { + BIO_printf(bio_err, "Unknown ISK type %s\n", isktype); + goto end; + } + } + + if (BIO_write(out, outbuf, outbuflen) != (int)outbuflen) { + BIO_printf(bio_err, "Failed to write output\n"); + goto end; + } + } + + ret = 0; +end: + OPENSSL_free(iv); + OPENSSL_free(inbuf); + OPENSSL_free(outbuf); + BIO_free(in); + BIO_free(out); + OPENSSL_free(inkey); + BIO_free(outdek); + BIO_free(key_bio); + EVP_PKEY_free(pkey); + EVP_PKEY_free(peer); + BIO_free(outkey); + OPENSSL_free(priv); + OPENSSL_free(pub); + OPENSSL_free(outevlp); + return ret; +} diff --git a/apps/speed.c b/apps/speed.c index 1df5ce69d..584028da3 100644 --- a/apps/speed.c +++ b/apps/speed.c @@ -30,6 +30,7 @@ #define EdDSA_SECONDS PKEY_SECONDS #define SM2_SECONDS PKEY_SECONDS #define FFDH_SECONDS PKEY_SECONDS +#define KEYGEN_SECONDS PKEY_SECONDS /* We need to use some deprecated APIs */ #define OPENSSL_SUPPRESS_DEPRECATED @@ -48,6 +49,8 @@ #include #include #include +#include +#include #if !defined(OPENSSL_SYS_MSDOS) # include #endif @@ -121,6 +124,7 @@ typedef struct openssl_speed_sec_st { int ec_elgamal; int paillier; int bulletproofs; + int keygen; } openssl_speed_sec_t; static volatile int run = 0; @@ -260,7 +264,7 @@ typedef enum OPTION_choice { OPT_COMMON, OPT_ELAPSED, OPT_EVP, OPT_HMAC, OPT_DECRYPT, OPT_ENGINE, OPT_MULTI, OPT_MR, OPT_MB, OPT_MISALIGN, OPT_ASYNCJOBS, OPT_R_ENUM, OPT_PROV_ENUM, - OPT_PRIMES, OPT_SECONDS, OPT_BYTES, OPT_AEAD, OPT_CMAC + OPT_PRIMES, OPT_SECONDS, OPT_BYTES, OPT_AEAD, OPT_CMAC, OPT_KEYGEN, OPT_SDF, } OPTION_CHOICE; const OPTIONS speed_options[] = { @@ -291,6 +295,8 @@ const OPTIONS speed_options[] = { "Time decryption instead of encryption (only EVP)"}, {"aead", OPT_AEAD, '-', "Benchmark EVP-named AEAD cipher in TLS-like sequence"}, + {"keygen", OPT_KEYGEN, 's', "Time the key generation using the specified algorithm"}, + {"sdf", OPT_SDF, 's', "Time the SDF operations using the specified operation"}, OPT_SECTION("Timing"), {"elapsed", OPT_ELAPSED, '-', @@ -316,7 +322,7 @@ enum { D_CBC_DES, D_EDE3_DES, D_RC4, D_CBC_RC5, D_CBC_128_AES, D_CBC_192_AES, D_CBC_256_AES, - D_EVP, D_GHASH, D_RAND, D_EVP_CMAC, D_SM3, D_CBC_SM4, + D_EVP, D_GHASH, D_RAND, D_EVP_CMAC, D_SM3, D_CBC_SM4, D_ECB_SM4, D_EEA3_128_ZUC, D_EIA3_128_ZUC, D_SM2_ENCRYPT, D_SM2_DECRYPT, D_SM2_THRESHOLD_DECRYPT, ALGOR_NUM }; @@ -327,7 +333,7 @@ static const char *names[ALGOR_NUM] = { "des-cbc", "des-ede3", "rc4", "rc5-cbc", "aes-128-cbc", "aes-192-cbc", "aes-256-cbc", - "evp", "ghash", "rand", "cmac", "sm3", "sm4", + "evp", "ghash", "rand", "cmac", "sm3", "sm4-cbc", "sm4-ecb", "zuc-128-eea3", "zuc-128-eia3", "sm2-encrypt", "sm2-decrypt", "sm2-thr-dec", }; @@ -354,6 +360,7 @@ static const OPT_PAIR doit_choices[] = { #ifndef OPENSSL_NO_SM4 {"sm4-cbc", D_CBC_SM4}, {"sm4", D_CBC_SM4}, + {"sm4-ecb", D_ECB_SM4}, #endif #ifndef OPENSSL_NO_ZUC {"zuc-128-eea3", D_EEA3_128_ZUC}, @@ -646,9 +653,34 @@ static double bulletproofs_results[BULLETPROOFS_NUM][BULLETPROOFS_BITS_NUM][BULL #endif /* OPENSSL_NO_BULLETPROOFS */ +enum { + R_SM2, KEYGEN_NUM +}; +static const OPT_PAIR keygen_choices[KEYGEN_NUM] = { + {"sm2", R_SM2}, +}; + +static double keygen_results[KEYGEN_NUM]; + +enum { + R_GenerateKey, SDF_NUM +}; +static const OPT_PAIR sdf_choices[SDF_NUM] = { + {"GenerateKey", R_GenerateKey}, +}; + +static double sdf_results[SDF_NUM]; + #define COND(unused_cond) (run && count < INT_MAX) #define COUNT(d) (count) +typedef struct { + void *hSessionHandle; + void *hKeyHandle; +} HANDLE_PAIR; + +DEFINE_STACK_OF(HANDLE_PAIR) + typedef struct loopargs_st { ASYNC_JOB *inprogress_job; ASYNC_WAIT_CTX *wait_ctx; @@ -710,6 +742,10 @@ typedef struct loopargs_st { #endif EVP_CIPHER_CTX *ctx; EVP_MAC_CTX *mctx; + + void *hDeviceHandle; + void *hSessionHandle; + STACK_OF(HANDLE_PAIR) *key_handles; } loopargs_t; static int run_benchmark(int async_jobs, int (*loop_function) (void *), loopargs_t * loopargs); @@ -1379,6 +1415,24 @@ static int SM2_decrypt_loop(void *args) return count; } + +static int SM2_keygen_loop(void *args) +{ + int count; + + for (count = 0; COND(keygen_results[testnum]); count++) { + if (EVP_PKEY_Q_keygen(app_get0_libctx(), app_get0_propq(), "SM2") + == NULL) { + BIO_printf(bio_err, "SM2 keygen failure\n"); + ERR_print_errors(bio_err); + count = -1; + break; + } + } + + return count; +} + # ifndef OPENSSL_NO_SM2_THRESHOLD static long sm2_threshold_c[2]; @@ -1697,6 +1751,43 @@ static int BULLETPROOFS_loop(void *args) } #endif /* OPENSSL_NO_BULLETPROOFS */ +static void sdf_destroy_key(HANDLE_PAIR *pair) +{ + (void)TSAPI_SDF_DestroyKey(pair->hSessionHandle, pair->hKeyHandle); +} + +static int SDF_GenerateKey_loop(void *args) +{ + HANDLE_PAIR *pair = NULL; + loopargs_t *tempargs = *(loopargs_t **)args; + void *hSessionHandle = tempargs->hSessionHandle; + void *pkeyHandle = NULL; + int ret, count; + + for (count = 0; COND(1); count++) { + ret = TSAPI_SDF_GenerateKey(hSessionHandle, OSSL_SDFE_SYM_KEY_TYPE_SM4, + 1, 16, &pkeyHandle); + if (ret != OSSL_SDR_OK) { + BIO_printf(bio_err, "SDF_GenerateKey failed with %d\n", ret); + count = -1; + break; + } + + pair = OPENSSL_zalloc(sizeof(HANDLE_PAIR)); + if (pair == NULL) { + BIO_printf(bio_err, "Memory allocation failed\n"); + count = -1; + break; + } + pair->hSessionHandle = hSessionHandle; + pair->hKeyHandle = pkeyHandle; + + sk_HANDLE_PAIR_push(tempargs->key_handles, pair); + } + + return count; +} + static int run_benchmark(int async_jobs, int (*loop_function) (void *), loopargs_t * loopargs) { @@ -1943,7 +2034,8 @@ int speed_main(int argc, char **argv) OPTION_CHOICE o; int async_init = 0, multiblock = 0, pr_header = 0; uint8_t doit[ALGOR_NUM] = { 0 }; - int ret = 1, misalign = 0, lengths_single = 0, aead = 0; + int ret = 1, misalign = 0, lengths_single = 0, aead = 0, keygen = 0; + int sdf = 0; long count = 0; unsigned int size_num = SIZE_NUM; unsigned int i, k, loopargs_len = 0, async_jobs = 0; @@ -1959,7 +2051,8 @@ int speed_main(int argc, char **argv) ECDSA_SECONDS, ECDH_SECONDS, EdDSA_SECONDS, SM2_SECONDS, FFDH_SECONDS, EC_ELGAMAL_SECONDS, - PAILLIER_SECONDS, BULLETPROOFS_SECONDS }; + PAILLIER_SECONDS, BULLETPROOFS_SECONDS, + KEYGEN_SECONDS,}; static const unsigned char key32[32] = { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, @@ -2140,6 +2233,8 @@ int speed_main(int argc, char **argv) uint8_t ecdsa_doit[ECDSA_NUM] = { 0 }; uint8_t ecdh_doit[EC_NUM] = { 0 }; uint8_t eddsa_doit[EdDSA_NUM] = { 0 }; + uint8_t keygen_doit[KEYGEN_NUM] = { 0 }; + uint8_t sdf_doit[SDF_NUM] = { 0 }; /* checks declarated curves against choices list. */ OPENSSL_assert(ed_curves[EdDSA_NUM - 1].nid == NID_ED448); @@ -2278,7 +2373,8 @@ int speed_main(int argc, char **argv) case OPT_SECONDS: seconds.sym = seconds.rsa = seconds.dsa = seconds.ecdsa = seconds.ecdh = seconds.eddsa - = seconds.sm2 = seconds.ffdh = atoi(opt_arg()); + = seconds.sm2 = seconds.ffdh = seconds.keygen + = atoi(opt_arg()); break; case OPT_BYTES: lengths_single = atoi(opt_arg()); @@ -2287,6 +2383,22 @@ int speed_main(int argc, char **argv) break; case OPT_AEAD: aead = 1; + break; + case OPT_KEYGEN: + keygen = 1; + if (opt_found(opt_arg(), keygen_choices, &i)) { + keygen_doit[i] = 1; + break; + } + + break; + case OPT_SDF: + sdf = 1; + if (opt_found(opt_arg(), sdf_choices, &i)) { + sdf_doit[i] = 1; + break; + } + break; } } @@ -2543,6 +2655,7 @@ int speed_main(int argc, char **argv) loopargs[i].secret_ff_a = app_malloc(MAX_FFDH_SIZE, "FFDH secret a"); loopargs[i].secret_ff_b = app_malloc(MAX_FFDH_SIZE, "FFDH secret b"); #endif + loopargs[i].key_handles = sk_HANDLE_PAIR_new_null(); } #ifndef NO_FORK @@ -2554,7 +2667,8 @@ int speed_main(int argc, char **argv) e = setup_engine(engine_id, 0); /* No parameters; turn on everything. */ - if (argc == 0 && !doit[D_EVP] && !doit[D_HMAC] && !doit[D_EVP_CMAC]) { + if (argc == 0 && !doit[D_EVP] && !doit[D_HMAC] && !doit[D_EVP_CMAC] + && !keygen && !sdf) { memset(doit, 1, sizeof(doit)); doit[D_EVP] = doit[D_EVP_CMAC] = 0; ERR_set_mark(); @@ -2604,6 +2718,8 @@ int speed_main(int argc, char **argv) memset(sm2_threshold_doit, 1, sizeof(sm2_threshold_doit)); # endif #endif + memset(keygen_doit, 1, sizeof(keygen_doit)); + memset(sdf_doit, 1, sizeof(sdf_doit)); } for (i = 0; i < ALGOR_NUM; i++) if (doit[i]) @@ -2966,27 +3082,31 @@ int speed_main(int argc, char **argv) } #ifndef OPENSSL_NO_SM4 - if (doit[D_CBC_SM4]) { - int st = 1; + for (k = 0; k < 2; k++) { + algindex = D_CBC_SM4 + k; - keylen = 16; - for (i = 0; st && i < loopargs_len; i++) { - loopargs[i].ctx = init_evp_cipher_ctx(names[D_CBC_SM4], - key32, keylen); - st = loopargs[i].ctx != NULL; - } + if (doit[algindex]) { + int st = 1; - for (testnum = 0; st && testnum < size_num; testnum++) { - print_message(names[D_CBC_SM4], c[D_CBC_SM4][testnum], - lengths[testnum], seconds.sym); - Time_F(START); - count = - run_benchmark(async_jobs, EVP_Cipher_loop, loopargs); - d = Time_F(STOP); - print_result(D_CBC_SM4, testnum, count, d); + keylen = 16; + for (i = 0; st && i < loopargs_len; i++) { + loopargs[i].ctx = init_evp_cipher_ctx(names[algindex], + key32, keylen); + st = loopargs[i].ctx != NULL; + } + + for (testnum = 0; st && testnum < size_num; testnum++) { + print_message(names[algindex], c[algindex][testnum], + lengths[testnum], seconds.sym); + Time_F(START); + count = + run_benchmark(async_jobs, EVP_Cipher_loop, loopargs); + d = Time_F(STOP); + print_result(algindex, testnum, count, d); + } + for (i = 0; i < loopargs_len; i++) + EVP_CIPHER_CTX_free(loopargs[i].ctx); } - for (i = 0; i < loopargs_len; i++) - EVP_CIPHER_CTX_free(loopargs[i].ctx); } #endif @@ -3715,47 +3835,57 @@ int speed_main(int argc, char **argv) for (i = 0; st && i < loopargs_len; i++) { EVP_PKEY *pkey = NULL, *pubkey = NULL; - OSSL_PARAM *pub_params = NULL; EVP_PKEY_CTX *ctx = NULL; + BIO *tmpbio = NULL; st = 0; pkey = EVP_PKEY_Q_keygen(app_get0_libctx(), app_get0_propq(), "SM2"); if (pkey == NULL) break; - if (!EVP_PKEY_todata(pkey, EVP_PKEY_PUBLIC_KEY, &pub_params)) { + if (!EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2)) + break; + + ctx = EVP_PKEY_CTX_new(pkey, NULL); + if (ctx == NULL) { EVP_PKEY_free(pkey); break; } - ctx = EVP_PKEY_CTX_new_from_name(NULL, "SM2", NULL); - if (ctx == NULL) { + tmpbio = BIO_new(BIO_s_mem()); + if (tmpbio == NULL) + break; + + if (!PEM_write_bio_PUBKEY(tmpbio, pkey)) { EVP_PKEY_free(pkey); + EVP_PKEY_CTX_free(ctx); + BIO_free(tmpbio); break; } - if (EVP_PKEY_fromdata_init(ctx) <= 0 - || EVP_PKEY_fromdata(ctx, &pubkey, EVP_PKEY_PUBLIC_KEY, - pub_params) <= 0) { + if (!PEM_read_bio_PUBKEY(tmpbio, &pubkey, NULL, NULL)) { EVP_PKEY_free(pkey); EVP_PKEY_CTX_free(ctx); + BIO_free(tmpbio); break; } EVP_PKEY_CTX_free(ctx); + BIO_free(tmpbio); loopargs[i].sm2_enc_pctx = EVP_PKEY_CTX_new(pubkey, NULL); if (loopargs[i].sm2_enc_pctx == NULL) { EVP_PKEY_free(pkey); + EVP_PKEY_free(pubkey); break; } + EVP_PKEY_free(pubkey); loopargs[i].sm2_dec_pctx = EVP_PKEY_CTX_new(pkey, NULL); if (loopargs[i].sm2_dec_pctx == NULL) { EVP_PKEY_free(pkey); break; } - EVP_PKEY_free(pkey); if (EVP_PKEY_encrypt_init(loopargs[i].sm2_enc_pctx) <= 0) @@ -3956,7 +4086,6 @@ int speed_main(int argc, char **argv) for (i = 0; i < loopargs_len; i++) { EVP_PKEY_CTX *sm2_pctx = NULL; EVP_PKEY_CTX *sm2_vfy_pctx = NULL; - EVP_PKEY_CTX *pctx = NULL; st = 0; loopargs[i].sm2_ctx[testnum] = EVP_MD_CTX_new(); @@ -3967,16 +4096,12 @@ int speed_main(int argc, char **argv) sm2_pkey = NULL; - st = !((pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_SM2, NULL)) == NULL - || EVP_PKEY_keygen_init(pctx) <= 0 - || EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, - sm2_curves[testnum].nid) <= 0 - || EVP_PKEY_keygen(pctx, &sm2_pkey) <= 0); - EVP_PKEY_CTX_free(pctx); - if (st == 0) + sm2_pkey = EVP_PKEY_Q_keygen(app_get0_libctx(), app_get0_propq(), "SM2"); + if (sm2_pkey == NULL) break; - st = 0; /* set back to zero */ + if (!EVP_PKEY_set_alias_type(sm2_pkey, EVP_PKEY_SM2)) + break; /* attach it sooner to rely on main final cleanup */ loopargs[i].sm2_pkey[testnum] = sm2_pkey; loopargs[i].sigsize = EVP_PKEY_get_size(sm2_pkey); @@ -4769,6 +4894,73 @@ int speed_main(int argc, char **argv) } #endif /* OPENSSL_NO_BULLETPROOFS */ + for (testnum = 0; testnum < KEYGEN_NUM; testnum++) { + if (!keygen_doit[testnum]) + continue; + + if (testnum == R_SM2) { + pkey_print_message("keygen", "sm2", 0, 128, seconds.keygen); + Time_F(START); +#ifndef OPENSSL_NO_SM2 + count = run_benchmark(async_jobs, SM2_keygen_loop, loopargs); +#else + count = 0; +#endif + d = Time_F(STOP); + BIO_printf(bio_err, + mr ? "+F14:%ld:%s:%.2f\n" + : "%ld %s keygen in %.2fs\n", + count, keygen_choices[testnum].name, d); + keygen_results[testnum] = (double)count / d; + } + } + + for (testnum = 0; testnum < SDF_NUM; testnum++) { + int st = 1; + int res; + + if (!sdf_doit[testnum]) + continue; + + for (i = 0; i < loopargs_len; i++) { + st = 0; + + res = TSAPI_SDF_OpenDevice(&loopargs[i].hDeviceHandle); + if (res != OSSL_SDR_OK) { + BIO_printf(bio_err, "TSAPI_SDF_OpenDevice failed with %d\n", ret); + break; + } + + res = TSAPI_SDF_OpenSession(loopargs[i].hDeviceHandle, + &loopargs[i].hSessionHandle); + if (res != OSSL_SDR_OK) { + BIO_printf(bio_err, "TSAPI_SDF_OpenSession failed with %d\n", ret); + break; + } + + st = 1; + } + + if (st == 0) { + BIO_printf(bio_err, "SDF failure.\n"); + op_count = 1; + } else { + + if (testnum == R_GenerateKey) { + pkey_print_message("GenerateKey", "sm4", 0, 128, + seconds.keygen); + Time_F(START); + count = run_benchmark(async_jobs, SDF_GenerateKey_loop, loopargs); + d = Time_F(STOP); + BIO_printf(bio_err, + mr ? "+F15:%ld:%s:%.2f\n" + : "%ld %s keygen in %.2fs\n", + count, sdf_choices[testnum].name, d); + sdf_results[testnum] = (double)count / d; + } + } + } + #ifndef NO_FORK show_res: #endif @@ -5060,6 +5252,48 @@ int speed_main(int argc, char **argv) } #endif + testnum = 1; + for (k = 0; k < KEYGEN_NUM; k++) { + if (!keygen_doit[k]) + continue; + + if (testnum && !mr) { + printf("%30sop op/s\n", " "); + testnum = 0; + } + + if (mr) + printf("+F14:%u:%s:%f:%f\n", + k, keygen_choices[k].name, keygen_results[k], + 1.0 / keygen_results[k]); + else + printf("128 bits keygen (%s) %8.4fs %8.1f\n", + keygen_choices[k].name, 1.0 / keygen_results[k], + keygen_results[k]); + } + + testnum = 1; + for (k = 0; k < SDF_NUM; k++) { + if (!sdf_doit[k]) + continue; + + if (testnum && !mr) { + printf("%30sop op/s\n", " "); + testnum = 0; + } + + if (k == R_GenerateKey) { + if (mr) + printf("+F15:%u:%s:%f:%f\n", + k, sdf_choices[k].name, sdf_results[k], + 1.0 / sdf_results[k]); + else + printf("128 bits keygen (%s) %8.4fs %8.1f\n", + sdf_choices[k].name, 1.0 / sdf_results[k], + sdf_results[k]); + } + } + ret = 0; end: @@ -5156,6 +5390,14 @@ int speed_main(int argc, char **argv) #endif OPENSSL_free(loopargs[i].secret_a); OPENSSL_free(loopargs[i].secret_b); + + sk_HANDLE_PAIR_pop_free(loopargs[i].key_handles, sdf_destroy_key); + + if (loopargs[i].hSessionHandle != NULL) + TSAPI_SDF_CloseSession(loopargs[i].hSessionHandle); + + if (loopargs[i].hDeviceHandle != NULL) + TSAPI_SDF_CloseDevice(loopargs[i].hDeviceHandle); } OPENSSL_free(evp_hmac_name); OPENSSL_free(evp_cmac_name); diff --git a/apps/version.c b/apps/version.c index 874542349..63be8bf83 100644 --- a/apps/version.c +++ b/apps/version.c @@ -167,7 +167,6 @@ int version_main(int argc, char **argv) } #ifdef SMTC_MODULE if (smtc) { - printf("%s\n", OpenSSL_version(TONGSUO_VERSION)); printf("%s\n", OpenSSL_version(TONGSUO_SMTC_INFO)); } #endif diff --git a/crypto/bio/bss_log.c b/crypto/bio/bss_log.c index 66d8f8868..9f379b8c3 100644 --- a/crypto/bio/bss_log.c +++ b/crypto/bio/bss_log.c @@ -22,30 +22,12 @@ #include "bio_local.h" #include "internal/cryptlib.h" -#if defined(OPENSSL_SYS_WINCE) -#elif defined(OPENSSL_SYS_WIN32) -#elif (!defined(MSDOS) || defined(WATT32)) && !defined(OPENSSL_SYS_VXWORKS) && !defined(NO_SYSLOG) -# include -#endif - +#include #include #include #ifndef NO_SYSLOG -# if defined(OPENSSL_SYS_WIN32) -# define LOG_EMERG 0 -# define LOG_ALERT 1 -# define LOG_CRIT 2 -# define LOG_ERR 3 -# define LOG_WARNING 4 -# define LOG_NOTICE 5 -# define LOG_INFO 6 -# define LOG_DEBUG 7 - -# define LOG_DAEMON (3<<3) -# endif - static int slg_write(BIO *h, const char *buf, int num); static int slg_puts(BIO *h, const char *str); static long slg_ctrl(BIO *h, int cmd, long arg1, void *arg2); diff --git a/crypto/build.info b/crypto/build.info index db0808cac..35b77e29a 100644 --- a/crypto/build.info +++ b/crypto/build.info @@ -6,7 +6,7 @@ SUBDIRS=objects buffer bio stack lhash rand evp asn1 pem x509 conf \ siphash sm3 des aes rc4 rc5 zuc \ sm4 chacha modes bn ec rsa dsa dh sm2 dso engine \ err comp http ocsp cms ts srp cmac ct async ess crmf cmp encode_decode \ - ffc paillier zkp + ffc paillier zkp sdf tsapi LIBS=../libcrypto @@ -96,7 +96,7 @@ SOURCE[../libcrypto]=$UTIL_COMMON \ mem.c mem_sec.c \ cversion.c info.c cpt_err.c ebcdic.c uid.c o_time.c o_dir.c \ o_fopen.c getenv.c o_init.c init.c trace.c provider.c provider_child.c \ - punycode.c passphrase.c + punycode.c passphrase.c o_syslog.c SOURCE[../providers/libfips.a]=$UTIL_COMMON SOURCE[../libcrypto]=$UPLINKSRC @@ -128,3 +128,14 @@ INCLUDE[s390xcpuid.o]=. IF[{- $config{target} =~ /^(?:Cygwin|mingw|VC-|BC-)/ -}] SHARED_SOURCE[../libcrypto]=dllmain.c ENDIF + +{- use File::Spec::Functions; + our $ex_lib = $withargs{sdf_lib} && + (file_name_is_absolute($withargs{sdf_lib}) ? + $withargs{sdf_lib} : catfile(updir(), $withargs{sdf_lib})); + "" +-} + +IF[{- !$disabled{sdf_lib} -}] + DEPEND[../libcrypto]={- $ex_lib -} +ENDIF 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 bd9bd818d..540ebdc2a 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 @@ -990,6 +989,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/evp/m_sigver.c b/crypto/evp/m_sigver.c index 76a6814b4..1d9534716 100644 --- a/crypto/evp/m_sigver.c +++ b/crypto/evp/m_sigver.c @@ -63,10 +63,16 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, if (ctx->pctx == NULL) { reinit = 0; - if (e == NULL) - ctx->pctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, props); - else + if (e == NULL) { +#ifdef SMTC_MODULE + if (ver) + ctx->pctx = EVP_PKEY_CTX_new_from_pkey_provided(libctx, pkey, props); + else +#endif + ctx->pctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, props); + } else { ctx->pctx = EVP_PKEY_CTX_new(pkey, e); + } } if (ctx->pctx == NULL) return 0; diff --git a/crypto/evp/pmeth_gn.c b/crypto/evp/pmeth_gn.c index 8e4940ed5..48e222631 100644 --- a/crypto/evp/pmeth_gn.c +++ b/crypto/evp/pmeth_gn.c @@ -230,6 +230,11 @@ int EVP_PKEY_generate(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey) default: goto not_supported; } + +# ifndef OPENSSL_NO_SM2 + if (ret > 0 && EVP_PKEY_CTX_is_a(ctx, "SM2")) + ret = EVP_PKEY_set_alias_type(*ppkey, EVP_PKEY_SM2); +# endif #endif end: @@ -271,6 +276,10 @@ int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey) ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED); return -1; } + +#ifdef SMTC_MODULE + OSSL_syslog(LOG_INFO, "Creating a key pair\n"); +#endif return EVP_PKEY_generate(ctx, ppkey); } diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c index 26d3e902d..a9cac26e3 100644 --- a/crypto/evp/pmeth_lib.c +++ b/crypto/evp/pmeth_lib.c @@ -375,6 +375,82 @@ EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_pkey(OSSL_LIB_CTX *libctx, EVP_PKEY *pkey, return int_ctx_new(libctx, pkey, NULL, NULL, propquery, -1); } +EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_pkey_provided(OSSL_LIB_CTX *libctx, + EVP_PKEY *pkey, + const char *propquery) +{ + EVP_PKEY_CTX *ret = NULL; + + if (pkey == NULL) { + ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + if (!evp_pkey_is_provided(pkey)) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY); + return NULL; + } + + ret = OPENSSL_zalloc(sizeof(*ret)); + if (ret == NULL) { + ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + return NULL; + } + + if (propquery != NULL) { + ret->propquery = OPENSSL_strdup(propquery); + if (ret->propquery == NULL) { + OPENSSL_free(ret); + return NULL; + } + } + + ret->libctx = libctx; + ret->operation = EVP_PKEY_OP_UNDEFINED; + ret->keymgmt = pkey->keymgmt; + EVP_KEYMGMT_up_ref(pkey->keymgmt); + + ret->keytype = EVP_KEYMGMT_get0_name(ret->keymgmt); + ret->pkey = pkey; + EVP_PKEY_up_ref(pkey); + + return ret; +} + +EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_name_provided(OSSL_LIB_CTX *libctx, + const char *name, + const char *propquery) +{ + EVP_PKEY_CTX *ret = NULL; + EVP_KEYMGMT *keymgmt; + + keymgmt = EVP_KEYMGMT_fetch(libctx, name, propquery); + if (keymgmt == NULL) + return NULL; + + ret = OPENSSL_zalloc(sizeof(*ret)); + if (ret == NULL) { + EVP_KEYMGMT_free(keymgmt); + ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + return NULL; + } + + if (propquery != NULL) { + ret->propquery = OPENSSL_strdup(propquery); + if (ret->propquery == NULL) { + OPENSSL_free(ret); + EVP_KEYMGMT_free(keymgmt); + return NULL; + } + } + + ret->operation = EVP_PKEY_OP_UNDEFINED; + ret->keymgmt = keymgmt; + ret->keytype = EVP_KEYMGMT_get0_name(keymgmt); + + return ret; +} + void evp_pkey_ctx_free_old_ops(EVP_PKEY_CTX *ctx) { if (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)) { diff --git a/crypto/info.c b/crypto/info.c index 69142d396..5984426fc 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; } @@ -200,6 +206,12 @@ const char *OPENSSL_info(int t) if (ossl_cpu_info_str[0] != '\0') return ossl_cpu_info_str + strlen(CPUINFO_PREFIX); break; +#ifdef SMTC_MODULE + case OPENSSL_INFO_SMTC_MODULE_CONF: + return SMTC_MODULE_CONF; + case OPENSSL_INFO_SMTC_AUTH_KEK: + return SMTC_AUTH_KEK; +#endif default: break; } diff --git a/crypto/init.c b/crypto/init.c index f4df1d983..4f20b7c33 100644 --- a/crypto/init.c +++ b/crypto/init.c @@ -10,6 +10,7 @@ /* We need to use some engine deprecated APIs */ #define OPENSSL_SUPPRESS_DEPRECATED +#include "internal/sdf.h" #include "internal/e_os.h" #include "crypto/cryptlib.h" #include @@ -445,6 +446,9 @@ void OPENSSL_cleanup(void) OSSL_CMP_log_close(); #endif + OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_sdf_lib_cleanup()\n"); + ossl_sdf_lib_cleanup(); + OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_trace_cleanup()\n"); ossl_trace_cleanup(); diff --git a/crypto/o_syslog.c b/crypto/o_syslog.c new file mode 100644 index 000000000..49ce4b437 --- /dev/null +++ b/crypto/o_syslog.c @@ -0,0 +1,80 @@ +/* + * 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 +#include +#include +#include "internal/nelem.h" + +static int logging = 0; + +void OSSL_enable_syslog(void) +{ + logging = 1; +} + +void OSSL_disable_syslog(void) +{ + logging = 0; +} + +void OSSL_syslog(int priority, const char *message, ...) +{ + va_list args; + unsigned char buf[4096]; + BIO *bio = NULL; + size_t i; + int written = 0, ret; + const struct { + int log_level; + const char *str; + } mapping[] = { + { LOG_EMERG, "EMERG" }, + { LOG_ALERT, "ALERT" }, + { LOG_CRIT, "CRIT" }, + { LOG_ERR, "ERROR" }, + { LOG_WARNING, "WARNING" }, + { LOG_NOTICE, "NOTICE" }, + { LOG_INFO, "INFO" }, + { LOG_DEBUG, "DEBUG" }, + }; + + if (logging == 0) + return; + + bio = BIO_new(BIO_s_log()); + if (bio == NULL) + return; + + for (i = 0; i < OSSL_NELEM(mapping); i++) { + if (mapping[i].log_level == priority) { + ret = BIO_snprintf((char *)buf, sizeof(buf), "%s ", mapping[i].str); + if (ret < 0) + goto end; + + written += ret; + break; + } + } + + va_start(args, message); + ret = BIO_vsnprintf((char *)buf, sizeof(buf) - written, message, args); + va_end(args); + + if (ret < 0) + goto end; + + written += ret; + + if (BIO_write(bio, buf, written) != written) + goto end; + +end: + BIO_free(bio); +} diff --git a/crypto/provider.c b/crypto/provider.c index 114b42692..e2001a2db 100644 --- a/crypto/provider.c +++ b/crypto/provider.c @@ -99,6 +99,16 @@ const OSSL_DISPATCH *OSSL_PROVIDER_get0_dispatch(const OSSL_PROVIDER *prov) return ossl_provider_get0_dispatch(prov); } +int OSSL_PROVIDER_reset(OSSL_PROVIDER *prov) +{ + return ossl_provider_reset(prov); +} + +int OSSL_PROVIDER_status(const OSSL_PROVIDER *prov) +{ + return ossl_provider_status(prov); +} + int OSSL_PROVIDER_self_test(const OSSL_PROVIDER *prov) { return ossl_provider_self_test(prov); diff --git a/crypto/provider_core.c b/crypto/provider_core.c index 177358f05..0c439ed6c 100644 --- a/crypto/provider_core.c +++ b/crypto/provider_core.c @@ -172,6 +172,8 @@ 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_status_fn *status; + OSSL_FUNC_provider_reset_fn *reset; /* * Cache of bit to indicate of query_operation() has been called on @@ -944,6 +946,12 @@ static int provider_init(OSSL_PROVIDER *prov) prov->unquery_operation = OSSL_FUNC_provider_unquery_operation(provider_dispatch); break; + case OSSL_FUNC_PROVIDER_STATUS: + prov->status = OSSL_FUNC_provider_status(provider_dispatch); + break; + case OSSL_FUNC_PROVIDER_RESET: + prov->reset = OSSL_FUNC_provider_reset(provider_dispatch); + break; #ifndef OPENSSL_NO_ERR # ifndef FIPS_MODULE case OSSL_FUNC_PROVIDER_GET_REASON_STRINGS: @@ -1492,6 +1500,22 @@ int ossl_provider_get_params(const OSSL_PROVIDER *prov, OSSL_PARAM params[]) ? 0 : prov->get_params(prov->provctx, params); } +int ossl_provider_reset(OSSL_PROVIDER *prov) +{ + if (prov->reset == NULL) + return 1; + + return prov->reset(prov->provctx); +} + +int ossl_provider_status(const OSSL_PROVIDER *prov) +{ + if (prov->status == NULL) + return 1; + + return prov->status(prov->provctx); +} + int ossl_provider_self_test(const OSSL_PROVIDER *prov) { int ret; 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/sdf/build.info b/crypto/sdf/build.info new file mode 100644 index 000000000..b847b6587 --- /dev/null +++ b/crypto/sdf/build.info @@ -0,0 +1,3 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + sdf_lib.c sdf_meth.c \ No newline at end of file diff --git a/crypto/sdf/sdf_lib.c b/crypto/sdf/sdf_lib.c new file mode 100644 index 000000000..ce8824196 --- /dev/null +++ b/crypto/sdf/sdf_lib.c @@ -0,0 +1,416 @@ +/* + * 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 +#include +#include +#include "internal/thread_once.h" +#include "internal/dso.h" +#include "internal/sdf.h" +#include "sdf_local.h" + +#ifdef SDF_LIB +# ifdef SDF_LIB_SHARED +static DSO *sdf_dso = NULL; +# else +extern int SDF_OpenDevice(void **phDeviceHandle) __attribute__((weak)); +extern int SDF_CloseDevice(void *hDeviceHandle) __attribute__((weak)); +extern int SDF_OpenSession(void *hDeviceHandle, void **phSessionHandle) __attribute__((weak)); +extern int SDF_CloseSession(void *hSessionHandle) __attribute__((weak)); + +extern int SDF_GenerateRandom(void *hSessionHandle, unsigned int uiLength, + unsigned char *pucRandom) __attribute__((weak)); + +extern int SDF_GetPrivateKeyAccessRight(void *hSessionHandle, + unsigned int uiKeyIndex, unsigned char *pucPassword, + unsigned int uiPwdLength); + +extern int SDF_ReleasePrivateKeyAccessRight(void *hSessionHandle, + unsigned int uiKeyIndex); + +extern int SDF_ImportKeyWithISK_ECC(void *hSessionHandle, + unsigned int uiISKIndex, OSSL_ECCCipher *pucKey, + void **phKeyHandle) __attribute__((weak)); + +extern int SDF_ImportKeyWithKEK(void *hSessionHandle, + unsigned int uiAlgID, unsigned int uiKEKIndex, unsigned char *pucKey, + unsigned int puiKeyLength, void **phKeyHandle) __attribute__((weak)); + +extern int SDF_ExportSignPublicKey_ECC(void *hSessionHandle, + unsigned int uiKeyIndex, OSSL_ECCrefPublicKey *pucPublicKey) + __attribute__((weak)); + +extern int SDF_ExportEncPublicKey_ECC(void *hSessionHandle, + unsigned int uiKeyIndex, OSSL_ECCrefPublicKey *pucPublicKey) + __attribute__((weak)); + +extern int SDF_DestroyKey(void *hSessionHandle, void *hKeyHandle) + __attribute__((weak)); + +extern int SDF_InternalEncrypt_ECC(void *hSessionHandle, + unsigned int uiISKIndex, unsigned char *pucData, unsigned int uiDataLength, + OSSL_ECCCipher * pucEncData); + +extern int SDF_InternalDecrypt_ECC(void *hSessionHandle, + unsigned int uiISKIndex, OSSL_ECCCipher *pucEncData, + unsigned char *pucData, unsigned int *puiDataLength); + +extern int SDF_InternalSign_ECC(void * hSessionHandle, unsigned int uiISKIndex, + unsigned char * pucData, unsigned int uiDataLength, + OSSL_ECCSignature * pucSignature); + +extern int SDF_Encrypt(void *hSessionHandle, void *hKeyHandle, + unsigned int uiAlgID, unsigned char *pucIV, unsigned char *pucData, + unsigned int uiDataLength, unsigned char *pucEncData, + unsigned int *puiEncDataLength) __attribute__((weak)); + +extern int SDF_Decrypt(void *hSessionHandle, void *hKeyHandle, + unsigned int uiAlgID, unsigned char *pucIV, unsigned char *pucEncData, + unsigned int uiEncDataLength, unsigned char *pucData, + unsigned int *puiDataLength) __attribute__((weak)); + +extern int SDF_CalculateMAC(void *hSessionHandle, void *hKeyHandle, + unsigned int uiAlgID, unsigned char *pucIV, unsigned char *pucData, + unsigned int uiDataLength, unsigned char *pucMac, + unsigned int *puiMACLength) __attribute__((weak)); + +extern int SDFE_GenerateKey(void *hSessionHandle, uint8_t type, uint8_t no_kek, + uint32_t len, void **pkey_handle) __attribute__((weak)); +# endif + +static CRYPTO_ONCE sdf_lib_once = CRYPTO_ONCE_STATIC_INIT; +static SDF_METHOD sdfm; + +DEFINE_RUN_ONCE_STATIC(ossl_sdf_lib_init) +{ +# ifdef SDF_LIB_SHARED +# ifndef LIBSDF +# define LIBSDF "sdf" +# endif + + sdf_dso = DSO_load(NULL, LIBSDF, NULL, 0); + if (sdf_dso != NULL) { + sdfm.OpenDevice = DSO_bind_func(sdf_dso, "SDF_OpenDevice"); + sdfm.CloseDevice = DSO_bind_func(sdf_dso, "SDF_CloseDevice"); + sdfm.OpenSession = DSO_bind_func(sdf_dso, "SDF_OpenSession"); + sdfm.CloseSession = DSO_bind_func(sdf_dso, "SDF_CloseSession"); + sdfm.GenerateRandom = DSO_bind_func(sdf_dso, "SDF_GenerateRandom"); + sdfm.GetPrivateKeyAccessRight = DSO_bind_func(sdf_dso, "SDF_GetPrivateKeyAccessRight"); + sdfm.ReleasePrivateKeyAccessRight = DSO_bind_func(sdf_dso, "SDF_ReleasePrivateKeyAccessRight"); + sdfm.ImportKeyWithISK_ECC = DSO_bind_func(sdf_dso, "SDF_ImportKeyWithISK_ECC"); + sdfm.ImportKeyWithKEK = DSO_bind_func(sdf_dso, "SDF_ImportKeyWithKEK"); + sdfm.ExportSignPublicKey_ECC = DSO_bind_func(sdf_dso, "SDF_ExportSignPublicKey_ECC"); + sdfm.ExportEncPublicKey_ECC = DSO_bind_func(sdf_dso, "SDF_ExportEncPublicKey_ECC"); + sdfm.DestroyKey = DSO_bind_func(sdf_dso, "SDF_DestroyKey"); + sdfm.InternalEncrypt_ECC = DSO_bind_func(sdf_dso, "SDF_InternalEncrypt_ECC"); + sdfm.InternalDecrypt_ECC = DSO_bind_func(sdf_dso, "SDF_InternalDecrypt_ECC"); + sdfm.InternalSign_ECC = DSO_bind_func(sdf_dso, "SDF_InternalSign_ECC"); + sdfm.Encrypt = DSO_bind_func(sdf_dso, "SDF_Encrypt"); + sdfm.Decrypt = DSO_bind_func(sdf_dso, "SDF_Decrypt"); + sdfm.CalculateMAC = DSO_bind_func(sdf_dso, "SDF_CalculateMAC"); + sdfm.GenerateKey = DSO_bind_func(sdf_dso, "SDFE_GenerateKey"); + } +# else + sdfm.OpenDevice = SDF_OpenDevice; + sdfm.CloseDevice = SDF_CloseDevice; + sdfm.OpenSession = SDF_OpenSession; + sdfm.CloseSession = SDF_CloseSession; + sdfm.GenerateRandom = SDF_GenerateRandom; + sdfm.GetPrivateKeyAccessRight = SDF_GetPrivateKeyAccessRight; + sdfm.ReleasePrivateKeyAccessRight = SDF_ReleasePrivateKeyAccessRight; + sdfm.ImportKeyWithISK_ECC = SDF_ImportKeyWithISK_ECC; + sdfm.ImportKeyWithKEK = SDF_ImportKeyWithKEK; + sdfm.ExportSignPublicKey_ECC = SDF_ExportSignPublicKey_ECC; + sdfm.ExportEncPublicKey_ECC = SDF_ExportEncPublicKey_ECC; + sdfm.DestroyKey = SDF_DestroyKey; + sdfm.InternalEncrypt_ECC = SDF_InternalEncrypt_ECC; + sdfm.InternalDecrypt_ECC = SDF_InternalDecrypt_ECC; + sdfm.InternalSign_ECC = SDF_InternalSign_ECC; + sdfm.Encrypt = SDF_Encrypt; + sdfm.Decrypt = SDF_Decrypt; + sdfm.CalculateMAC = SDF_CalculateMAC; + sdfm.GenerateKey = SDFE_GenerateKey; +# endif + return 1; +} +#endif + +void ossl_sdf_lib_cleanup(void) +{ +#ifdef SDF_LIB_SHARED + DSO_free(sdf_dso); + sdf_dso = NULL; +#endif +} + +static const SDF_METHOD *sdf_get_method(void) +{ + const SDF_METHOD *meth = &ts_sdf_meth; + +#ifdef SDF_LIB + if (RUN_ONCE(&sdf_lib_once, ossl_sdf_lib_init)) + meth = &sdfm; +#endif + + return meth; +} + +int TSAPI_SDF_OpenDevice(void **phDeviceHandle) +{ + const SDF_METHOD *meth = sdf_get_method(); + + if (meth == NULL || meth->OpenDevice == NULL) + return OSSL_SDR_NOTSUPPORT; + + return meth->OpenDevice(phDeviceHandle); +} + +int TSAPI_SDF_CloseDevice(void *hDeviceHandle) +{ + const SDF_METHOD *meth = sdf_get_method(); + + if (hDeviceHandle == NULL) + return OSSL_SDR_OK; + + if (meth == NULL || meth->CloseDevice == NULL) + return OSSL_SDR_NOTSUPPORT; + + return meth->CloseDevice(hDeviceHandle); +} + +int TSAPI_SDF_OpenSession(void *hDeviceHandle, void **phSessionHandle) +{ + const SDF_METHOD *meth = sdf_get_method(); + + if (meth == NULL || meth->OpenSession == NULL) + return OSSL_SDR_NOTSUPPORT; + + return meth->OpenSession(hDeviceHandle, phSessionHandle); +} + +int TSAPI_SDF_CloseSession(void *hSessionHandle) +{ + const SDF_METHOD *meth = sdf_get_method(); + + if (hSessionHandle == NULL) + return OSSL_SDR_OK; + + if (meth == NULL || meth->CloseSession == NULL) + return OSSL_SDR_NOTSUPPORT; + + return meth->CloseSession(hSessionHandle); +} + +int TSAPI_SDF_GenerateRandom(void *hSessionHandle, unsigned int uiLength, + unsigned char *pucRandom) +{ +#define MAX_RANDOM_LEN (2048) + int ret; + unsigned int len; + const SDF_METHOD *meth = sdf_get_method(); + + if (meth == NULL || meth->GenerateRandom == NULL) + return OSSL_SDR_NOTSUPPORT; + + do { + if (uiLength > MAX_RANDOM_LEN) + len = MAX_RANDOM_LEN; + else + len = uiLength; + + if ((ret = meth->GenerateRandom(hSessionHandle, len, pucRandom)) != 0) + return ret; + + uiLength -= len; + pucRandom += len; + } while (uiLength > 0); + + return OSSL_SDR_OK; +} + +int TSAPI_SDF_GetPrivateKeyAccessRight(void *hSessionHandle, + unsigned int uiKeyIndex, + unsigned char *pucPassword, + unsigned int uiPwdLength) +{ + const SDF_METHOD *meth = sdf_get_method(); + + if (meth == NULL || meth->GetPrivateKeyAccessRight == NULL) + return OSSL_SDR_NOTSUPPORT; + + return meth->GetPrivateKeyAccessRight(hSessionHandle, uiKeyIndex, + pucPassword, uiPwdLength); +} + +int TSAPI_SDF_ReleasePrivateKeyAccessRight(void *hSessionHandle, + unsigned int uiKeyIndex) +{ + const SDF_METHOD *meth = sdf_get_method(); + + if (meth == NULL || meth->ReleasePrivateKeyAccessRight == NULL) + return OSSL_SDR_NOTSUPPORT; + + return meth->ReleasePrivateKeyAccessRight(hSessionHandle, uiKeyIndex); +} + +int TSAPI_SDF_ImportKeyWithISK_ECC(void *hSessionHandle, + unsigned int uiISKIndex, + OSSL_ECCCipher *pucKey, + void **phKeyHandle) +{ + const SDF_METHOD *meth = sdf_get_method(); + + if (meth == NULL || meth->ImportKeyWithISK_ECC == NULL) + return OSSL_SDR_NOTSUPPORT; + + return meth->ImportKeyWithISK_ECC(hSessionHandle, uiISKIndex, pucKey, + phKeyHandle); +} + +int TSAPI_SDF_ImportKeyWithKEK(void *hSessionHandle, unsigned int uiAlgID, + unsigned int uiKEKIndex, unsigned char *pucKey, + unsigned int puiKeyLength, void **phKeyHandle) +{ + const SDF_METHOD *meth = sdf_get_method(); + + if (meth == NULL || meth->ImportKeyWithKEK == NULL) + return OSSL_SDR_NOTSUPPORT; + + return meth->ImportKeyWithKEK(hSessionHandle, uiAlgID, uiKEKIndex, pucKey, + puiKeyLength, phKeyHandle); +} + +int TSAPI_SDF_Encrypt(void *hSessionHandle, void *hKeyHandle, + unsigned int uiAlgID, unsigned char *pucIV, + unsigned char *pucData, unsigned int uiDataLength, + unsigned char *pucEncData, unsigned int *puiEncDataLength) +{ + const SDF_METHOD *meth = sdf_get_method(); + + if (meth == NULL || meth->Encrypt == NULL) + return OSSL_SDR_NOTSUPPORT; + + return meth->Encrypt(hSessionHandle, hKeyHandle, uiAlgID, pucIV, pucData, + uiDataLength, pucEncData, puiEncDataLength); +} + +int TSAPI_SDF_Decrypt(void *hSessionHandle, void *hKeyHandle, + unsigned int uiAlgID, unsigned char *pucIV, + unsigned char *pucEncData, unsigned int uiEncDataLength, + unsigned char *pucData, unsigned int *puiDataLength) +{ + const SDF_METHOD *meth = sdf_get_method(); + + if (meth == NULL || meth->Decrypt == NULL) + return OSSL_SDR_NOTSUPPORT; + + return meth->Decrypt(hSessionHandle, hKeyHandle, uiAlgID, pucIV, + pucEncData, uiEncDataLength, pucData, puiDataLength); +} + +int TSAPI_SDF_CalculateMAC(void *hSessionHandle, void *hKeyHandle, + unsigned int uiAlgID, unsigned char *pucIV, + unsigned char *pucData, unsigned int uiDataLength, + unsigned char *pucMac, unsigned int *puiMACLength) +{ + const SDF_METHOD *meth = sdf_get_method(); + + if (meth == NULL || meth->CalculateMAC == NULL) + return OSSL_SDR_NOTSUPPORT; + + return meth->CalculateMAC(hSessionHandle, hKeyHandle, uiAlgID, pucIV, + pucData, uiDataLength, pucMac, puiMACLength); +} + +int TSAPI_SDF_GenerateKey(void *hSessionHandle, uint8_t type, uint8_t no_kek, + uint32_t len, void **pkey_handle) +{ + const SDF_METHOD *meth = sdf_get_method(); + + if (meth == NULL || meth->GenerateKey == NULL) + return OSSL_SDR_NOTSUPPORT; + + return meth->GenerateKey(hSessionHandle, type, no_kek, len, pkey_handle); +} + +int TSAPI_SDF_DestroyKey(void *hSessionHandle, void *hKeyHandle) +{ + const SDF_METHOD *meth = sdf_get_method(); + + if (meth == NULL || meth->DestroyKey == NULL) + return OSSL_SDR_NOTSUPPORT; + + return meth->DestroyKey(hSessionHandle, hKeyHandle); +} + +int TSAPI_SDF_ExportSignPublicKey_ECC(void *hSessionHandle, + unsigned int uiKeyIndex, + OSSL_ECCrefPublicKey *pucPublicKey) +{ + const SDF_METHOD *meth = sdf_get_method(); + + if (meth == NULL || meth->ExportSignPublicKey_ECC == NULL) + return OSSL_SDR_NOTSUPPORT; + + return meth->ExportSignPublicKey_ECC(hSessionHandle, uiKeyIndex, pucPublicKey); +} + +int TSAPI_SDF_ExportEncPublicKey_ECC(void *hSessionHandle, + unsigned int uiKeyIndex, + OSSL_ECCrefPublicKey *pucPublicKey) +{ + const SDF_METHOD *meth = sdf_get_method(); + + if (meth == NULL || meth->ExportEncPublicKey_ECC == NULL) + return OSSL_SDR_NOTSUPPORT; + + return meth->ExportEncPublicKey_ECC(hSessionHandle, uiKeyIndex, pucPublicKey); +} + +int TSAPI_SDF_InternalEncrypt_ECC(void *hSessionHandle, unsigned int uiISKIndex, + unsigned char *pucData, + unsigned int uiDataLength, + OSSL_ECCCipher *pucEncData) +{ + const SDF_METHOD *meth = sdf_get_method(); + + if (meth == NULL || meth->InternalEncrypt_ECC == NULL) + return OSSL_SDR_NOTSUPPORT; + + return meth->InternalEncrypt_ECC(hSessionHandle, uiISKIndex, pucData, + uiDataLength, pucEncData); +} + +int TSAPI_SDF_InternalDecrypt_ECC(void *hSessionHandle, unsigned int uiISKIndex, + OSSL_ECCCipher *pucEncData, + unsigned char *pucData, + unsigned int *puiDataLength) +{ + const SDF_METHOD *meth = sdf_get_method(); + + if (meth == NULL || meth->InternalDecrypt_ECC == NULL) + return OSSL_SDR_NOTSUPPORT; + + return meth->InternalDecrypt_ECC(hSessionHandle, uiISKIndex, pucEncData, + pucData, puiDataLength); +} + +int TSAPI_SDF_InternalSign_ECC(void *hSessionHandle, unsigned int uiISKIndex, + unsigned char *pucData, + unsigned int uiDataLength, + OSSL_ECCSignature *pucSignature) +{ + const SDF_METHOD *meth = sdf_get_method(); + + if (meth == NULL || meth->InternalSign_ECC == NULL) + return OSSL_SDR_NOTSUPPORT; + + return meth->InternalSign_ECC(hSessionHandle, uiISKIndex, pucData, + uiDataLength, pucSignature); +} diff --git a/crypto/sdf/sdf_local.h b/crypto/sdf/sdf_local.h new file mode 100644 index 000000000..f2187c504 --- /dev/null +++ b/crypto/sdf/sdf_local.h @@ -0,0 +1,130 @@ +/* + * 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 OSSL_CRYPTO_SDF_LOCAL_H +# define OSSL_CRYPTO_SDF_LOCAL_H + +# include +# include + +# define OSSL_ECCref_MAX_BITS 512 +# define OSSL_ECCref_MAX_LEN ((OSSL_ECCref_MAX_BITS + 7) / 8) + +# pragma pack(1) +struct OSSL_ECCrefPrivateKey_st { + unsigned int bits; + unsigned char K[OSSL_ECCref_MAX_LEN]; +}; + +struct OSSL_ECCrefPublicKey_st{ + unsigned int bits; + unsigned char x[OSSL_ECCref_MAX_LEN]; + unsigned char y[OSSL_ECCref_MAX_LEN]; +}; + +struct OSSL_ECCCipher_st { + unsigned char x[OSSL_ECCref_MAX_LEN]; + unsigned char y[OSSL_ECCref_MAX_LEN]; + unsigned char M[32]; + unsigned int L; + unsigned char C[1]; +}; + +struct OSSL_ECCSignature_st { + unsigned char r[OSSL_ECCref_MAX_LEN]; + unsigned char s[OSSL_ECCref_MAX_LEN]; +}; +# pragma pack() + +typedef int (*SDF_OpenDevice_fn)(void **phDeviceHandle); +typedef int (*SDF_CloseDevice_fn)(void *hDeviceHandle); +typedef int (*SDF_OpenSession_fn)(void *hDeviceHandle, void **phSessionHandle); +typedef int (*SDF_CloseSession_fn)(void *hSessionHandle); +typedef int (*SDF_GenerateRandom_fn)(void *hSessionHandle, + unsigned int uiLength, unsigned char *pucRandom); + +typedef int (*SDF_GetPrivateKeyAccessRight_fn)(void *hSessionHandle, + unsigned int uiKeyIndex, unsigned char *pucPassword, + unsigned int uiPwdLength); + +typedef int (*SDF_ReleasePrivateKeyAccessRight_fn)(void *hSessionHandle, + unsigned int uiKeyIndex); + +typedef int (*SDF_ImportKeyWithISK_ECC_fn)(void *hSessionHandle, + unsigned int uiISKIndex, OSSL_ECCCipher *pucKey, void **phKeyHandle); + +typedef int (*SDF_ImportKeyWithKEK_fn)(void *hSessionHandle, + unsigned int uiAlgID, unsigned int uiKEKIndex, unsigned char *pucKey, + unsigned int puiKeyLength, void **phKeyHandle); + +typedef int (*SDF_DestroyKey_fn)(void *hSessionHandle, void *hKeyHandle); + +typedef int (*SDF_Encrypt_fn)(void *hSessionHandle, void *hKeyHandle, + unsigned int uiAlgID, unsigned char *pucIV, unsigned char *pucData, + unsigned int uiDataLength, unsigned char *pucEncData, + unsigned int *puiEncDataLength); + +typedef int (*SDF_Decrypt_fn)(void *hSessionHandle, void *hKeyHandle, + unsigned int uiAlgID, unsigned char *pucIV, unsigned char *pucEncData, + unsigned int uiEncDataLength, unsigned char *pucData, + unsigned int *puiDataLength); + +typedef int (*SDF_CalculateMAC_fn)(void *hSessionHandle, void *hKeyHandle, + unsigned int uiAlgID, unsigned char *pucIV, unsigned char *pucData, + unsigned int uiDataLength, unsigned char *pucMac, + unsigned int *puiMACLength); + +typedef int (*SDF_GenerateKey_fn)(void *hSessionHandle, uint8_t type, + uint8_t no_kek, uint32_t len, void **pkey_handle); + +typedef int (*SDF_ExportSignPublicKey_ECC_fn)(void *hSessionHandle, + unsigned int uiKeyIndex, OSSL_ECCrefPublicKey *pucPublicKey); + +typedef int (*SDF_ExportEncPublicKey_ECC_fn)(void *hSessionHandle, + unsigned int uiKeyIndex, OSSL_ECCrefPublicKey *pucPublicKey); + +typedef int (*SDF_InternalEncrypt_ECC_fn)(void *hSessionHandle, + unsigned int uiISKIndex, unsigned char *pucData, unsigned int uiDataLength, + OSSL_ECCCipher *pucEncData); +typedef int (*SDF_InternalDecrypt_ECC_fn)(void *hSessionHandle, + unsigned int uiISKIndex, OSSL_ECCCipher *pucEncData, unsigned char *pucData, + unsigned int *puiDataLength); + +typedef int (*SDF_InternalSign_ECC_fn)(void *hSessionHandle, + unsigned int uiISKIndex, unsigned char *pucData, unsigned int uiDataLength, + OSSL_ECCSignature *pucSignature); +/* + * Returns 0 for success, others for error code + */ +struct sdf_method_st { + SDF_OpenDevice_fn OpenDevice; + SDF_CloseDevice_fn CloseDevice; + SDF_OpenSession_fn OpenSession; + SDF_CloseSession_fn CloseSession; + SDF_GenerateRandom_fn GenerateRandom; + SDF_GetPrivateKeyAccessRight_fn GetPrivateKeyAccessRight; + SDF_ReleasePrivateKeyAccessRight_fn ReleasePrivateKeyAccessRight; + SDF_ImportKeyWithISK_ECC_fn ImportKeyWithISK_ECC; + SDF_ImportKeyWithKEK_fn ImportKeyWithKEK; + SDF_ExportSignPublicKey_ECC_fn ExportSignPublicKey_ECC; + SDF_ExportEncPublicKey_ECC_fn ExportEncPublicKey_ECC; + SDF_DestroyKey_fn DestroyKey; + SDF_InternalEncrypt_ECC_fn InternalEncrypt_ECC; + SDF_InternalDecrypt_ECC_fn InternalDecrypt_ECC; + SDF_InternalSign_ECC_fn InternalSign_ECC; + SDF_Encrypt_fn Encrypt; + SDF_Decrypt_fn Decrypt; + SDF_CalculateMAC_fn CalculateMAC; + + /* SDF Ext API */ + SDF_GenerateKey_fn GenerateKey; +}; + +extern SDF_METHOD ts_sdf_meth; +#endif diff --git a/crypto/sdf/sdf_meth.c b/crypto/sdf/sdf_meth.c new file mode 100644 index 000000000..d28bc8f8b --- /dev/null +++ b/crypto/sdf/sdf_meth.c @@ -0,0 +1,168 @@ +/* + * 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 +#include +#include "sdf_local.h" + +static int x_OpenDevice(void **phDeviceHandle) +{ + return OSSL_SDR_NOTSUPPORT; +} + +static int x_CloseDevice(void *hDeviceHandle) +{ + return OSSL_SDR_NOTSUPPORT; +} + +static int x_OpenSession(void *hDeviceHandle, void **phSessionHandle) +{ + return OSSL_SDR_NOTSUPPORT; +} + +static int x_CloseSession(void *hSessionHandle) +{ + return OSSL_SDR_NOTSUPPORT; +} + +static int x_GenerateRandom(void *hSessionHandle, unsigned int uiLength, + unsigned char *pucRandom) +{ + return OSSL_SDR_NOTSUPPORT; +} + +static int x_GetPrivateKeyAccessRight(void *hSessionHandle, + unsigned int uiKeyIndex, + unsigned char *pucPassword, + unsigned int uiPwdLength) +{ + return OSSL_SDR_NOTSUPPORT; +} + +static int x_ReleasePrivateKeyAccessRight(void *hSessionHandlek, + unsigned int uiKeyIndex) +{ + return OSSL_SDR_NOTSUPPORT; +} + +static int x_ImportKeyWithISK_ECC(void *hSessionHandle, + unsigned int uiISKIndex, + OSSL_ECCCipher *pucKey, + void **phKeyHandle) +{ + return OSSL_SDR_NOTSUPPORT; +} + + +static int x_ImportKeyWithKEK(void *hSessionHandle, unsigned int uiAlgID, + unsigned int uiKEKIndex, unsigned char *pucKey, + unsigned int puiKeyLength, void **phKeyHandle) +{ + return OSSL_SDR_NOTSUPPORT; +} + +static int x_ExportSignPublicKey_ECC(void *hSessionHandle, + unsigned int uiKeyIndex, + OSSL_ECCrefPublicKey *pucPublicKey) +{ + return OSSL_SDR_NOTSUPPORT; +} + +static int x_ExportEncPublicKey_ECC(void *hSessionHandle, + unsigned int uiKeyIndex, + OSSL_ECCrefPublicKey *pucPublicKey) +{ + return OSSL_SDR_NOTSUPPORT; +} + +static int x_DestroyKey(void *hSessionHandle, void *hKeyHandle) +{ + return OSSL_SDR_NOTSUPPORT; +} + +static int x_InternalEncrypt_ECC(void *hSessionHandle, unsigned int uiISKIndex, + unsigned char *pucData, + unsigned int uiDataLength, + OSSL_ECCCipher *pucEncData) +{ + return OSSL_SDR_NOTSUPPORT; +} + +static int x_InternalDecrypt_ECC(void *hSessionHandle, unsigned int uiISKIndex, + OSSL_ECCCipher *pucEncData, + unsigned char *pucData, + unsigned int *puiDataLength) +{ + return OSSL_SDR_NOTSUPPORT; +} + +static int x_InternalSign_ECC(void *hSessionHandle, unsigned int uiISKIndex, + unsigned char * pucData, + unsigned int uiDataLength, + OSSL_ECCSignature *pucSignature) +{ + return OSSL_SDR_NOTSUPPORT; +} + +static int x_Encrypt(void *hSessionHandle, void *hKeyHandle, + unsigned int uiAlgID, unsigned char *pucIV, + unsigned char *pucData, + unsigned int uiDataLength, + unsigned char *pucEncData, + unsigned int *puiEncDataLength) +{ + return OSSL_SDR_NOTSUPPORT; +} + +static int x_Decrypt(void *hSessionHandle, void *hKeyHandle, + unsigned int uiAlgID, unsigned char *pucIV, + unsigned char *pucEncData, unsigned int uiEncDataLength, + unsigned char *pucData, + unsigned int *puiDataLength) +{ + return OSSL_SDR_NOTSUPPORT; +} + +static int x_CalculateMAC(void *hSessionHandle, void *hKeyHandle, + unsigned int uiAlgID, unsigned char *pucIV, + unsigned char *pucData, unsigned int uiDataLength, + unsigned char *pucMac, unsigned int *puiMACLength) +{ + return OSSL_SDR_NOTSUPPORT; +} + +static int x_GenerateKey(void *hSessionHandle, uint8_t type, uint8_t no_kek, + uint32_t len, void **pkey_handle) +{ + return OSSL_SDR_NOTSUPPORT; +} + +SDF_METHOD ts_sdf_meth = { + x_OpenDevice, + x_CloseDevice, + x_OpenSession, + x_CloseSession, + x_GenerateRandom, + x_GetPrivateKeyAccessRight, + x_ReleasePrivateKeyAccessRight, + x_ImportKeyWithISK_ECC, + x_ImportKeyWithKEK, + x_ExportSignPublicKey_ECC, + x_ExportEncPublicKey_ECC, + x_DestroyKey, + x_InternalEncrypt_ECC, + x_InternalDecrypt_ECC, + x_InternalSign_ECC, + x_Encrypt, + x_Decrypt, + x_CalculateMAC, + + /* SDF Ext API */ + x_GenerateKey, +}; diff --git a/crypto/sm2/sm2_crypt.c b/crypto/sm2/sm2_crypt.c index 177df5bac..d899318d3 100644 --- a/crypto/sm2/sm2_crypt.c +++ b/crypto/sm2/sm2_crypt.c @@ -392,6 +392,62 @@ int ossl_sm2_decrypt(const EC_KEY *key, return rc; } +unsigned char *ossl_sm2_ciphertext_encode(const BIGNUM *C1x, const BIGNUM *C1y, + const uint8_t *C2_data, size_t C2_len, + const uint8_t *C3_data, size_t C3_len, + size_t *ciphertext_len) +{ + unsigned char *ciphertext_buf = NULL; + struct SM2_Ciphertext_st ctext_struct; + int ciphertext_leni; + + if (C1x == NULL || C1y == NULL || C2_data == NULL || C3_data == NULL) { + ERR_raise(ERR_LIB_SM2, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + memset(&ctext_struct, 0, sizeof(ctext_struct)); + + ctext_struct.C1x = (BIGNUM *)C1x; + ctext_struct.C1y = (BIGNUM *)C1y; + ctext_struct.C2 = ASN1_OCTET_STRING_new(); + + if (ctext_struct.C2 == NULL) { + ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); + goto end; + } + + if (!ASN1_OCTET_STRING_set(ctext_struct.C2, C2_data, C2_len)) + goto end; + + ctext_struct.C3 = ASN1_OCTET_STRING_new(); + + if (ctext_struct.C3 == NULL) { + ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); + goto end; + } + + if (!ASN1_OCTET_STRING_set(ctext_struct.C3, C3_data, C3_len)) + goto end; + + ciphertext_leni = i2d_SM2_Ciphertext(&ctext_struct, &ciphertext_buf); + /* Ensure cast to size_t is safe */ + if (ciphertext_leni < 0) { + ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR); + goto end; + } + *ciphertext_len = (size_t)ciphertext_leni; + + end: + if (ctext_struct.C2 != NULL) + ASN1_OCTET_STRING_free(ctext_struct.C2); + + if (ctext_struct.C3 != NULL) + ASN1_OCTET_STRING_free(ctext_struct.C3); + + return ciphertext_buf; +} + int ossl_sm2_ciphertext_decode(const uint8_t *ciphertext, size_t ciphertext_len, EC_POINT **C1p, uint8_t **C2_data, size_t *C2_len, uint8_t **C3_data, 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/build.info b/crypto/tsapi/build.info new file mode 100644 index 000000000..703ddc366 --- /dev/null +++ b/crypto/tsapi/build.info @@ -0,0 +1,3 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + tsapi_lib.c \ No newline at end of file diff --git a/crypto/tsapi/tsapi_lib.c b/crypto/tsapi/tsapi_lib.c new file mode 100644 index 000000000..45db1f731 --- /dev/null +++ b/crypto/tsapi/tsapi_lib.c @@ -0,0 +1,1322 @@ +/* + * 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 "internal/deprecated.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "internal/e_os.h" +#include "crypto/rand.h" +#include "crypto/sm2.h" +#include "../sdf/sdf_local.h" +#ifdef SDF_LIB +# include "sdfe_api.h" +#endif + +unsigned char *TSAPI_GetEntropy(int entropy, size_t *outlen) +{ + unsigned char *out = NULL; + size_t len; + + len = ossl_rand_get_entropy(NULL, &out, entropy, entropy, entropy * 4); + if (len == 0) { + *outlen = 0; + return NULL; + } + + *outlen = len; + return out; +} + +void TSAPI_FreeEntropy(unsigned char *ent, size_t len) +{ + ossl_rand_cleanup_entropy(NULL, ent, len); +} + +unsigned char *TSAPI_RandBytes(size_t len) +{ + unsigned char *buf = OPENSSL_malloc(len); + + if (buf == NULL) + return NULL; + + if (RAND_bytes(buf, (int)len) <= 0) { + OPENSSL_free(buf); + return NULL; + } + + return buf; +} + +char *TSAPI_Version(void) +{ + int ret; + int buflen = 1 + strlen(OpenSSL_version(TONGSUO_VERSION)) + 1 +#ifdef SMTC_MODULE + + strlen(OpenSSL_version(TONGSUO_SMTC_INFO)) + 1 +#endif + ; + char *buf = OPENSSL_malloc(buflen); + + ret = BIO_snprintf((char *)buf, buflen, "%s\n", + OpenSSL_version(TONGSUO_VERSION)); + if (ret < 0) { + OPENSSL_free(buf); + return NULL; + } + +#ifdef SMTC_MODULE + ret = BIO_snprintf(buf + ret, buflen - ret, "%s\n", + OpenSSL_version(TONGSUO_VERSION)); + if (ret < 0) { + OPENSSL_free(buf); + return NULL; + } +#endif + + return buf; +} + +#ifndef OPENSSL_NO_SM2 +int TSAPI_DelSm2KeyWithIndex(int index, int sign, const char *user, + const char *password) +{ + int ok = 0; +#ifdef SDF_LIB + void *hDeviceHandle = NULL; + void *hSessionHandle = NULL; + sdfe_login_arg_t login_arg; + int area; + + if (sign) { + area = SDFE_ASYM_KEY_AREA_SIGN; + } else { + area = SDFE_ASYM_KEY_AREA_ENC; + } + + memset(&login_arg, 0, sizeof(login_arg)); + + login_arg.passwd = (uint8_t *)password; + if (password) + login_arg.passwd_len = strlen(password); + else + login_arg.passwd_len = 0; + + if (user) { + if (strlen(user) >= sizeof(login_arg.name)) + return 0; + + strcpy((char *)login_arg.name, user); + } + + if (TSAPI_SDF_OpenDevice(&hDeviceHandle) != OSSL_SDR_OK) + goto end; + + if (TSAPI_SDF_OpenSession(hDeviceHandle, &hSessionHandle) != OSSL_SDR_OK) + goto end; + + if (SDFE_LoginUsr(hSessionHandle, &login_arg) != OSSL_SDR_OK) + goto end; + + if (SDFE_DelECCKey(hSessionHandle, area, index) + != OSSL_SDR_OK) + goto end; + + ok = 1; +end: + TSAPI_SDF_CloseSession(hSessionHandle); + TSAPI_SDF_CloseDevice(hDeviceHandle); +#endif + return ok; +} + +int TSAPI_GenerateSM2KeyWithIndex(int index, int sign, const char *user, + const char *password) +{ + int ok = 0; +#ifdef SDF_LIB + void *hDeviceHandle = NULL; + void *hSessionHandle = NULL; + sdfe_login_arg_t login_arg; + int area; + + if (sign) + area = SDFE_ASYM_KEY_AREA_SIGN; + else + area = SDFE_ASYM_KEY_AREA_ENC; + + memset(&login_arg, 0, sizeof(login_arg)); + + login_arg.passwd = (uint8_t *)password; + if (password) + login_arg.passwd_len = strlen(password); + else + login_arg.passwd_len = 0; + + if (user) { + if (strlen(user) >= sizeof(login_arg.name)) + return 0; + + strcpy((char *)login_arg.name, user); + } + + if (TSAPI_SDF_OpenDevice(&hDeviceHandle) != OSSL_SDR_OK) + goto end; + + if (TSAPI_SDF_OpenSession(hDeviceHandle, &hSessionHandle) != OSSL_SDR_OK) + goto end; + + if (SDFE_LoginUsr(hSessionHandle, &login_arg) != OSSL_SDR_OK) + goto end; + + if (SDFE_GenECCKey(hSessionHandle, area, index, 0, NULL) != OSSL_SDR_OK) + goto end; + + ok = 1; +end: + TSAPI_SDF_CloseSession(hSessionHandle); + TSAPI_SDF_CloseDevice(hDeviceHandle); +#endif + return ok; +} + +EVP_PKEY *TSAPI_EVP_PKEY_new_from_ECCrefKey(const OSSL_ECCrefPublicKey *pubkey, + const OSSL_ECCrefPrivateKey *privkey) +{ + int ok = 0; + EC_KEY *eckey = NULL; + EC_GROUP *group = NULL; + BN_CTX *ctx = NULL; + EVP_PKEY *pkey = NULL; + BIGNUM *x = NULL, *y = NULL; + int bytes; + + if (pubkey == NULL) + return NULL; + + eckey = EC_KEY_new(); + if (eckey == NULL) + return NULL; + + group = EC_GROUP_new_by_curve_name(NID_sm2); + if (group == NULL) + goto end; + + if (!EC_KEY_set_group(eckey, group)) + goto end; + + bytes = (pubkey->bits + 7) / 8; + + ctx = BN_CTX_new(); + if (ctx == NULL) + goto end; + + BN_CTX_start(ctx); + x = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + + if (BN_bin2bn(pubkey->x + sizeof(pubkey->x) - bytes, bytes, x) == NULL) + goto end; + + if (BN_bin2bn(pubkey->y + sizeof(pubkey->y) - bytes, bytes, y) == NULL) + goto end; + + if (!EC_KEY_set_public_key_affine_coordinates(eckey, x, y)) + goto end; + + if (privkey) { + bytes = (privkey->bits + 7) / 8; + if (BN_bin2bn(privkey->K + sizeof(privkey->K) - bytes, bytes, x) == NULL) + goto end; + + if (!EC_KEY_set_private_key(eckey, x)) + goto end; + } + + pkey = EVP_PKEY_new(); + if (pkey == NULL) + goto end; + + if (!EVP_PKEY_assign_EC_KEY(pkey, eckey)) + goto end; + + eckey = NULL; + + ok = 1; +end: + if (!ok) { + EVP_PKEY_free(pkey); + pkey = NULL; + } + BN_CTX_end(ctx); + BN_CTX_free(ctx); + EC_GROUP_free(group); + EC_KEY_free(eckey); + return pkey; +} + +OSSL_ECCrefPublicKey *TSAPI_EVP_PKEY_get_ECCrefPublicKey(const EVP_PKEY *pkey) +{ + int ok = 0; + const EC_KEY *eckey = NULL; + const EC_GROUP *group = NULL; + const EC_POINT *point = NULL; + BIGNUM *x = NULL, *y = NULL; + BN_CTX *ctx = NULL; + OSSL_ECCrefPublicKey *outkey = NULL; + + if (pkey == NULL) + return NULL; + + eckey = EVP_PKEY_get0_EC_KEY(pkey); + if (eckey == NULL) + return NULL; + + group = EC_KEY_get0_group(eckey); + point = EC_KEY_get0_public_key(eckey); + if (group == NULL || point == NULL) + return NULL; + + ctx = BN_CTX_new(); + if (ctx == NULL) + return NULL; + + BN_CTX_start(ctx); + x = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + if (y == NULL) + goto end; + + if (!EC_POINT_get_affine_coordinates(group, point, x, y, ctx)) + goto end; + + outkey = OPENSSL_zalloc(sizeof(*outkey)); + if (outkey == NULL) + goto end; + + outkey->bits = EVP_PKEY_get_bits(pkey); + + if (BN_bn2bin(x, outkey->x + sizeof(outkey->x) - BN_num_bytes(x)) < 0) + goto end; + if (BN_bn2bin(y, outkey->y + sizeof(outkey->y) - BN_num_bytes(y)) < 0) + goto end; + + ok = 1; +end: + if (!ok) { + OPENSSL_free(outkey); + outkey = NULL; + } + BN_CTX_end(ctx); + BN_CTX_free(ctx); + return outkey; +} + +OSSL_ECCrefPrivateKey *TSAPI_EVP_PKEY_get_ECCrefPrivateKey(const EVP_PKEY *pkey) +{ + int ok = 0; + const EC_KEY *eckey = NULL; + const BIGNUM *priv = NULL; + OSSL_ECCrefPrivateKey *outkey = NULL; + + if (pkey == NULL) + return NULL; + + eckey = EVP_PKEY_get0_EC_KEY(pkey); + if (eckey == NULL) + return NULL; + + priv = EC_KEY_get0_private_key(eckey); + if (priv == NULL) + return NULL; + + outkey = OPENSSL_zalloc(sizeof(*outkey)); + if (outkey == NULL) + goto end; + + outkey->bits = EVP_PKEY_get_bits(pkey); + + if (BN_bn2bin(priv, outkey->K + sizeof(outkey->K) - BN_num_bytes(priv)) < 0) + goto end; + + ok = 1; +end: + if (!ok) { + OPENSSL_free(outkey); + outkey = NULL; + } + return outkey; +} + +int TSAPI_ImportSM2Key(int index, int sign, const char *user, + const char *password, const EVP_PKEY *sm2_pkey) +{ + int ok = 0; +#ifdef SDF_LIB + int area; + void *hDeviceHandle = NULL; + void *hSessionHandle = NULL; + OSSL_ECCrefPrivateKey *privkey = NULL; + OSSL_ECCrefPublicKey *pubkey = NULL; + sdfe_asym_key_ecc_t sm2_key; + sdfe_login_arg_t login_arg; + + memset(&login_arg, 0, sizeof(login_arg)); + memset(&sm2_key, 0, sizeof(sm2_key)); + + login_arg.passwd = (uint8_t *)password; + if (password) + login_arg.passwd_len = strlen(password); + else + login_arg.passwd_len = 0; + + if (user) { + if (strlen(user) >= sizeof(login_arg.name)) + return 0; + + strcpy((char *)login_arg.name, user); + } + + if (TSAPI_SDF_OpenDevice(&hDeviceHandle) != OSSL_SDR_OK) + goto end; + + if (TSAPI_SDF_OpenSession(hDeviceHandle, &hSessionHandle) != OSSL_SDR_OK) + goto end; + + if (SDFE_LoginUsr(hSessionHandle, &login_arg) != OSSL_SDR_OK) + goto end; + + if (sign) + area = SDFE_ASYM_KEY_AREA_SIGN; + else + area = SDFE_ASYM_KEY_AREA_ENC; + + privkey = TSAPI_EVP_PKEY_get_ECCrefPrivateKey(sm2_pkey); + if (privkey == NULL) + goto end; + + pubkey = TSAPI_EVP_PKEY_get_ECCrefPublicKey(sm2_pkey); + if (pubkey == NULL) + goto end; + + sm2_key.area = area; + sm2_key.index = index; + sm2_key.type = SDFE_ASYM_KEY_TYPE_SM2; + sm2_key.privkey_bits = 256; + sm2_key.privkey_len = sm2_key.privkey_bits >> 3; + sm2_key.pubkey_bits = 256; + sm2_key.pubkey_len = (sm2_key.pubkey_bits >> 3) << 1; + + memcpy(sm2_key.pubkey, pubkey, sizeof(*pubkey)); + memcpy(sm2_key.privkey, privkey, sizeof(*privkey)); + + if (SDFE_ImportECCKey(hSessionHandle, &sm2_key, NULL) + != OSSL_SDR_OK) + goto end; + + ok = 1; +end: + TSAPI_SDF_CloseSession(hSessionHandle); + TSAPI_SDF_CloseDevice(hDeviceHandle); +#endif + return ok; +} + +int TSAPI_ImportSM2KeyWithEvlp(int index, int sign, const char *user, + const char *password, unsigned char *key, + size_t keylen, unsigned char *dek, size_t deklen) +{ + int ok = 0; +#ifdef SDF_LIB + int area; + void *hDeviceHandle = NULL; + void *hSessionHandle = NULL; + sdfe_asym_key_ecc_t sm2_key; + sdfe_sym_key_evlp_t sym_key_evlp; + sdfe_login_arg_t login_arg; + + memset(&login_arg, 0, sizeof(login_arg)); + memset(&sm2_key, 0, sizeof(sm2_key)); + memset(&sym_key_evlp, 0, sizeof(sym_key_evlp)); + + login_arg.passwd = (uint8_t *)password; + if (password) + login_arg.passwd_len = strlen(password); + else + login_arg.passwd_len = 0; + + if (user) { + if (strlen(user) >= sizeof(login_arg.name)) + return 0; + + strcpy((char *)login_arg.name, user); + } + + if (TSAPI_SDF_OpenDevice(&hDeviceHandle) != OSSL_SDR_OK) + goto end; + + if (TSAPI_SDF_OpenSession(hDeviceHandle, &hSessionHandle) != OSSL_SDR_OK) + goto end; + + if (SDFE_LoginUsr(hSessionHandle, &login_arg) != OSSL_SDR_OK) + goto end; + + sym_key_evlp.flags = SDFE_SYM_KEY_EVLP_F_IMPORT_KEY_INDEX_VALID; + sym_key_evlp.asym_key_type = SDFE_ASYM_KEY_TYPE_SM2; + sym_key_evlp.sym_key_type = SDFE_SYM_KEY_TYPE_SM4; + sym_key_evlp.sym_key_len = 16; + sym_key_evlp.asym_key_index = 0; + + if (deklen > sizeof(sym_key_evlp.data)) + goto end; + sym_key_evlp.data_len = deklen; + memcpy(sym_key_evlp.data, dek, deklen); + + if (sign) + area = SDFE_ASYM_KEY_AREA_SIGN; + else + area = SDFE_ASYM_KEY_AREA_ENC; + + sm2_key.area = area; + sm2_key.index = index; + sm2_key.type = SDFE_ASYM_KEY_TYPE_SM2; + sm2_key.privkey_bits = 256; + sm2_key.privkey_len = sm2_key.privkey_bits >> 3; + sm2_key.pubkey_bits = 256; + sm2_key.pubkey_len = (sm2_key.pubkey_bits >> 3) << 1; + + if (keylen != sizeof(sm2_key.privkey) + sizeof(sm2_key.pubkey)) + goto end; + + memcpy(sm2_key.pubkey, key, sizeof(sm2_key.pubkey)); + memcpy(sm2_key.privkey, key + sizeof(sm2_key.pubkey), + sizeof(sm2_key.privkey)); + + if (SDFE_ImportECCKeyWithEvlp(hSessionHandle, &sm2_key, &sym_key_evlp, NULL) + != OSSL_SDR_OK) + goto end; + + ok = 1; +end: + TSAPI_SDF_CloseSession(hSessionHandle); + TSAPI_SDF_CloseDevice(hDeviceHandle); +#endif + return ok; +} + +int TSAPI_ExportSM2KeyWithEvlp(int index, int sign, const char *user, + const char *password, EVP_PKEY *sm2_pkey, + unsigned char **priv, size_t *privlen, + unsigned char **pub, size_t *publen, + unsigned char **outevlp, size_t *outevlplen) + +{ + int ok = 0; +#ifdef SDF_LIB + int area; + void *hDeviceHandle = NULL; + void *hSessionHandle = NULL; + OSSL_ECCrefPublicKey *pubkey = NULL; + sdfe_asym_key_ecc_t sm2_key; + sdfe_sym_key_evlp_t sym_key_evlp; + sdfe_login_arg_t login_arg; + + if (sign) + area = SDFE_ASYM_KEY_AREA_SIGN; + else + area = SDFE_ASYM_KEY_AREA_ENC; + + memset(&login_arg, 0, sizeof(login_arg)); + memset(&sm2_key, 0, sizeof(sm2_key)); + memset(&sym_key_evlp, 0, sizeof(sym_key_evlp)); + + login_arg.passwd = (uint8_t *)password; + if (password) + login_arg.passwd_len = strlen(password); + else + login_arg.passwd_len = 0; + + if (user) { + if (strlen(user) >= sizeof(login_arg.name)) + return 0; + + strcpy((char *)login_arg.name, user); + } + + if (TSAPI_SDF_OpenDevice(&hDeviceHandle) != OSSL_SDR_OK) + goto end; + + if (TSAPI_SDF_OpenSession(hDeviceHandle, &hSessionHandle) != OSSL_SDR_OK) + goto end; + + if (SDFE_LoginUsr(hSessionHandle, &login_arg) != OSSL_SDR_OK) + goto end; + + sm2_key.area = area; + sm2_key.index = index; + sm2_key.type = SDFE_ASYM_KEY_TYPE_SM2; + + sym_key_evlp.asym_key_type = SDFE_ASYM_KEY_TYPE_SM2; + sym_key_evlp.sym_key_type = SDFE_SYM_KEY_TYPE_SM4; + sym_key_evlp.sym_key_len = 16; + + pubkey = TSAPI_EVP_PKEY_get_ECCrefPublicKey(sm2_pkey); + if (pubkey == NULL) + goto end; + + if (SDFE_ExportECCKeyWithEvlp(hSessionHandle, &sm2_key, &sym_key_evlp, + (void *)pubkey) != OSSL_SDR_OK) + goto end; + + *outevlp = OPENSSL_malloc(sym_key_evlp.data_len); + if (*outevlp == NULL) + goto end; + + memcpy(*outevlp, sym_key_evlp.data, sym_key_evlp.data_len); + *outevlplen = sym_key_evlp.data_len; + + *priv = OPENSSL_malloc(sizeof(sm2_key.privkey)); + if (*priv == NULL) + goto end; + + memcpy(*priv, sm2_key.privkey, sizeof(sm2_key.privkey)); + *privlen = sizeof(sm2_key.privkey); + + *pub = OPENSSL_malloc(sizeof(sm2_key.pubkey)); + if (*pub == NULL) + goto end; + + memcpy(*pub, sm2_key.pubkey, sizeof(sm2_key.pubkey)); + *publen = sizeof(sm2_key.pubkey); + + ok = 1; +end: + if (!ok) { + OPENSSL_free(*priv); + OPENSSL_free(*pub); + OPENSSL_free(*outevlp); + *priv = NULL; + *pub = NULL; + *outevlp = NULL; + *privlen = 0; + *publen = 0; + *outevlplen = 0; + } + + OPENSSL_free(pubkey); + TSAPI_SDF_CloseSession(hSessionHandle); + TSAPI_SDF_CloseDevice(hDeviceHandle); +#endif + return ok; +} + +EVP_PKEY *TSAPI_ExportSM2KeyWithIndex(int index, int sign, const char *user, + const char *password) +{ + EVP_PKEY *pkey = NULL; +#ifdef SDF_LIB + void *hDeviceHandle = NULL; + void *hSessionHandle = NULL; + sdfe_login_arg_t login_arg; + int area; + OSSL_ECCrefPrivateKey privkey; + OSSL_ECCrefPublicKey pubkey; + + if (sign) + area = SDFE_ASYM_KEY_AREA_SIGN; + else + area = SDFE_ASYM_KEY_AREA_ENC; + + memset(&login_arg, 0, sizeof(login_arg)); + + if (user) { + if (strlen(user) >= sizeof(login_arg.name)) + return 0; + + strcpy((char *)login_arg.name, user); + } + + login_arg.passwd = (uint8_t *)password; + if (password) + login_arg.passwd_len = strlen(password); + else + login_arg.passwd_len = 0; + + if (TSAPI_SDF_OpenDevice(&hDeviceHandle) != OSSL_SDR_OK) + goto end; + + if (TSAPI_SDF_OpenSession(hDeviceHandle, &hSessionHandle) != OSSL_SDR_OK) + goto end; + + if (SDFE_LoginUsr(hSessionHandle, &login_arg) != OSSL_SDR_OK) + goto end; + + if (SDFE_ExportECCPrivKey(hSessionHandle, area, index, 0, NULL, + (ECCrefPrivateKey *)&privkey) != OSSL_SDR_OK) + goto end; + + if (sign && TSAPI_SDF_ExportSignPublicKey_ECC(hSessionHandle, index, + &pubkey) != OSSL_SDR_OK) + goto end; + + if (!sign && TSAPI_SDF_ExportEncPublicKey_ECC(hSessionHandle, index, + &pubkey) != OSSL_SDR_OK) + goto end; + + pkey = TSAPI_EVP_PKEY_new_from_ECCrefKey(&pubkey, &privkey); + if (pkey == NULL) + goto end; +end: + TSAPI_SDF_CloseSession(hSessionHandle); + TSAPI_SDF_CloseDevice(hDeviceHandle); +#endif + return pkey; +} + +EVP_PKEY *TSAPI_ExportSM2PubKeyWithIndex(int index, int sign) +{ + EVP_PKEY *pkey = NULL; +#ifdef SDF_LIB + void *hDeviceHandle = NULL; + void *hSessionHandle = NULL; + OSSL_ECCrefPublicKey pubkey; + EC_GROUP *group = NULL; + EC_KEY *eckey = NULL; + BIGNUM *x = NULL, *y = NULL; + int nbytes; + + if (TSAPI_SDF_OpenDevice(&hDeviceHandle) != OSSL_SDR_OK) + goto end; + + if (TSAPI_SDF_OpenSession(hDeviceHandle, &hSessionHandle) != OSSL_SDR_OK) + goto end; + + if (sign) { + if (TSAPI_SDF_ExportSignPublicKey_ECC(hSessionHandle, index, &pubkey) + != OSSL_SDR_OK) + goto end; + } else { + if (TSAPI_SDF_ExportEncPublicKey_ECC(hSessionHandle, index, &pubkey) + != OSSL_SDR_OK) + goto end; + } + + group = EC_GROUP_new_by_curve_name(NID_sm2); + if (group == NULL) + goto end; + + eckey = EC_KEY_new(); + if (eckey == NULL) + goto end; + + EC_KEY_set_group(eckey, group); + + nbytes = (pubkey.bits + 7) / 8; + + x = BN_bin2bn(pubkey.x + sizeof(pubkey.x) - nbytes, nbytes, NULL); + if (x == NULL) + goto end; + + y = BN_bin2bn(pubkey.y + sizeof(pubkey.y) - nbytes, nbytes, NULL); + if (y == NULL) + goto end; + + if (!EC_KEY_set_public_key_affine_coordinates(eckey, x, y)) + goto end; + + pkey = EVP_PKEY_new(); + if (pkey == NULL) + goto end; + + if (!EVP_PKEY_assign_EC_KEY(pkey, eckey)) { + EVP_PKEY_free(pkey); + goto end; + } + eckey = NULL; + +end: + EC_KEY_free(eckey); + EC_GROUP_free(group); + BN_free(x); + BN_free(y); + TSAPI_SDF_CloseSession(hSessionHandle); + TSAPI_SDF_CloseDevice(hDeviceHandle); +#endif + return pkey; +} + +int TSAPI_UpdateSm2KeyWithIndex(int index, int sign, const char *user, const char *password) +{ + int ok = 0; +#ifdef SDF_LIB + void *hDeviceHandle = NULL; + void *hSessionHandle = NULL; + sdfe_login_arg_t login_arg; + int area; + + if (sign) + area = SDFE_ASYM_KEY_AREA_SIGN; + else + area = SDFE_ASYM_KEY_AREA_ENC; + + memset(&login_arg, 0, sizeof(login_arg)); + + if (user) { + if (strlen(user) >= sizeof(login_arg.name)) + return 0; + + strcpy((char *)login_arg.name, user); + } + + login_arg.passwd = (uint8_t *)password; + if (password) + login_arg.passwd_len = strlen(password); + else + login_arg.passwd_len = 0; + + if (TSAPI_SDF_OpenDevice(&hDeviceHandle) != OSSL_SDR_OK) + goto end; + + if (TSAPI_SDF_OpenSession(hDeviceHandle, &hSessionHandle) != OSSL_SDR_OK) + goto end; + + if (SDFE_LoginUsr(hSessionHandle, &login_arg) != OSSL_SDR_OK) + goto end; + + if (SDFE_DelECCKey(hSessionHandle, area, index) + != OSSL_SDR_OK) + goto end; + + if (SDFE_GenECCKey(hSessionHandle, area, index, 0, NULL) + != OSSL_SDR_OK) + goto end; + + ok = 1; +end: + TSAPI_SDF_CloseSession(hSessionHandle); + TSAPI_SDF_CloseDevice(hDeviceHandle); +#endif + return ok; +} + +EVP_PKEY *TSAPI_SM2Keygen(void) +{ + return EVP_PKEY_Q_keygen(NULL, NULL, "SM2"); +} + +# ifndef OPENSSL_NO_SM3 +int TSAPI_SM2Verify(EVP_PKEY *key, const unsigned char *tbs, size_t tbslen, + const unsigned char *sig, size_t siglen) +{ + int ok = 0; + EVP_MD_CTX *ctx = NULL; + + if (key == NULL || tbs == NULL || sig == NULL) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + ctx = EVP_MD_CTX_new(); + if (ctx == NULL) + return 0; + + if (!EVP_DigestVerifyInit(ctx, NULL, EVP_sm3(), NULL, key) + || EVP_DigestVerify(ctx, sig, siglen, tbs, tbslen) <= 0) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_EVP_LIB); + goto end; + } + + ok = 1; +end: + EVP_MD_CTX_free(ctx); + return ok; +} + +unsigned char *TSAPI_SM2Sign(EVP_PKEY *key, const unsigned char *tbs, + size_t tbslen, size_t *siglen) +{ + unsigned char *sig = NULL; + size_t len; + EVP_MD_CTX *ctx = NULL; + + if (key == NULL || tbs == NULL || siglen == NULL) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + ctx = EVP_MD_CTX_new(); + if (ctx == NULL) + return NULL; + + if (!EVP_DigestSignInit(ctx, NULL, EVP_sm3(), NULL, key) + || !EVP_DigestSign(ctx, NULL, &len, tbs, tbslen)) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_EVP_LIB); + goto end; + } + + sig = OPENSSL_malloc(len); + if (sig == NULL) + goto end; + + if (!EVP_DigestSign(ctx, sig, &len, tbs, tbslen)) { + OPENSSL_free(sig); + *siglen = 0; + ERR_raise(ERR_LIB_CRYPTO, ERR_R_EVP_LIB); + goto end; + } + + *siglen = len; +end: + EVP_MD_CTX_free(ctx); + return sig; +} +# endif + +static unsigned char *do_SM2Crypt(int enc, EVP_PKEY *key, + const unsigned char *in, size_t inlen, + size_t *outlen) +{ + EVP_PKEY_CTX *ctx = NULL; + size_t len = 0; + unsigned char *out = NULL; + + if (key == NULL || in == NULL || outlen == NULL) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + if (enc) { + ctx = EVP_PKEY_CTX_new_from_pkey_provided(NULL, key, NULL); + } else { + ctx = EVP_PKEY_CTX_new(key, NULL); + } + + if (ctx == NULL) + return NULL; + + if (enc) { + if (EVP_PKEY_encrypt_init(ctx) <= 0 + || EVP_PKEY_encrypt(ctx, NULL, &len, in, inlen) <= 0) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_EVP_LIB); + goto end; + } + } else { + if (EVP_PKEY_decrypt_init(ctx) <= 0 + || EVP_PKEY_decrypt(ctx, NULL, &len, in, inlen) <= 0) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_EVP_LIB); + goto end; + } + } + + out = OPENSSL_malloc(len); + if (out == NULL) + goto end; + + if (enc) { + if (EVP_PKEY_encrypt(ctx, out, &len, in, inlen) <= 0) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_EVP_LIB); + OPENSSL_free(out); + out = NULL; + len = 0; + } + } else { + if (EVP_PKEY_decrypt(ctx, out, &len, in, inlen) <= 0) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_EVP_LIB); + OPENSSL_free(out); + out = NULL; + len = 0; + } + } + + *outlen = len; +end: + EVP_PKEY_CTX_free(ctx); + return out; +} + +unsigned char *TSAPI_SM2DecryptWithISK(int isk, const unsigned char *in, + size_t inlen, size_t *outlen) +{ + unsigned char *out = NULL; +#ifdef SDF_LIB + void *hDeviceHandle = NULL; + void *hSessionHandle = NULL; + OSSL_ECCCipher *ecc = NULL; + unsigned int len; + + if (TSAPI_SDF_OpenDevice(&hDeviceHandle) != OSSL_SDR_OK) + return NULL; + + if (TSAPI_SDF_OpenSession(hDeviceHandle, &hSessionHandle) != OSSL_SDR_OK) + goto end; + + if (TSAPI_SDF_GetPrivateKeyAccessRight(hSessionHandle, isk, NULL, 0) + != OSSL_SDR_OK) + goto end; + + ecc = TSAPI_SM2Ciphertext_to_ECCCipher(in, inlen); + if (ecc == NULL) + goto end; + + len = ecc->L; + out = OPENSSL_malloc(len); + if (out == NULL) + goto end; + + if (TSAPI_SDF_InternalDecrypt_ECC(hSessionHandle, isk, ecc, out, &len) + != OSSL_SDR_OK) { + OPENSSL_free(out); + out = NULL; + *outlen = 0; + goto end; + } + + *outlen = len; +end: + OPENSSL_free(ecc); + TSAPI_SDF_ReleasePrivateKeyAccessRight(hSessionHandle, isk); + TSAPI_SDF_CloseSession(hSessionHandle); + TSAPI_SDF_CloseDevice(hDeviceHandle); +#endif + return out; +} + +unsigned char *TSAPI_SM2EncryptWithISK(int isk, const unsigned char *in, + size_t inlen, size_t *outlen) +{ + unsigned char *out = NULL; +#ifdef SDF_LIB + void *hDeviceHandle = NULL; + void *hSessionHandle = NULL; + OSSL_ECCCipher *ecc = NULL; + + if (TSAPI_SDF_OpenDevice(&hDeviceHandle) != OSSL_SDR_OK) + return NULL; + + if (TSAPI_SDF_OpenSession(hDeviceHandle, &hSessionHandle) != OSSL_SDR_OK) + goto end; + + ecc = OPENSSL_zalloc(sizeof(OSSL_ECCCipher) + inlen); + if (ecc == NULL) + goto end; + + if (TSAPI_SDF_InternalEncrypt_ECC(hSessionHandle, isk, (unsigned char *)in, + inlen, ecc) + != OSSL_SDR_OK) + goto end; + + out = TSAPI_ECCCipher_to_SM2Ciphertext(ecc, outlen); + +end: + OPENSSL_free(ecc); + TSAPI_SDF_CloseSession(hSessionHandle); + TSAPI_SDF_CloseDevice(hDeviceHandle); +#endif + return out; +} + +unsigned char *TSAPI_SM2Encrypt(EVP_PKEY *key, const unsigned char *in, + size_t inlen, size_t *outlen) +{ + return do_SM2Crypt(1, key, in, inlen, outlen); +} + +unsigned char *TSAPI_SM2Decrypt(EVP_PKEY *key, const unsigned char *in, + size_t inlen, size_t *outlen) +{ + return do_SM2Crypt(0, key, in, inlen, outlen); +} + +unsigned char *TSAPI_ECCCipher_to_SM2Ciphertext(const OSSL_ECCCipher *ecc, + size_t *ciphertext_len) +{ + BIGNUM *x = NULL, *y = NULL; + unsigned char *out = NULL; + + if (ecc == NULL) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + if ((x = BN_bin2bn(ecc->x, sizeof(ecc->x), NULL)) == NULL + || (y = BN_bin2bn(ecc->y, sizeof(ecc->y), NULL)) == NULL) + goto end; + + out = ossl_sm2_ciphertext_encode(x, y, ecc->C, ecc->L, ecc->M, + sizeof(ecc->M), ciphertext_len); +end: + BN_free(x); + BN_free(y); + return out; + +} + +OSSL_ECCCipher *TSAPI_SM2Ciphertext_to_ECCCipher(const unsigned char *ciphertext, + size_t ciphertext_len) +{ + int ok = 0; + EC_POINT *C1 = NULL; + uint8_t *C2_data = NULL, *C3_data = NULL; + size_t C2_len, C3_len; + EC_GROUP *group = NULL; + BN_CTX *ctx = NULL; + BIGNUM *Cx = NULL, *Cy = NULL; + OSSL_ECCCipher *ecc = NULL; + + if (ciphertext == NULL) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + if (!ossl_sm2_ciphertext_decode(ciphertext, ciphertext_len, &C1, &C2_data, + &C2_len, &C3_data, &C3_len)) + goto end; + + ecc = OPENSSL_zalloc(sizeof(OSSL_ECCCipher) + C2_len); + if (ecc == NULL) + goto end; + + if (C3_len != sizeof(ecc->M)) + goto end; + + memcpy(ecc->M, C3_data, C3_len); + ecc->L = C2_len; + memcpy(ecc->C, C2_data, C2_len); + + group = EC_GROUP_new_by_curve_name(NID_sm2); + if (group == NULL) + goto end; + + ctx = BN_CTX_new(); + if (ctx == NULL) + goto end; + + BN_CTX_start(ctx); + Cx = BN_CTX_get(ctx); + Cy = BN_CTX_get(ctx); + if (Cy == NULL) + goto end; + + if (!EC_POINT_get_affine_coordinates(group, C1, Cx, Cy, NULL)) + goto end; + + if (BN_bn2bin(Cx, ecc->x + sizeof(ecc->x) - BN_num_bytes(Cx)) + != BN_num_bytes(Cx) + || BN_bn2bin(Cy, ecc->y + sizeof(ecc->y) - BN_num_bytes(Cy)) + != BN_num_bytes(Cy)) + goto end; + + ok = 1; +end: + if (!ok) { + OPENSSL_free(ecc); + ecc = NULL; + } + BN_CTX_end(ctx); + BN_CTX_free(ctx); + EC_POINT_free(C1); + OPENSSL_free(C2_data); + OPENSSL_free(C3_data); + return ecc; + +} +#endif + +#ifndef OPENSSL_NO_SM4 +static unsigned char *do_SM4Crypt(int mode, int enc, + const unsigned char *key, + size_t keylen, int isk, + const unsigned char *iv, + const unsigned char *in, size_t inlen, + size_t *outlen) +{ +# ifdef SDF_LIB + void *hDeviceHandle = NULL; + void *hSessionHandle = NULL; + void *hkeyHandle = NULL; + OSSL_ECCCipher *ecc = NULL; +# endif + const EVP_CIPHER *cipher = NULL; + EVP_CIPHER_CTX *ctx = NULL; + unsigned char *outbuf = NULL; + unsigned int len = 0; + int lenf = 0; + size_t max_out_len; + + if (isk < 0) { + ctx = EVP_CIPHER_CTX_new(); + if (ctx == NULL) + return 0; + + if (mode == OSSL_SGD_MODE_ECB) + cipher = EVP_sm4_ecb(); + else if (mode == OSSL_SGD_MODE_CBC) + cipher = EVP_sm4_cbc(); + else if (mode == OSSL_SGD_MODE_CFB) + cipher = EVP_sm4_cfb(); + else if (mode == OSSL_SGD_MODE_OFB) + cipher = EVP_sm4_ofb(); + else if (mode == OSSL_SGD_MODE_CTR) + cipher = EVP_sm4_ctr(); + else + goto end; + + if (!EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, enc) + || !EVP_CIPHER_CTX_set_padding(ctx, 0)) + goto end; + + max_out_len = inlen + EVP_CIPHER_CTX_get_block_size(ctx); + + outbuf = OPENSSL_malloc(max_out_len); + if (outbuf == NULL) + goto end; + + if (!EVP_CipherUpdate(ctx, outbuf, (int *)&len, in, inlen)) { + OPENSSL_free(outbuf); + outbuf = NULL; + len = 0; + goto end; + } + + if (!EVP_CipherFinal_ex(ctx, outbuf + len, &lenf)) { + OPENSSL_free(outbuf); + outbuf = NULL; + len = 0; + goto end; + } + + len += lenf; + } +# ifdef SDF_LIB + else { + + if (TSAPI_SDF_OpenDevice(&hDeviceHandle) != OSSL_SDR_OK) + goto end; + + if (TSAPI_SDF_OpenSession(hDeviceHandle, &hSessionHandle) != OSSL_SDR_OK) + goto end; + + if (TSAPI_SDF_GetPrivateKeyAccessRight(hSessionHandle, isk, NULL, 0) + != OSSL_SDR_OK) + goto end; + + ecc = TSAPI_SM2Ciphertext_to_ECCCipher(key, keylen); + if (ecc == NULL) + goto end; + + if (TSAPI_SDF_ImportKeyWithISK_ECC(hSessionHandle, isk, ecc, &hkeyHandle) + != OSSL_SDR_OK) + goto end; + + outbuf = (unsigned char *)OPENSSL_malloc(inlen) + 128; + if (outbuf == NULL) + goto end; + + if (enc) { + if (TSAPI_SDF_Encrypt(hSessionHandle, hkeyHandle, + OSSL_SGD_SM4 | mode, + (unsigned char *)iv, (unsigned char *)in, + inlen, outbuf, &len) != OSSL_SDR_OK) { + OPENSSL_free(outbuf); + outbuf = NULL; + goto end; + } + } else { + if (TSAPI_SDF_Decrypt(hSessionHandle, hkeyHandle, + OSSL_SGD_SM4 | mode, + (unsigned char *)iv, (unsigned char *)in, + inlen, outbuf, &len) != OSSL_SDR_OK) { + OPENSSL_free(outbuf); + outbuf = NULL; + goto end; + } + } + } +# endif + *outlen = len; +end: + EVP_CIPHER_CTX_free(ctx); +# ifdef SDF_LIB + if (isk >= 0) { + TSAPI_SDF_DestroyKey(hSessionHandle, hkeyHandle); + TSAPI_SDF_ReleasePrivateKeyAccessRight(hSessionHandle, isk); + OPENSSL_free(ecc); + TSAPI_SDF_CloseSession(hSessionHandle); + TSAPI_SDF_CloseDevice(hDeviceHandle); + } +# endif + return outbuf; +} + +unsigned char *TSAPI_SM4Decrypt(int mode, const unsigned char *key, + size_t keylen, int isk, + const unsigned char *iv, + const unsigned char *in, size_t inlen, + size_t *outlen) +{ + return do_SM4Crypt(mode, 0, key, keylen, isk, iv, in, inlen, outlen); +} + +unsigned char *TSAPI_SM4Encrypt(int mode, const unsigned char *key, + size_t keylen, int isk, + const unsigned char *iv, + const unsigned char *in, size_t inlen, + size_t *outlen) +{ + return do_SM4Crypt(mode, 1, key, keylen, isk, iv, in, inlen, outlen); +} +#endif + +#ifndef OPENSSL_NO_SM3 +unsigned char *TSAPI_SM3(const void *data, size_t datalen, size_t *outlen) +{ + EVP_MD_CTX *ctx = NULL; + unsigned char *out = NULL; + unsigned int len = 0; + + if (data == NULL || outlen == NULL) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + ctx = EVP_MD_CTX_new(); + if (ctx == NULL) + return NULL; + + if (!EVP_DigestInit_ex(ctx, EVP_sm3(), NULL) + || !EVP_DigestUpdate(ctx, data, datalen)) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_EVP_LIB); + goto end; + } + + out = OPENSSL_malloc(EVP_MD_CTX_get_size(ctx)); + if (out == NULL) + goto end; + + if (!EVP_DigestFinal_ex(ctx, out, &len)) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_EVP_LIB); + OPENSSL_free(out); + out = NULL; + len = 0; + } + + *outlen = len; +end: + EVP_MD_CTX_free(ctx); + return out; +} +#endif 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/crypto/sm2.h b/include/crypto/sm2.h index 108d821fb..22c9f7da8 100644 --- a/include/crypto/sm2.h +++ b/include/crypto/sm2.h @@ -79,6 +79,11 @@ int ossl_sm2_decrypt(const EC_KEY *key, const uint8_t *ciphertext, size_t ciphertext_len, uint8_t *ptext_buf, size_t *ptext_len); +unsigned char *ossl_sm2_ciphertext_encode(const BIGNUM *C1x, const BIGNUM *C1y, + const uint8_t *C2_data, size_t C2_len, + const uint8_t *C3_data, size_t C3_len, + size_t *ciphertext_len); + int ossl_sm2_ciphertext_decode(const uint8_t *ciphertext, size_t ciphertext_len, EC_POINT **C1p, uint8_t **C2p, size_t *C2_len, uint8_t **C3p, size_t *C3_len); diff --git a/include/internal/cryptlib.h b/include/internal/cryptlib.h index bfd035781..be81384db 100644 --- a/include/internal/cryptlib.h +++ b/include/internal/cryptlib.h @@ -70,6 +70,11 @@ 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" +# define SMTC_AUTH_KEK OPENSSLDIR "/auth_kek.pem" +# 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/provider.h b/include/internal/provider.h index d09829d05..585bbbf34 100644 --- a/include/internal/provider.h +++ b/include/internal/provider.h @@ -87,6 +87,8 @@ int ossl_provider_get_capabilities(const OSSL_PROVIDER *prov, const char *capability, OSSL_CALLBACK *cb, void *arg); +int ossl_provider_reset(OSSL_PROVIDER *prov); +int ossl_provider_status(const OSSL_PROVIDER *prov); int ossl_provider_self_test(const OSSL_PROVIDER *prov); const OSSL_ALGORITHM *ossl_provider_query_operation(const OSSL_PROVIDER *prov, int operation_id, diff --git a/include/internal/sdf.h b/include/internal/sdf.h new file mode 100644 index 000000000..028f211e3 --- /dev/null +++ b/include/internal/sdf.h @@ -0,0 +1,16 @@ +/* + * 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 OSSL_INTERNAL_SDF_H +# define OSSL_INTERNAL_SDF_H +# pragma once + +void ossl_sdf_lib_cleanup(void); + +#endif diff --git a/include/internal/smtc_names.h b/include/internal/smtc_names.h index fe67aae5c..0f934fd6e 100644 --- a/include/internal/smtc_names.h +++ b/include/internal/smtc_names.h @@ -1,5 +1,5 @@ /* - * Copyright 2022 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 @@ -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_SYSLOG "syslog" +# 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..357dc2399 100644 --- a/include/openssl/core_dispatch.h +++ b/include/openssl/core_dispatch.h @@ -249,6 +249,12 @@ 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_STATUS 1032 +OSSL_CORE_MAKE_FUNC(int, provider_status, (void *provctx)) + +# define OSSL_FUNC_PROVIDER_RESET 1033 +OSSL_CORE_MAKE_FUNC(int, provider_reset, (void *provctx)) + /* Operations */ # define OSSL_OP_DIGEST 1 diff --git a/include/openssl/crypto.h.in b/include/openssl/crypto.h.in index 47d91aedb..116f32ac4 100644 --- a/include/openssl/crypto.h.in +++ b/include/openssl/crypto.h.in @@ -53,10 +53,31 @@ use OpenSSL::stackhash qw(generate_stack_macros); # include # endif +#if defined(OPENSSL_SYS_WINCE) +#elif defined(OPENSSL_SYS_WIN32) +#elif (!defined(MSDOS) || defined(WATT32)) && !defined(OPENSSL_SYS_VXWORKS) && !defined(NO_SYSLOG) +# include +#endif + #ifdef __cplusplus extern "C" { #endif +# ifndef NO_SYSLOG +# if defined(OPENSSL_SYS_WIN32) +# define LOG_EMERG 0 +# define LOG_ALERT 1 +# define LOG_CRIT 2 +# define LOG_ERR 3 +# define LOG_WARNING 4 +# define LOG_NOTICE 5 +# define LOG_INFO 6 +# define LOG_DEBUG 7 + +# define LOG_DAEMON (3<<3) +# endif +# endif + # ifndef OPENSSL_NO_DEPRECATED_1_1_0 # define SSLeay OpenSSL_version_num # define SSLeay_version OpenSSL_version @@ -184,6 +205,8 @@ const char *OPENSSL_info(int type); # define OPENSSL_INFO_LIST_SEPARATOR 1006 # define OPENSSL_INFO_SEED_SOURCE 1007 # define OPENSSL_INFO_CPU_SETTINGS 1008 +# define OPENSSL_INFO_SMTC_MODULE_CONF 1009 +# define OPENSSL_INFO_SMTC_AUTH_KEK 1010 int OPENSSL_issetugid(void); @@ -542,6 +565,10 @@ void OSSL_LIB_CTX_free(OSSL_LIB_CTX *); OSSL_LIB_CTX *OSSL_LIB_CTX_get0_global_default(void); OSSL_LIB_CTX *OSSL_LIB_CTX_set0_default(OSSL_LIB_CTX *libctx); +void OSSL_enable_syslog(void); +void OSSL_disable_syslog(void); +void OSSL_syslog(int priority, const char *message, ...); + # ifdef __cplusplus } # endif diff --git a/include/openssl/evp.h b/include/openssl/evp.h index efa47dfc6..ec26e09af 100644 --- a/include/openssl/evp.h +++ b/include/openssl/evp.h @@ -1681,8 +1681,14 @@ EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e); EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_name(OSSL_LIB_CTX *libctx, const char *name, const char *propquery); +EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_name_provided(OSSL_LIB_CTX *libctx, + const char *name, + const char *propquery); EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_pkey(OSSL_LIB_CTX *libctx, EVP_PKEY *pkey, const char *propquery); +EVP_PKEY_CTX *EVP_PKEY_CTX_new_from_pkey_provided(OSSL_LIB_CTX *libctx, + EVP_PKEY *pkey, + const char *propquery); EVP_PKEY_CTX *EVP_PKEY_CTX_dup(const EVP_PKEY_CTX *ctx); void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx); int EVP_PKEY_CTX_is_a(EVP_PKEY_CTX *ctx, const char *keytype); diff --git a/include/openssl/opensslv.h.in b/include/openssl/opensslv.h.in index dfc4e45b7..8c3d996d7 100644 --- a/include/openssl/opensslv.h.in +++ b/include/openssl/opensslv.h.in @@ -126,7 +126,7 @@ extern "C" { # define BABASSL_VERSION_NUMBER TONGSUO_VERSION_NUMBER # define BABASSL_VERSION_TEXT TONGSUO_VERSION_TEXT -# define TONGSUO_SMTC_INFO_STR "{- $config{TONGSUO_SMTC_INFO} -}" +# define TONGSUO_SMTC_INFO_STR "{- $config{tongsuo_smtc_info} -}" # ifdef __cplusplus } 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/provider.h b/include/openssl/provider.h index dc86ff587..32cdf7838 100644 --- a/include/openssl/provider.h +++ b/include/openssl/provider.h @@ -32,6 +32,8 @@ int OSSL_PROVIDER_do_all(OSSL_LIB_CTX *ctx, const OSSL_PARAM *OSSL_PROVIDER_gettable_params(const OSSL_PROVIDER *prov); int OSSL_PROVIDER_get_params(const OSSL_PROVIDER *prov, OSSL_PARAM params[]); +int OSSL_PROVIDER_reset(OSSL_PROVIDER *prov); +int OSSL_PROVIDER_status(const OSSL_PROVIDER *prov); int OSSL_PROVIDER_self_test(const OSSL_PROVIDER *prov); int OSSL_PROVIDER_get_capabilities(const OSSL_PROVIDER *prov, const char *capability, 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/sdf.h b/include/openssl/sdf.h new file mode 100644 index 000000000..5d07bc2a4 --- /dev/null +++ b/include/openssl/sdf.h @@ -0,0 +1,118 @@ +/* + * 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 OPENSSL_SDF_H +# define OPENSSL_SDF_H +# pragma once + +# include +# include + +# ifdef __cplusplus +extern "C" { +# endif + +/* SDF error codes from GM/T 0018-2012 Appendix A */ +# define OSSL_SDR_OK 0 +# define OSSL_SDR_BASE 0x01000000 +# define OSSL_SDR_UNKNOWNERR (OSSL_SDR_BASE + 1) +# define OSSL_SDR_NOTSUPPORT (OSSL_SDR_BASE + 2) +# define OSSL_SDR_COMMFAIL (OSSL_SDR_BASE + 3) +# define OSSL_SDR_HARDFAIL (OSSL_SDR_BASE + 4) +# define OSSL_SDR_OPENDEVICE (OSSL_SDR_BASE + 5) +# define OSSL_SDR_OPENSESSION (OSSL_SDR_BASE + 6) +# define OSSL_SDR_PARDENY (OSSL_SDR_BASE + 7) +# define OSSL_SDR_KEYNOTEXIST (OSSL_SDR_BASE + 8) +# define OSSL_SDR_ALGNOTSUPPORT (OSSL_SDR_BASE + 9) +# define OSSL_SDR_ALGMODNOTSUPPORT (OSSL_SDR_BASE + 10) +# define OSSL_SDR_PKOPERR (OSSL_SDR_BASE + 11) +# define OSSL_SDR_SKOPERR (OSSL_SDR_BASE + 12) +# define OSSL_SDR_SIGNERR (OSSL_SDR_BASE + 13) +# define OSSL_SDR_VERIFYERR (OSSL_SDR_BASE + 14) +# define OSSL_SDR_SYMOPERR (OSSL_SDR_BASE + 15) +# define OSSL_SDR_STEPERR (OSSL_SDR_BASE + 16) +# define OSSL_SDR_FILESIZEERR (OSSL_SDR_BASE + 17) +# define OSSL_SDR_FILENOTEXIST (OSSL_SDR_BASE + 18) +# define OSSL_SDR_FILEOFSERR (OSSL_SDR_BASE + 19) +# define OSSL_SDR_KEYTYPEERR (OSSL_SDR_BASE + 20) +# define OSSL_SDR_KEYERR (OSSL_SDR_BASE + 21) +# define OSSL_SDR_ENCDATAERR (OSSL_SDR_BASE + 22) +# define OSSL_SDR_RANDERR (OSSL_SDR_BASE + 23) +# define OSSL_SDR_PRKRERR (OSSL_SDR_BASE + 24) +# define OSSL_SDR_MACERR (OSSL_SDR_BASE + 25) +# define OSSL_SDR_FILEEXISTS (OSSL_SDR_BASE + 26) +# define OSSL_SDR_FILEWERR (OSSL_SDR_BASE + 27) +# define OSSL_SDR_NOBUFFER (OSSL_SDR_BASE + 28) +# define OSSL_SDR_INARGERR (OSSL_SDR_BASE + 29) +# define OSSL_SDR_OUTARGERR (OSSL_SDR_BASE + 30) + +#define OSSL_SDFE_ASYM_KEY_TYPE_SM2 (0xa0) +#define OSSL_SDFE_SYM_KEY_TYPE_SM4 (0xb0) + +typedef struct OSSL_ECCCipher_st OSSL_ECCCipher; +typedef struct OSSL_ECCSignature_st OSSL_ECCSignature; +typedef struct OSSL_ECCrefPrivateKey_st OSSL_ECCrefPrivateKey; +typedef struct OSSL_ECCrefPublicKey_st OSSL_ECCrefPublicKey; +int TSAPI_SDF_OpenDevice(void **phDeviceHandle); +int TSAPI_SDF_CloseDevice(void *hDeviceHandle); +int TSAPI_SDF_OpenSession(void *hDeviceHandle, void **phSessionHandle); +int TSAPI_SDF_CloseSession(void *hSessionHandle); +int TSAPI_SDF_GenerateRandom(void *hSessionHandle, unsigned int uiLength, + unsigned char *pucRandom); +int TSAPI_SDF_GetPrivateKeyAccessRight(void *hSessionHandle, + unsigned int uiKeyIndex, + unsigned char *pucPassword, + unsigned int uiPwdLength); +int TSAPI_SDF_ReleasePrivateKeyAccessRight(void *hSessionHandle, + unsigned int uiKeyIndex); +int TSAPI_SDF_ImportKeyWithISK_ECC(void *hSessionHandle, + unsigned int uiISKIndex, + OSSL_ECCCipher *pucKey, + void **phKeyHandle); +int TSAPI_SDF_ImportKeyWithKEK(void *hSessionHandle, unsigned int uiAlgID, + unsigned int uiKEKIndex, unsigned char *pucKey, unsigned int puiKeyLength, + void **phKeyHandle); +int TSAPI_SDF_ExportSignPublicKey_ECC(void *hSessionHandle, + unsigned int uiKeyIndex, + OSSL_ECCrefPublicKey *pucPublicKey); +int TSAPI_SDF_ExportEncPublicKey_ECC(void *hSessionHandle, + unsigned int uiKeyIndex, + OSSL_ECCrefPublicKey *pucPublicKey); +int TSAPI_SDF_DestroyKey(void *hSessionHandle, void *hKeyHandle); +int TSAPI_SDF_InternalEncrypt_ECC(void *hSessionHandle, unsigned int uiISKIndex, + unsigned char *pucData, + unsigned int uiDataLength, + OSSL_ECCCipher *pucEncData); +int TSAPI_SDF_InternalDecrypt_ECC(void *hSessionHandle, unsigned int uiISKIndex, + OSSL_ECCCipher *pucEncData, + unsigned char *pucData, + unsigned int *puiDataLength); +int TSAPI_SDF_Encrypt(void *hSessionHandle, void *hKeyHandle, + unsigned int uiAlgID, unsigned char *pucIV, unsigned char *pucData, + unsigned int uiDataLength, unsigned char *pucEncData, + unsigned int *puiEncDataLength); +int TSAPI_SDF_Decrypt(void *hSessionHandle, void *hKeyHandle, + unsigned int uiAlgID, unsigned char *pucIV, unsigned char *pucEncData, + unsigned int uiEncDataLength, unsigned char *pucData, + unsigned int *puiDataLength); +int TSAPI_SDF_CalculateMAC(void *hSessionHandle, void *hKeyHandle, + unsigned int uiAlgID, unsigned char *pucIV, unsigned char *pucData, + unsigned int uiDataLength, unsigned char *pucMac, + unsigned int *puiMACLength); +int TSAPI_SDF_GenerateKey(void *hSessionHandle, uint8_t type, uint8_t no_kek, + uint32_t len, void **pkey_handle); +int TSAPI_SDF_InternalSign_ECC(void *hSessionHandle, unsigned int uiISKIndex, + unsigned char *pucData, + unsigned int uiDataLength, + OSSL_ECCSignature *pucSignature); + +# ifdef __cplusplus +} +# endif +#endif /* OPENSSL_SDF_H */ diff --git a/include/openssl/self_test.h b/include/openssl/self_test.h index 357e1a9d2..1ffdf5e8d 100644 --- a/include/openssl/self_test.h +++ b/include/openssl/self_test.h @@ -32,6 +32,7 @@ extern "C" { # define OSSL_SELF_TEST_TYPE_PCT "Conditional_PCT" # define OSSL_SELF_TEST_TYPE_KAT_CIPHER "KAT_Cipher" # define OSSL_SELF_TEST_TYPE_KAT_ASYM_CIPHER "KAT_AsymmetricCipher" +# define OSSL_SELF_TEST_TYPE_PCT_ASYM_CIPHER "PCT_AsymmetricCipher" # define OSSL_SELF_TEST_TYPE_KAT_DIGEST "KAT_Digest" # define OSSL_SELF_TEST_TYPE_KAT_SIGNATURE "KAT_Signature" # define OSSL_SELF_TEST_TYPE_PCT_SIGNATURE "PCT_Signature" @@ -42,6 +43,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 +58,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/sgd.h b/include/openssl/sgd.h new file mode 100644 index 000000000..e79267ff4 --- /dev/null +++ b/include/openssl/sgd.h @@ -0,0 +1,53 @@ +/* + * 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 OPENSSL_SGD_H +# define OPENSSL_SGD_H +# pragma once + +# include +# ifndef OPENSSL_NO_DEPRECATED_3_0 +# define HEADER_SGD_H +# endif + +# ifdef __cplusplus +extern "C" { +# endif + +/* Defined in GM/T 0006-2012 */ +# define OSSL_SGD_MODE_ECB 0x00000001 +# define OSSL_SGD_MODE_CBC 0x00000002 +# define OSSL_SGD_MODE_CFB 0x00000004 +# define OSSL_SGD_MODE_OFB 0x00000008 +# define OSSL_SGD_MODE_MAC 0x00000010 +# define OSSL_SGD_MODE_CTR 0x00000020 +# define OSSL_SGD_MODE_XTS 0x00000040 + +# define OSSL_SGD_SM4 0x00000400 +# define OSSL_SGD_SM4_ECB (OSSL_SGD_SM4 | OSSL_SGD_MODE_ECB) +# define OSSL_SGD_SM4_CBC (OSSL_SGD_SM4 | OSSL_SGD_MODE_CBC) +# define OSSL_SGD_SM4_CFB (OSSL_SGD_SM4 | OSSL_SGD_MODE_CFB) +# define OSSL_SGD_SM4_OFB (OSSL_SGD_SM4 | OSSL_SGD_MODE_OFB) +# define OSSL_SGD_SM4_MAC (OSSL_SGD_SM4 | OSSL_SGD_MODE_MAC) + +# define OSSL_SGD_RSA 0x00010000 +# define OSSL_SGD_SM2 0x00020100 +# define OSSL_SGD_SM2_1 0x00020200 +# define OSSL_SGD_SM2_2 0x00020400 +# define OSSL_SGD_SM2_3 0x00020800 + +# define OSSL_SGD_SM3 0x00000001 + +# define OSSL_SGD_SM3_SM2 0x00020201 + +# ifdef __cplusplus +} +# endif + +#endif 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..7d5adff78 --- /dev/null +++ b/include/openssl/tsapi.h @@ -0,0 +1,98 @@ +/* + * 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 +# include +# include +# include + +# ifdef __cplusplus +extern "C" { +# endif + +unsigned char *TSAPI_GetEntropy(int entropy, size_t *outlen); +void TSAPI_FreeEntropy(unsigned char *ent, size_t len); +char *TSAPI_Version(void); +unsigned char *TSAPI_RandBytes(size_t len); + +# ifndef OPENSSL_NO_SM2 +EVP_PKEY *TSAPI_SM2Keygen(void); +# ifndef OPENSSL_NO_SM3 +unsigned char *TSAPI_SM2Sign(EVP_PKEY *key, const unsigned char *tbs, + size_t tbslen, size_t *siglen); +int TSAPI_SM2Verify(EVP_PKEY *key, const unsigned char *tbs, size_t tbslen, + const unsigned char *sig, size_t siglen); +# endif +unsigned char *TSAPI_SM2Encrypt(EVP_PKEY *key, const unsigned char *in, + size_t inlen, size_t *outlen); +unsigned char *TSAPI_SM2Decrypt(EVP_PKEY *key, const unsigned char *in, + size_t inlen, size_t *outlen); +unsigned char *TSAPI_SM2EncryptWithISK(int isk, const unsigned char *in, + size_t inlen, size_t *outlen); +unsigned char *TSAPI_SM2DecryptWithISK(int isk, const unsigned char *in, + size_t inlen, size_t *outlen); +unsigned char *TSAPI_ECCCipher_to_SM2Ciphertext(const OSSL_ECCCipher *ecc, + size_t *ciphertext_len); +OSSL_ECCCipher *TSAPI_SM2Ciphertext_to_ECCCipher(const unsigned char *ciphertext, + size_t ciphertext_len); +int TSAPI_ImportSM2Key(int index, int sign, const char *user, + const char *password, const EVP_PKEY *sm2_pkey); +OSSL_ECCrefPublicKey *TSAPI_EVP_PKEY_get_ECCrefPublicKey(const EVP_PKEY *pkey); +OSSL_ECCrefPrivateKey *TSAPI_EVP_PKEY_get_ECCrefPrivateKey(const EVP_PKEY *pkey); +EVP_PKEY *TSAPI_ExportSM2KeyWithIndex(int index, int sign, const char *user, + const char *password); +EVP_PKEY *TSAPI_EVP_PKEY_new_from_ECCrefKey(const OSSL_ECCrefPublicKey *pubkey, + const OSSL_ECCrefPrivateKey *privkey); +int TSAPI_ImportSM2KeyWithEvlp(int index, int sign, const char *user, + const char *password, unsigned char *key, + size_t keylen, unsigned char *dek, + size_t deklen); +int TSAPI_ExportSM2KeyWithEvlp(int index, int sign, const char *user, + const char *password, EVP_PKEY *sm2_pubkey, + unsigned char **priv, size_t *privlen, + unsigned char **pub, size_t *publen, + unsigned char **outevlp, size_t *outevlplen); +int TSAPI_GenerateSM2KeyWithIndex(int index, int sign, const char *user, const char *password); +int TSAPI_DelSm2KeyWithIndex(int index, int sign, const char *user, + const char *password); +int TSAPI_UpdateSm2KeyWithIndex(int index, int sign, const char *user, + const char *password); +EVP_PKEY *TSAPI_ExportSM2PubKeyWithIndex(int index, int sign); +# endif + +# ifndef OPENSSL_NO_SM4 +unsigned char *TSAPI_SM4Encrypt(int mode, const unsigned char *key, + size_t keylen, int isk, + const unsigned char *iv, + const unsigned char *in, size_t inlen, + size_t *outlen); +unsigned char *TSAPI_SM4Decrypt(int mode, const unsigned char *key, + size_t keylen, int isk, + const unsigned char *iv, + const unsigned char *in, size_t inlen, + size_t *outlen); +# endif +# ifndef OPENSSL_NO_SM3 +unsigned char *TSAPI_SM3(const void *data, size_t datalen, size_t *outlen); +# endif + +# ifdef __cplusplus +} +# endif + +#endif diff --git a/include/openssl/types.h b/include/openssl/types.h index 4e3bce468..ce5c076e6 100644 --- a/include/openssl/types.h +++ b/include/openssl/types.h @@ -244,6 +244,8 @@ typedef struct ossl_decoder_ctx_st OSSL_DECODER_CTX; typedef struct ossl_self_test_st OSSL_SELF_TEST; +typedef struct sdf_method_st SDF_METHOD; + #ifdef __cplusplus } #endif diff --git a/providers/build.info b/providers/build.info index 072bce04c..ff46b25b9 100644 --- a/providers/build.info +++ b/providers/build.info @@ -152,12 +152,22 @@ IF[{- !$disabled{smtc} -}] SOURCE[$SMTCGOAL]=smtc.ld GENERATE[smtc.ld]=../util/providers.num ENDIF - SOURCE[$LIBSMTC]=prov_running.c ENDIF DEFINE[$SMTCGOAL]=SMTC_MODULE DEFINE[$LIBDEFAULT]=SMTC_MODULE DEFINE[../libssl]=SMTC_MODULE + +{- use File::Spec::Functions; + our $ex_lib = $withargs{atf_slibce_lib} && + (file_name_is_absolute($withargs{atf_slibce_lib}) ? + $withargs{atf_slibce_lib} : catfile(updir(), $withargs{atf_slibce_lib})); + "" +-} + + IF[{- !$disabled{atf_slibce} -}] + DEPEND[$SMTCGOAL]={- $ex_lib -} + ENDIF ENDIF # 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..847f250d8 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,55 @@ 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(); + + while ((ret = write(fd[0], &data, sizeof(data))) < 0 && errno == EINTR); + if (ret < 0) { + close(fd[0]); + close(fd[1]); + break; + } + + while ((ret = read(fd[1], &data, sizeof(data))) < 0 && errno == EINTR); + if (ret < 0) { + close(fd[0]); + close(fd[1]); + break; + } + + /* 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 +751,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 +770,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 +784,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 +825,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 +867,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 + +# 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 - entropy_available = ossl_prov_acquire_entropy_from_rtc2(pool); - if (entropy_available > 0) - return entropy_available; +# 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..8877966ff 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/H) */ +#define REPEAT_COUNT_TEST_THRESHOLD 4 /* * 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,20 @@ 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. + */ + bytes_needed = (entropy + 7) / 8; + if (bytes_needed < min_len) + bytes_needed = min_len; + if (bytes_needed > max_len) + goto unlock_return; + + entp = ent = OPENSSL_secure_malloc(bytes_needed); + if (ent == NULL) + goto unlock_return; + OSSL_SELF_TEST_get_callback(libctx, &stcb, &stcbarg); if (stcb != NULL) { st = OSSL_SELF_TEST_new(stcb, stcbarg); @@ -136,16 +194,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/README.md b/providers/smtc/README.md index 1a7f2ee22..43628a058 100644 --- a/providers/smtc/README.md +++ b/providers/smtc/README.md @@ -1,25 +1,22 @@ -# 构建SMTC +# Build SMTC ``` -./config enable-smtc enable-ntls no-shared enable-ssl-trace --prefix=/opt/tongsuo -Wl,-rpath,/opt/tongsuo/lib64 +./config enable-smtc enable-ntls no-shared enable-ssl-trace --prefix=/path/to/tongsuo -Wl,-rpath,/path/to/tongsuo/lib64 make make install ``` -# 配置SMTC +# Install SMTC ``` -/opt/tongsuo/bin/tongsuo mod -module /opt/tongsuo/bin/tongsuo -provider_name smtc -section_name smtc_sect -show_selftest -out /opt/tongsuo/ssl/smtcmodule.cnf - -# 修改/opt/tongsuo/ssl/openssl.cnf,包含smtcmodule.cnf,设置smtc section -sed -i -e 's|^# .include smtcmodule.cnf|.include /opt/tongsuo/ssl/smtcmodule.cnf|;s/^# smtc = smtc_sect/smtc = smtc_sect/' /opt/tongsuo/ssl/openssl.cnf +/path/to/tongsuo/bin/tongsuo mod -install -module /path/to/tongsuo/bin/tongsuo -sigfile signature.bin ``` -# SMTC自测试 +# SMTC Self Test ``` -/opt/tongsuo/bin/tongsuo mod -test +/path/to/tongsuo/bin/tongsuo mod -test ``` diff --git a/providers/smtc/self_test.c b/providers/smtc/self_test.c index e76027833..a00c55958 100644 --- a/providers/smtc/self_test.c +++ b/providers/smtc/self_test.c @@ -7,15 +7,23 @@ * https://www.openssl.org/source/license.html */ +#include "internal/deprecated.h" + #include +#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" @@ -25,18 +33,143 @@ #include "self_test.h" #include "self_test_rand.h" #include "../implementations/rands/drbg_local.h" -#include "../../crypto/evp/evp_local.h" +#include "crypto/evp/evp_local.h" +#include "crypto/evp/legacy_meth.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}; + +#ifndef OPENSSL_NO_ATF_SLIBCE +IMPLEMENT_LEGACY_EVP_MD_METH(sm3_sw, SM3) +static EVP_MD *sm3_md = NULL; +static const EVP_MD *sw_sm3_md(void) +{ + if (sm3_md == NULL) { + EVP_MD *md; + + if ((md = EVP_MD_meth_new(NID_sm3, NID_SM2_with_SM3)) == NULL + || !EVP_MD_meth_set_result_size(md, SM3_DIGEST_LENGTH) + || !EVP_MD_meth_set_input_blocksize(md, SM3_CBLOCK) + || !EVP_MD_meth_set_app_datasize(md, + sizeof(EVP_MD *) + sizeof(SM3_CTX)) + || !EVP_MD_meth_set_flags(md, 0) + || !EVP_MD_meth_set_init(md, sm3_sw_init) + || !EVP_MD_meth_set_update(md, sm3_sw_update) + || !EVP_MD_meth_set_final(md, sm3_sw_final)) { + EVP_MD_meth_free(md); + md = NULL; + } + sm3_md = md; + } + return sm3_md; +} + +static int sw_digests(ENGINE *e, const EVP_MD **digest, + const int **nids, int nid) +{ + static int digest_nids[2] = { NID_sm3, 0}; + int ok = 1; + if (!digest) { + *nids = digest_nids; + return OSSL_NELEM(digest_nids); + } + + switch (nid) { + case NID_sm3: + *digest = sw_sm3_md(); + break; + default: + ok = 0; + *digest = NULL; + break; + } + + return ok; +} + +static CRYPTO_ONCE engine_atf_slibce = CRYPTO_ONCE_STATIC_INIT; +DEFINE_RUN_ONCE_STATIC(init_engine_atf_slibce) +{ + int ok = 0; + ENGINE *engine = NULL; + +# ifdef OPENSSL_NO_DYNAMIC_ENGINE + extern ENGINE *engine_atf_slibce_load(const char* engine_name); + engine = engine_atf_slibce_load("atf_slibce"); +# else + engine = ENGINE_by_id("atf_slibce"); +# endif + if (engine == NULL) + return 0; + + if(!ENGINE_ctrl_cmd_string(engine, "engine_load", NULL, 0)) { + OSSL_TRACE(SMTC, "Failed to execute cmd: engine_load\n"); + goto end; + } + + if(!ENGINE_ctrl_cmd_string(engine, "engine_alloc_prsrc", NULL, 0)) { + OSSL_TRACE(SMTC, "Failed to execute cmd: engine_alloc_prsrc\n"); + goto end; + } + + if(!ENGINE_ctrl_cmd_string(engine, "engine_enable_sm2", NULL, 0)) { + OSSL_TRACE(SMTC, "Failed to execute cmd: engine_enable_sm2\n"); + goto end; + } + + if(!ENGINE_ctrl_cmd_string(engine, "engine_enable_sm4", NULL, 0)) { + OSSL_TRACE(SMTC, "Failed to execute cmd: engine_enable_sm4\n"); + goto end; + } + + if(!ENGINE_ctrl_cmd_string(engine, "engine_enable_asym_kek", NULL, 0)) { + OSSL_TRACE(SMTC, "Failed to execute cmd: engine_enable_asym_kek\n"); + goto end; + } + + if(!ENGINE_ctrl_cmd_string(engine, "engine_enable_kek", NULL, 0)) { + OSSL_TRACE(SMTC, "Failed to execute cmd: engine_enable_kek\n"); + goto end; + } + + if(!ENGINE_ctrl_cmd_string(engine, "engine_enable_kgen_kek", NULL, 0)) { + OSSL_TRACE(SMTC, "Failed to execute cmd: engine_enable_kgen_kek\n"); + goto end; + } + + if (!ENGINE_set_digests(engine, sw_digests)) + goto end; + + if (!ENGINE_set_default_pkey_meths(engine)) + goto end; + + ok = 1; +end: +# ifdef OPENSSL_NO_DYNAMIC_ENGINE + if (ok == 0) +# endif + { + ENGINE_free(engine); + } + return ok; +} +#endif static CRYPTO_ONCE smtc_self_test_init = CRYPTO_ONCE_STATIC_INIT; DEFINE_RUN_ONCE_STATIC(do_smtc_self_test_init) @@ -52,93 +185,241 @@ DEFINE_RUN_ONCE_STATIC(do_smtc_self_test_init) } /* - * Calculate the HMAC SM3 of data read using a BIO and read_cb, and verify - * the result matches the expected value. + * 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. */ -static int verify_integrity(OSSL_CORE_BIO *bio, OSSL_FUNC_BIO_read_ex_fn read_ex_cb, +static int verify_integrity(OSSL_CORE_BIO *bio, + OSSL_FUNC_BIO_read_ex_fn read_ex_cb, unsigned char *expected, size_t expected_len, - OSSL_LIB_CTX *libctx, OSSL_SELF_TEST *ev, - const char *event_type) + OSSL_LIB_CTX *libctx, OSSL_SELF_TEST *ev) { - int ret = 0, status; - unsigned char out[MAX_MD_SIZE]; + int ok = 0, status; + 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, OSSL_SELF_TEST_TYPE_MODULE_INTEGRITY, + OSSL_SELF_TEST_DESC_INTEGRITY_VERIFY); - mac = EVP_MAC_fetch(libctx, MAC_NAME, NULL); - if (mac == NULL) - goto err; - ctx = EVP_MAC_CTX_new(mac); - if (ctx == NULL) - goto err; + pkey_bio = BIO_new_mem_buf(pubkey, sizeof(pubkey)); + if (pkey_bio == NULL) + goto end; - *p++ = OSSL_PARAM_construct_utf8_string("digest", DIGEST_NAME, 0); - *p = OSSL_PARAM_construct_end(); + pkey = PEM_read_bio_PUBKEY_ex(pkey_bio, NULL, NULL, NULL, libctx, NULL); + if (pkey == NULL) + goto end; - if (!EVP_MAC_init(ctx, fixed_key, sizeof(fixed_key), params)) - goto err; + mctx = EVP_MD_CTX_new(); + if (mctx == NULL) + goto end; + + if (EVP_DigestVerifyInit(mctx, NULL, EVP_sm3(), NULL, pkey) != 1) + goto end; while (1) { status = read_ex_cb(bio, buf, sizeof(buf), &bytes_read); if (status != 1) break; - if (!EVP_MAC_update(ctx, buf, bytes_read)) - 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) - goto err; - ret = 1; -err: - OSSL_SELF_TEST_onend(ev, ret); - EVP_MAC_CTX_free(ctx); - EVP_MAC_free(mac); - return ret; + if (EVP_DigestVerifyUpdate(mctx, buf, bytes_read) != 1) + goto end; + } + + OSSL_SELF_TEST_oncorrupt_byte(ev, expected); + + if (EVP_DigestVerifyFinal(mctx, expected, expected_len) != 1) + goto end; + + ok = 1; +end: + BIO_free(pkey_bio); + EVP_PKEY_free(pkey); + EVP_MD_CTX_free(mctx); + OSSL_SELF_TEST_onend(ev, ok); + return ok; } #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_file, + 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, keklen; + size_t outlen; + unsigned char mac[EVP_MAX_MD_SIZE]; + unsigned int maclen; + ENGINE *engine = NULL; + BIO *bio = NULL, *kekbio = NULL; + EVP_PKEY *pkek = NULL; + EVP_PKEY_CTX *ctx = NULL; + unsigned char kekbuf[4096]; + + if (conf_key == NULL && conf_salt == NULL) { + if (EVP_read_pw_string(passphrase, sizeof(passphrase), + "Enter password: ", 0) != 0) + goto end; - if (password == NULL || pass_len != SM3_DIGEST_LENGTH || salt == NULL - || salt_len != SM3_DIGEST_LENGTH) + 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; + + 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; + + 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; + + if (HMAC(EVP_sm3(), key, sizeof(key), buf, buflen, mac, &maclen) == NULL) + goto end; + + if (eng) { + engine = ENGINE_by_id(eng); + if (engine == NULL) { + OSSL_TRACE1(SMTC, "Can't load engine %s\n", eng); + goto end; + } + } + + kekbio = BIO_new_file(kek_file, "rb"); + if (kekbio == NULL) { + OSSL_TRACE1(SMTC, "Can't open auth kek file %s\n", kek_file); + goto end; + } + + keklen = BIO_read(kekbio, kekbuf, sizeof(kekbuf) - 1); + BIO_free(kekbio); + + if (keklen <= 0) { + OSSL_TRACE1(SMTC, "Error reading auth kek %s\n", kek_file); + goto end; + } + + kekbuf[keklen] = '\0'; + + /* + * atf_slibce engine doesn't support ENGINE_load_private_key(), use + * PEM_read_bio_PrivateKey() instead + */ +#ifdef OPENSSL_NO_ATF_SLIBCE + if (engine) { + pkek = ENGINE_load_private_key(engine, (const char *)kekbuf, NULL, + NULL); + } else { +#endif + bio = BIO_new_mem_buf((const void *)kekbuf, keklen); + if (bio == NULL) + goto end; + + pkek = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL); +#ifdef OPENSSL_NO_ATF_SLIBCE + } +#endif + + if (pkek == NULL) goto end; - if (memcmp(buf, password, pass_len)) + ctx = EVP_PKEY_CTX_new(pkek, engine); + if (ctx == NULL) + goto end; + + outlen = sizeof(mkey); + + if (EVP_PKEY_decrypt_init(ctx) != 1 + || EVP_PKEY_decrypt(ctx, mkey, &outlen, mac_key, mac_key_len) != 1 + || outlen != sizeof(mkey)) goto end; - ret = 1; + 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_syslog(LOG_ERR, "[SMTC] Admin login failed!\n"); + ossl_sleep(3000); + } else { + OSSL_syslog(LOG_INFO, "[SMTC] Admin login success\n"); + } + 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) @@ -161,82 +442,108 @@ static void smtc_set_state(int state) smtc_state = state; CRYPTO_THREAD_unlock(smtc_state_lock); } + + if (state == SMTC_STATE_ERROR) { + OSSL_syslog(LOG_ERR, "[SMTC] SMTC module entering error state\n"); + } else if (state == SMTC_STATE_RUNNING) { + OSSL_syslog(LOG_INFO, "[SMTC] SMTC module ready\n"); + } } -static int get_bit(const unsigned char *buf, int m) +/* + * GM/T 0105-2021 Appendix D.3, Adaptive Proportion Test + */ +static ossl_unused 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 = 0; +#if defined(OPENSSL_RAND_SEED_RTCODE) || defined(OPENSSL_RAND_SEED_RTMEM) \ + || defined(OPENSSL_RAND_SEED_RTSOCK) + size_t len = 1024, W = 512, C = 13; +#endif 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) { + if (!smtc_adaptive_proportion_test(entropy, len, W, C)) + 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) { + if (!smtc_adaptive_proportion_test(entropy, len, W, C)) 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) { + if (!smtc_adaptive_proportion_test(entropy, len, W, C)) + 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; +#if defined(OPENSSL_RAND_SEED_RTCODE) || defined(OPENSSL_RAND_SEED_RTMEM) \ + || defined(OPENSSL_RAND_SEED_RTSOCK) +end: +#endif + 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; + OSSL_SELF_TEST_onend(st, ok); + return ok; } /* This API is triggered either on loading of the SMTC module or on demand */ @@ -244,16 +551,21 @@ 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)) return 0; +#ifndef OPENSSL_NO_ATF_SLIBCE + if (!RUN_ONCE(&engine_atf_slibce, init_engine_atf_slibce)) { + OSSL_TRACE(SMTC, "Failed to load atf_slibce engine\n"); + goto end; + } +#endif + if (!CRYPTO_THREAD_write_lock(self_test_lock)) return 0; if (!CRYPTO_THREAD_read_lock(smtc_state_lock)) { @@ -285,25 +597,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_TRACE(SMTC, "Module integrity verification failed\n"); ERR_raise(ERR_LIB_PROV, PROV_R_MODULE_INTEGRITY_FAILURE); goto end; } @@ -319,12 +630,20 @@ int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test) if ((st->randomness_poweron_test == NULL || atoi(st->randomness_poweron_test) != 0) - && !smtc_randomness_test_poweron(ev, st->libctx)) { + && (!smtc_rand_poweron_test(ev, 0) +#ifdef SDF_LIB + || !smtc_rand_poweron_test(ev, 1) +#endif + )) { ERR_raise(ERR_LIB_PROV, PROV_R_SELF_TEST_POST_FAILURE); goto end; } } else { // SMTC_STATE_SELFTEST_WHILE_RUNNING - if (!smtc_randomness_test_single(ev, st->libctx)) { + if (!smtc_rand_single_test(ev, 0) +#ifdef SDF_LIB + || !smtc_rand_single_test(ev, 1) +#endif + ) { ERR_raise(ERR_LIB_PROV, PROV_R_SELF_TEST_POST_FAILURE); goto end; } @@ -339,46 +658,56 @@ 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: - OPENSSL_free(password); - OPENSSL_free(salt); OSSL_SELF_TEST_free(ev); - OPENSSL_free(module_checksum); + OPENSSL_free(module_sig); if (st != NULL) ossl_prov_bio_free(bio_module); - if (ok) + if (ok) { + OSSL_syslog(LOG_INFO, "[SMTC] Self-test passed\n"); smtc_set_state(SMTC_STATE_RUNNING); - else + } else { + OSSL_syslog(LOG_ERR, "[SMTC] Self-test failed\n"); smtc_set_state(SMTC_STATE_ERROR); + } CRYPTO_THREAD_unlock(self_test_lock); 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..ffbec9618 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 *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 *module_sig; /* Signature of module */ + 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 *syslog; /* syslog switch */ + 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..741466bf3 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; @@ -155,6 +166,20 @@ static const ST_KAT_DIGEST st_kat_digest_tests[] = /*- CIPHER TEST DATA */ #ifndef OPENSSL_NO_SM4 +/* SM4-ECB test data */ +static const unsigned char sm4_ecb_key[] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, +}; +static const unsigned char sm4_ecb_pt[] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, +}; +static const unsigned char sm4_ecb_ct[] = { + 0x68, 0x1E, 0xDF, 0x34, 0xD2, 0x06, 0x96, 0x5E, + 0x86, 0xB3, 0xE9, 0x4F, 0x53, 0x6E, 0x42, 0x46, +}; + /* SM4-CBC test data */ static const unsigned char sm4_cbc_key[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, @@ -212,6 +237,16 @@ static const unsigned char sm4_gcm_tag[] = { static const ST_KAT_CIPHER st_kat_cipher_tests[] = { #ifndef OPENSSL_NO_SM4 + { + { + "SM4_ECB", + "SM4-ECB", + ITM(sm4_ecb_pt), + ITM(sm4_ecb_ct) + }, + CIPHER_MODE_ENCRYPT | CIPHER_MODE_DECRYPT, + ITM(sm4_ecb_key), + }, { { "SM4_CBC", @@ -223,6 +258,7 @@ static const ST_KAT_CIPHER st_kat_cipher_tests[] = ITM(sm4_cbc_key), ITM(sm4_cbc_iv), }, +/* { { "SM4_GCM", @@ -236,6 +272,7 @@ static const ST_KAT_CIPHER st_kat_cipher_tests[] = ITM(sm4_gcm_aad), ITM(sm4_gcm_tag), }, +*/ #endif }; @@ -364,21 +401,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 +466,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 +783,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 +824,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 }; @@ -759,7 +865,7 @@ static const ST_KAT_ASYM_CIPHER st_kat_asym_cipher_tests[] = { OSSL_SELF_TEST_DESC_ASYM_SM2_DEC, "SM2", 0, - sm2_priv_key, + sm2_key, sm2_enc_params, ITM(sm2_asym_expected_encrypt), ITM(sm2_asym_plaintext_encrypt), diff --git a/providers/smtc/self_test_kats.c b/providers/smtc/self_test_kats.c index 4c4c95177..aa9094f0c 100644 --- a/providers/smtc/self_test_kats.c +++ b/providers/smtc/self_test_kats.c @@ -12,10 +12,22 @@ #include #include #include +#include +#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" +#include "../../crypto/sdf/sdf_local.h" +#ifdef SDF_LIB +# include "sdfe_api.h" +#endif + static int self_test_digest(const ST_KAT_DIGEST *t, OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) @@ -247,13 +259,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 +303,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 +319,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 +338,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] = @@ -358,8 +385,128 @@ static int self_test_drbg(const ST_KAT_DRBG *t, OSSL_SELF_TEST *st, return ret; } -static int self_test_sign(const ST_KAT_SIGN *t, - OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) +#ifdef SDF_LIB +static int bitmap_is_inuse(uint64_t *pu64, int32_t index) +{ + + int32_t pos, offset; + uint64_t mask; + + mask = 0x1ull; + + pos = index >> 6; + offset = (63 - (index & 0x3f)); + mask <<= offset; + + return (pu64[pos] & mask) ? 1 : 0; +} + +static int self_test_sign_with_sdf(const ST_KAT_SIGN *t, OSSL_SELF_TEST *st, + OSSL_LIB_CTX *libctx) +{ + int ok = 0; + void *hDeviceHandle = NULL; + void *hSessionHandle = NULL; + sdfe_login_arg_t login_arg; + OSSL_ECCrefPrivateKey privkey; + OSSL_ECCrefPublicKey pubkey; + sdfe_bitmap_t bitmap; + sdfe_asym_key_ecc_t asym; + const ST_KAT_PARAM *param; + OSSL_ECCSignature sig; + uint32_t cnt, i; + int index = -1; + const char *typ = OSSL_SELF_TEST_TYPE_KAT_SIGNATURE; + + if (t->sig_expected == NULL) + typ = OSSL_SELF_TEST_TYPE_PCT_SIGNATURE; + + OSSL_SELF_TEST_onbegin(st, typ, t->desc); + + memset(&privkey, 0, sizeof(privkey)); + memset(&pubkey, 0, sizeof(pubkey)); + memset(&asym, 0, sizeof(asym)); + memset(&login_arg, 0, sizeof(login_arg)); + + strcpy((char *)login_arg.name, "admin"); + login_arg.passwd = (uint8_t *)"123123"; + login_arg.passwd_len = 6; + + if (TSAPI_SDF_OpenDevice(&hDeviceHandle) != OSSL_SDR_OK) + goto end; + + if (TSAPI_SDF_OpenSession(hDeviceHandle, &hSessionHandle) != OSSL_SDR_OK) + goto end; + + if (SDFE_LoginUsr(hSessionHandle, &login_arg) != OSSL_SDR_OK) + goto end; + + bitmap.start = 0; + bitmap.cnt = SDFE_BITMAP_U64_MAX_CNT; + if (SDFE_BitmapAsymKey(hSessionHandle, SDFE_ASYM_KEY_AREA_ENC, + SDFE_ASYM_KEY_TYPE_SM2, &bitmap) != OSSL_SDR_OK) + goto end; + + cnt = bitmap.cnt << 6; + for(i = 0; i < cnt; i++){ + if(!bitmap_is_inuse(bitmap.bitmap, i)) { + index = i; + break; + } + } + + if (index < 0) + goto end; + + asym.area = SDFE_ASYM_KEY_AREA_SIGN; + asym.index = index; + asym.type = SDFE_ASYM_KEY_TYPE_SM2; + asym.privkey_bits = 256; + asym.privkey_len = asym.privkey_bits >> 3; + asym.pubkey_bits = 256; + asym.pubkey_len = (asym.pubkey_bits >> 3) << 1; + + for (param = t->key; param->data; param++) { + if (strcmp(param->name, OSSL_PKEY_PARAM_PUB_KEY) == 0) { + pubkey.bits = 256; + memcpy(pubkey.x + sizeof(pubkey.x) - 32, + (unsigned char *)param->data + 1, 32); + memcpy(pubkey.y + sizeof(pubkey.y) - 32, + (unsigned char *)param->data + 1 + 32, 32); + } else if (strcmp(param->name, OSSL_PKEY_PARAM_PRIV_KEY) == 0) { + privkey.bits = 256; + memcpy(privkey.K + sizeof(privkey.K) - param->data_len, param->data, + param->data_len); + } + } + + memcpy(asym.pubkey, &pubkey, sizeof(pubkey)); + memcpy(asym.privkey, &privkey, sizeof(privkey)); + + if (SDFE_ImportECCKey(hSessionHandle, &asym, NULL) != OSSL_SDR_OK) + goto end; + + if (TSAPI_SDF_GetPrivateKeyAccessRight(hSessionHandle, index, NULL, 0) + != OSSL_SDR_OK) + goto end; + + if (TSAPI_SDF_InternalSign_ECC(hSessionHandle, index, + (unsigned char *)t->dgst, + t->dgst_len, &sig) != OSSL_SDR_OK) + goto end; + + ok = 1; +end: + (void)SDFE_DelECCKey(hSessionHandle, asym.area, index); + TSAPI_SDF_CloseSession(hSessionHandle); + TSAPI_SDF_CloseDevice(hDeviceHandle); + OSSL_SELF_TEST_onend(st, ok); + return ok; +} +#endif + +static int self_test_sign(const ST_KAT_SIGN *t, OSSL_SELF_TEST *st, + OSSL_LIB_CTX *libctx) { int ret = 0; OSSL_PARAM *params = NULL, *params_sig = NULL; @@ -369,13 +516,13 @@ 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; +#ifdef SDF_LIB + if (t->sign) + return self_test_sign_with_sdf(t, st, libctx); +#endif + if (t->sig_expected == NULL) typ = OSSL_SELF_TEST_TYPE_PCT_SIGNATURE; @@ -391,20 +538,20 @@ static int self_test_sign(const ST_KAT_SIGN *t, if (!add_params(bld, t->key, bnctx)) goto err; + params = OSSL_PARAM_BLD_to_param(bld); - /* Create a EVP_PKEY_CTX to load the DSA key into */ - kctx = EVP_PKEY_CTX_new_from_name(libctx, t->algorithm, ""); + kctx = EVP_PKEY_CTX_new_from_name_provided(libctx, t->algorithm, NULL); + if (kctx == NULL || params == NULL) goto err; + if (EVP_PKEY_fromdata_init(kctx) <= 0 || EVP_PKEY_fromdata(kctx, &pkey, EVP_PKEY_KEYPAIR, params) <= 0) goto err; - /* 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) + sctx = EVP_PKEY_CTX_new_from_pkey_provided(libctx, pkey, NULL); + if (sctx == NULL) goto err; /* set signature parameters */ @@ -412,47 +559,172 @@ 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); EVP_PKEY_free(pkey); - EVP_PKEY_CTX_free(kctx); EVP_PKEY_CTX_free(sctx); - OSSL_PARAM_free(params); OSSL_PARAM_free(params_sig); OSSL_PARAM_BLD_free(bld); OSSL_SELF_TEST_onend(st, ret); return ret; } -/* - * Test an encrypt or decrypt KAT.. - * - * FIPS 140-2 IG D.9 states that separate KAT tests are needed for encrypt - * and decrypt.. - */ -static int self_test_asym_cipher(const ST_KAT_ASYM_CIPHER *t, OSSL_SELF_TEST *st, +#ifdef SDF_LIB +static int self_test_asym_decrypt_with_sdf(const ST_KAT_ASYM_CIPHER *t, + OSSL_SELF_TEST *st, + OSSL_LIB_CTX *libctx) +{ + int ok = 0; + void *hDeviceHandle = NULL; + void *hSessionHandle = NULL; + sdfe_login_arg_t login_arg; + OSSL_ECCrefPrivateKey privkey; + OSSL_ECCrefPublicKey pubkey; + sdfe_bitmap_t bitmap; + sdfe_asym_key_ecc_t asym; + const ST_KAT_PARAM *param; + OSSL_ECCCipher *pECCCipher = NULL; + unsigned char out[256]; + unsigned int outlen = sizeof(out); + uint32_t cnt, i; + int index = -1; + const char *typ = OSSL_SELF_TEST_TYPE_KAT_ASYM_CIPHER; + + if (t->expected == NULL) + typ = OSSL_SELF_TEST_TYPE_PCT_ASYM_CIPHER; + + OSSL_SELF_TEST_onbegin(st, typ, t->desc); + + memset(&privkey, 0, sizeof(privkey)); + memset(&pubkey, 0, sizeof(pubkey)); + memset(&asym, 0, sizeof(asym)); + memset(&login_arg, 0, sizeof(login_arg)); + + strcpy((char *)login_arg.name, "admin"); + login_arg.passwd = (uint8_t *)"123123"; + login_arg.passwd_len = 6; + + if (TSAPI_SDF_OpenDevice(&hDeviceHandle) != OSSL_SDR_OK) + goto end; + + if (TSAPI_SDF_OpenSession(hDeviceHandle, &hSessionHandle) != OSSL_SDR_OK) + goto end; + + if (SDFE_LoginUsr(hSessionHandle, &login_arg) != OSSL_SDR_OK) + goto end; + + bitmap.start = 0; + bitmap.cnt = SDFE_BITMAP_U64_MAX_CNT; + if (SDFE_BitmapAsymKey(hSessionHandle, SDFE_ASYM_KEY_AREA_ENC, + SDFE_ASYM_KEY_TYPE_SM2, &bitmap) != OSSL_SDR_OK) + goto end; + + cnt = bitmap.cnt << 6; + for(i = 0; i < cnt; i++){ + if(!bitmap_is_inuse(bitmap.bitmap, i)) { + index = i; + break; + } + } + + if (index < 0) + goto end; + + asym.area = SDFE_ASYM_KEY_AREA_ENC; + asym.index = index; + asym.type = SDFE_ASYM_KEY_TYPE_SM2; + asym.privkey_bits = 256; + asym.privkey_len = asym.privkey_bits >> 3; + asym.pubkey_bits = 256; + asym.pubkey_len = (asym.pubkey_bits >> 3) << 1; + + for (param = t->key; param->data; param++) { + if (strcmp(param->name, OSSL_PKEY_PARAM_PUB_KEY) == 0) { + pubkey.bits = 256; + memcpy(pubkey.x + sizeof(pubkey.x) - 32, + (unsigned char *)param->data + 1, 32); + memcpy(pubkey.y + sizeof(pubkey.y) - 32, + (unsigned char *)param->data + 1 + 32, 32); + } else if (strcmp(param->name, OSSL_PKEY_PARAM_PRIV_KEY) == 0) { + privkey.bits = 256; + memcpy(privkey.K + sizeof(privkey.K) - param->data_len, param->data, + param->data_len); + } + } + + memcpy(asym.pubkey, &pubkey, sizeof(pubkey)); + memcpy(asym.privkey, &privkey, sizeof(privkey)); + + if (SDFE_ImportECCKey(hSessionHandle, &asym, NULL) != OSSL_SDR_OK) + goto end; + + if (TSAPI_SDF_GetPrivateKeyAccessRight(hSessionHandle, index, NULL, 0) + != OSSL_SDR_OK) + goto end; + + pECCCipher = TSAPI_SM2Ciphertext_to_ECCCipher(t->in, t->in_len); + + if (TSAPI_SDF_InternalDecrypt_ECC(hSessionHandle, index, pECCCipher, + out, &outlen) != OSSL_SDR_OK) + goto end; + + OSSL_SELF_TEST_oncorrupt_byte(st, out); + + if (t->expected != NULL + && (outlen != t->expected_len + || memcmp(out, t->expected, t->expected_len) != 0)) + goto end; + + ok = 1; +end: + OPENSSL_free(pECCCipher); + (void)SDFE_DelECCKey(hSessionHandle, asym.area, index); + TSAPI_SDF_CloseSession(hSessionHandle); + TSAPI_SDF_CloseDevice(hDeviceHandle); + OSSL_SELF_TEST_onend(st, ok); + return ok; +} +#endif + +static int self_test_asym_cipher(const ST_KAT_ASYM_CIPHER *t, + OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) { int ret = 0; @@ -463,8 +735,17 @@ static int self_test_asym_cipher(const ST_KAT_ASYM_CIPHER *t, OSSL_SELF_TEST *st BN_CTX *bnctx = NULL; unsigned char out[256]; size_t outlen = sizeof(out); + const char *typ = OSSL_SELF_TEST_TYPE_KAT_ASYM_CIPHER; + +#ifdef SDF_LIB + if (!t->encrypt) + return self_test_asym_decrypt_with_sdf(t, st, libctx); +#endif - OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_KAT_ASYM_CIPHER, t->desc); + if (t->expected == NULL) + typ = OSSL_SELF_TEST_TYPE_PCT_ASYM_CIPHER; + + OSSL_SELF_TEST_onbegin(st, typ, t->desc); bnctx = BN_CTX_new_ex(libctx); if (bnctx == NULL) @@ -476,7 +757,7 @@ static int self_test_asym_cipher(const ST_KAT_ASYM_CIPHER *t, OSSL_SELF_TEST *st || !add_params(keybld, t->key, bnctx)) goto err; keyparams = OSSL_PARAM_BLD_to_param(keybld); - keyctx = EVP_PKEY_CTX_new_from_name(libctx, t->algorithm, NULL); + keyctx = EVP_PKEY_CTX_new_from_name_provided(libctx, t->algorithm, NULL); if (keyctx == NULL || keyparams == NULL) goto err; if (EVP_PKEY_fromdata_init(keyctx) <= 0 @@ -484,7 +765,7 @@ static int self_test_asym_cipher(const ST_KAT_ASYM_CIPHER *t, OSSL_SELF_TEST *st 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); + encctx = EVP_PKEY_CTX_new_from_pkey_provided(libctx, key, NULL); if (encctx == NULL || (t->encrypt && EVP_PKEY_encrypt_init(encctx) <= 0) || (!t->encrypt && EVP_PKEY_decrypt_init(encctx) <= 0)) @@ -614,17 +895,12 @@ int SELF_TEST_kats(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) { int ret = 1; - if (!self_test_digests(st, libctx)) - ret = 0; - if (!self_test_ciphers(st, libctx)) - ret = 0; - if (!self_test_signatures(st, libctx)) - ret = 0; - if (!self_test_kdfs(st, libctx)) - ret = 0; - if (!self_test_drbgs(st, libctx)) - ret = 0; - if (!self_test_asym_ciphers(st, libctx)) + if (!self_test_digests(st, libctx) + || !self_test_ciphers(st, libctx) + || !self_test_asym_ciphers(st, libctx) + || !self_test_signatures(st, libctx) + || !self_test_kdfs(st, libctx) + || !self_test_drbgs(st, libctx)) ret = 0; return ret; diff --git a/providers/smtc/self_test_rand.c b/providers/smtc/self_test_rand.c index a35fd965c..78296b9f4 100644 --- a/providers/smtc/self_test_rand.c +++ b/providers/smtc/self_test_rand.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include "internal/nelem.h" #include "self_test_rand.h" @@ -1903,19 +1904,36 @@ int rand_self_test_discrete_fourier_transform(const unsigned char *buf, return p_value >= alpha; } -int smtc_randomness_test_delivery(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) +int smtc_rand_delivery_test(OSSL_SELF_TEST *st, int sdf) { int nbit = 1000000; unsigned char buf[nbit / 8]; int fail[15] = {0}; size_t i = 0, j, k; int retry = 1, res = 0; + void *hDeviceHandle = NULL, *hSessionHandle = NULL; - OSSL_SELF_TEST_onbegin(st, "Delivery_Test", "Randomness"); + if (sdf) + OSSL_SELF_TEST_onbegin(st, "Delivery_Test", "Randomness for device"); + else + OSSL_SELF_TEST_onbegin(st, "Delivery_Test", "Randomness"); + + if (sdf) { + if (TSAPI_SDF_OpenDevice(&hDeviceHandle) != 0) + goto end; + + if (TSAPI_SDF_OpenSession(hDeviceHandle, &hSessionHandle) != 0) + goto end; + } while (i++ < 50) { - if (RAND_bytes(buf, nbit / 8) != 1) - return 0; + if (sdf) { + if (TSAPI_SDF_GenerateRandom(hSessionHandle, nbit / 8, buf) != 0) + goto end; + } else { + if (RAND_bytes(buf, nbit / 8) != 1) + goto end; + } j = 0; fail[j++] += rand_self_test_frequency(buf, nbit, NULL) ^ 1; @@ -1948,23 +1966,42 @@ int smtc_randomness_test_delivery(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) res = 1; end: + TSAPI_SDF_CloseSession(hSessionHandle); + TSAPI_SDF_CloseDevice(hDeviceHandle); OSSL_SELF_TEST_onend(st, res); return 1; } -int smtc_randomness_test_poweron(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) +int smtc_rand_poweron_test(OSSL_SELF_TEST *st, int sdf) { int nbit = 1000000; unsigned char buf[nbit / 8]; int fail[15]; size_t i = 0, j, k; int retry = 1, res = 0; + void *hDeviceHandle = NULL, *hSessionHandle = NULL; - OSSL_SELF_TEST_onbegin(st, "Poweron_Test", "Randomness"); + if (sdf) + OSSL_SELF_TEST_onbegin(st, "Poweron_Test", "Randomness for device"); + else + OSSL_SELF_TEST_onbegin(st, "Poweron_Test", "Randomness"); - while(i++ < 20) { - if (RAND_bytes(buf, nbit / 8) != 1) + if (sdf) { + if (TSAPI_SDF_OpenDevice(&hDeviceHandle) != 0) + goto end; + + if (TSAPI_SDF_OpenSession(hDeviceHandle, &hSessionHandle) != 0) goto end; + } + + while(i++ < 20) { + if (sdf) { + if (TSAPI_SDF_GenerateRandom(hSessionHandle, nbit / 8, buf) != 0) + goto end; + } else { + if (RAND_bytes(buf, nbit / 8) != 1) + goto end; + } j = 0; fail[j++] += rand_self_test_frequency(buf, nbit, NULL) ^ 1; @@ -1997,25 +2034,37 @@ int smtc_randomness_test_poweron(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) res = 1; end: + TSAPI_SDF_CloseSession(hSessionHandle); + TSAPI_SDF_CloseDevice(hDeviceHandle); OSSL_SELF_TEST_onend(st, res); return 1; } -int smtc_randomness_test_cyclical(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) +int smtc_rand_cyclical_test(OSSL_SELF_TEST *st, int sdf) { int nbit = 20000; unsigned char buf[nbit / 8]; int fail[12] = {0}; size_t i = 0, j, k; int retry = 1, res = 0; + void *hDeviceHandle = NULL, *hSessionHandle = NULL; - OSSL_SELF_TEST_onbegin(st, "Cyclical_Test", "Randomness"); + if (sdf) + OSSL_SELF_TEST_onbegin(st, "Cyclical_Test", "Randomness for device"); + else + OSSL_SELF_TEST_onbegin(st, "Cyclical_Test", "Randomness"); while(i++ < 20) { - if (RAND_bytes(buf, nbit / 8) != 1) - goto end; + if (sdf) { + if (TSAPI_SDF_GenerateRandom(hSessionHandle, nbit / 8, buf) != 0) + goto end; + } else { + if (RAND_bytes(buf, nbit / 8) != 1) + goto end; + } j = 0; + fail[j++] += rand_self_test_frequency(buf, nbit, NULL) ^ 1; fail[j++] += rand_self_test_block_frequency(buf, nbit, 1000, NULL) ^ 1; fail[j++] += rand_self_test_poker(buf, nbit, 8, NULL) ^ 1; @@ -2043,22 +2092,41 @@ int smtc_randomness_test_cyclical(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) res = 1; end: + TSAPI_SDF_CloseSession(hSessionHandle); + TSAPI_SDF_CloseDevice(hDeviceHandle); OSSL_SELF_TEST_onend(st, res); return 1; } -int smtc_randomness_test_single(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) +int smtc_rand_single_test(OSSL_SELF_TEST *st, int sdf) { int nbit = 256; unsigned char buf[nbit / 8]; int retry = 1, res = 0; + void *hDeviceHandle = NULL, *hSessionHandle = NULL; - OSSL_SELF_TEST_onbegin(st, "Single_Test", "Randomness"); + if (sdf) + OSSL_SELF_TEST_onbegin(st, "Single_Test", "Randomness for device"); + else + OSSL_SELF_TEST_onbegin(st, "Single_Test", "Randomness"); - do { - if (RAND_bytes(buf, nbit / 8) != 1) + if (sdf) { + if (TSAPI_SDF_OpenDevice(&hDeviceHandle) != 0) goto end; + if (TSAPI_SDF_OpenSession(hDeviceHandle, &hSessionHandle) != 0) + goto end; + } + + do { + if (sdf) { + if (TSAPI_SDF_GenerateRandom(hSessionHandle, nbit / 8, buf) != 0) + goto end; + } else { + if (RAND_bytes(buf, nbit / 8) != 1) + goto end; + } + if (rand_self_test_poker(buf, nbit, 2, NULL) == 1) break; else @@ -2067,6 +2135,8 @@ int smtc_randomness_test_single(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) res = 1; end: + TSAPI_SDF_CloseSession(hSessionHandle); + TSAPI_SDF_CloseDevice(hDeviceHandle); OSSL_SELF_TEST_onend(st, res); return 1; } diff --git a/providers/smtc/self_test_rand.h b/providers/smtc/self_test_rand.h index 3dd69ff20..c33745a97 100644 --- a/providers/smtc/self_test_rand.h +++ b/providers/smtc/self_test_rand.h @@ -45,7 +45,7 @@ int rand_self_test_maurer_universal_statistical(const unsigned char *buf, int rand_self_test_discrete_fourier_transform(const unsigned char *buf, size_t nbit, double *P); -int smtc_randomness_test_delivery(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx); -int smtc_randomness_test_poweron(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx); -int smtc_randomness_test_cyclical(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx); -int smtc_randomness_test_single(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx); +int smtc_rand_delivery_test(OSSL_SELF_TEST *st, int sdf); +int smtc_rand_poweron_test(OSSL_SELF_TEST *st, int sdf); +int smtc_rand_cyclical_test(OSSL_SELF_TEST *st, int sdf); +int smtc_rand_single_test(OSSL_SELF_TEST *st, int sdf); 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..6455d50ad 100644 --- a/providers/smtc/smtcprov.c +++ b/providers/smtc/smtcprov.c @@ -8,11 +8,15 @@ */ #include +#include #include #include #include +#include +#include #include #include +#include #include "internal/cryptlib.h" #include "prov/implementations.h" #include "prov/bio.h" @@ -24,6 +28,14 @@ #include "self_test.h" #include "internal/core.h" #include "internal/smtc_names.h" +#include "internal/thread_once.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 @@ -41,12 +53,6 @@ OSSL_provider_init_fn ossl_smtc_provider_init; # define OSSL_provider_init_int ossl_smtc_provider_init #endif -/* - * Should these function pointers be stored in the provider side provctx? Could - * they ever be different from one init to the next? We assume not for now. - */ -static BIO *bio_err = NULL; - /* Functions provided by the core */ static OSSL_FUNC_core_gettable_params_fn *c_gettable_params = NULL; static OSSL_FUNC_core_get_params_fn *c_get_params; @@ -91,32 +97,40 @@ 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[14], *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_AUTH_KEY, + (char **)&fgbl->selftest_params.auth_key, + sizeof(fgbl->selftest_params.auth_key)); *p++ = OSSL_PARAM_construct_utf8_ptr( - OSSL_PROV_SMTC_PARAM_SHOW_SELFTEST, - (char **)&fgbl->selftest_params.show_selftest, - sizeof(fgbl->selftest_params.show_selftest)); + 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_PASS, - (char **)&fgbl->selftest_params.admin_pass, - sizeof(fgbl->selftest_params.admin_pass)); + 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_ADMIN_SALT, - (char **)&fgbl->selftest_params.admin_salt, - sizeof(fgbl->selftest_params.admin_salt)); + 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, sizeof(fgbl->selftest_params.rng_poweron_test)); + *p++ = OSSL_PARAM_construct_utf8_ptr( + OSSL_PROV_SMTC_PARAM_SYSLOG, + (char **)&fgbl->selftest_params.syslog, + sizeof(fgbl->selftest_params.syslog)); *p++ = OSSL_PARAM_construct_utf8_ptr( OSSL_PROV_SMTC_PARAM_RNG_CONTINUOUS_TEST, (char **)&fgbl->selftest_params.rng_continuous_test, @@ -127,9 +141,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 +178,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; } @@ -177,12 +191,6 @@ static int self_test_events(const OSSL_PARAM params[], void *arg) const char *phase = NULL, *type = NULL, *desc = NULL; int ret = 0; - if (bio_err == NULL) { - bio_err = BIO_new_fp(stderr, BIO_NOCLOSE | BIO_FP_TEXT); - if (bio_err == NULL) - return 0; - } - p = OSSL_PARAM_locate_const(params, OSSL_PROV_PARAM_SELF_TEST_PHASE); if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING) goto err; @@ -198,11 +206,10 @@ static int self_test_events(const OSSL_PARAM params[], void *arg) goto err; type = (const char *)p->data; - if (strcmp(phase, OSSL_SELF_TEST_PHASE_START) == 0) - BIO_printf(bio_err, "%s : (%s) : %s\n", desc, type, phase); - else if (strcmp(phase, OSSL_SELF_TEST_PHASE_PASS) == 0 - || strcmp(phase, OSSL_SELF_TEST_PHASE_FAIL) == 0) - BIO_printf(bio_err, "%s : (%s) : %s\n", desc, type, phase); + if (strcmp(phase, OSSL_SELF_TEST_PHASE_START) == 0 + || strcmp(phase, OSSL_SELF_TEST_PHASE_PASS) == 0 + || strcmp(phase, OSSL_SELF_TEST_PHASE_FAIL) == 0) + OSSL_TRACE3(SMTC, "%s : (%s) : %s\n", desc, type, phase); /* * The self test code will internally corrupt the KAT test result if an * error is returned during the corrupt phase. @@ -216,7 +223,7 @@ static int self_test_events(const OSSL_PARAM params[], void *arg) if (self_test_corrupt_type != NULL && strcmp(self_test_corrupt_type, type) != 0) goto end; - BIO_printf(bio_err, "%s : (%s) : %s\n", desc, type, phase); + OSSL_TRACE3(SMTC, "%s : (%s) : %s\n", desc, type, phase); goto err; } end: @@ -227,10 +234,8 @@ static int self_test_events(const OSSL_PARAM params[], void *arg) static void set_self_test_cb(SMTC_GLOBAL *fgbl) { - if (fgbl->selftest_params.show_selftest != NULL - && atoi(fgbl->selftest_params.show_selftest) != 0) - OSSL_SELF_TEST_set_callback(fgbl->selftest_params.libctx, - self_test_events, NULL); + OSSL_SELF_TEST_set_callback(fgbl->selftest_params.libctx, self_test_events, + NULL); if (c_stcbfn != NULL) { c_stcbfn((OPENSSL_CORE_CTX *)fgbl->selftest_params.libctx, @@ -244,14 +249,70 @@ 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_status(void *provctx) +{ + return ossl_prov_is_running(); +} + +static int smtc_reset(void *provctx) +{ + int ok = 0, i; + const char *conf_file = OPENSSL_info(OPENSSL_INFO_SMTC_MODULE_CONF); + CONF *conf = NULL; + STACK_OF(CONF_VALUE) *sect = NULL; + CONF_VALUE *cv = NULL; + const char *sec_name = "smtc_sect"; + BIO *out = NULL; + long eline; + + conf = NCONF_new(NCONF_default()); + if (conf == NULL) + goto end; + + if (NCONF_load(conf, conf_file, &eline) <= 0) + goto end; + + out = BIO_new_file(conf_file, "w"); + if (out == NULL) + goto end; + + if (BIO_printf(out, "[%s]\n", sec_name) <= 0 + || BIO_printf(out, "activate = 1\n") <= 0) + goto end; + + sect = NCONF_get_section(conf, sec_name); + + for (i = 0; i < sk_CONF_VALUE_num(sect); i++) { + cv = sk_CONF_VALUE_value(sect, i); + + if (strcmp(cv->name, OSSL_PROV_SMTC_PARAM_MODULE_PATH) == 0 + || strcmp(cv->name, OSSL_PROV_SMTC_PARAM_MODULE_SIG) == 0 + || strcmp(cv->name, OSSL_PROV_SMTC_PARAM_AUTH_KEK) == 0 + || strcmp(cv->name, OSSL_PROV_SMTC_PARAM_ENGINE) == 0 + || strcmp(cv->name, OSSL_PROV_SMTC_PARAM_SYSLOG) == 0 + || strcmp(cv->name, OSSL_PROV_SMTC_PARAM_RANDOMNESS_POWERON_TEST) == 0) + if (BIO_printf(out, "%s = %s\n", cv->name, cv->value) <= 0) + goto end; + } + + ok = 1; + OSSL_syslog(LOG_NOTICE, "[SMTC] Reset module\n"); +end: + NCONF_free(conf); + BIO_free(out); + + return ok; +} + /* * For the algorithm names, we use the following formula for our primary * names: @@ -286,8 +347,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}}; @@ -300,6 +366,7 @@ static const OSSL_ALGORITHM smtc_macs[] = { static const OSSL_ALGORITHM smtc_kdfs[] = { { PROV_NAMES_TLS1_PRF, "provider=smtc", ossl_kdf_tls1_prf_functions }, + { PROV_NAMES_PBKDF2, "provider=smtc", ossl_kdf_pbkdf2_functions }, /* used by SM2 encryption and decryption */ { PROV_NAMES_X963KDF, "provider=smtc", ossl_kdf_x963_kdf_functions }, { NULL, NULL, NULL } @@ -307,6 +374,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 } }; @@ -349,11 +417,18 @@ static const OSSL_ALGORITHM smtc_keymgmt[] = { PROV_DESCS_SM2 }, #endif /* TLCP create HMAC, such as ECC-SM2-SM4-CBC-SM3 */ - { PROV_NAMES_HMAC, "provider=default", ossl_mac_legacy_keymgmt_functions, + { PROV_NAMES_HMAC, "provider=smtc", ossl_mac_legacy_keymgmt_functions, PROV_DESCS_HMAC_SIGN }, { NULL, NULL, NULL } }; +static const OSSL_ALGORITHM smtc_encoder[] = { +#define ENCODER_PROVIDER "smtc" +#include "../encoders.inc" + { NULL, NULL, NULL } +#undef ENCODER_PROVIDER +}; + static const OSSL_ALGORITHM smtc_decoder[] = { #define DECODER_PROVIDER "smtc" #include "../decoders.inc" @@ -361,6 +436,15 @@ static const OSSL_ALGORITHM smtc_decoder[] = { #undef DECODER_PROVIDER }; +static const OSSL_ALGORITHM smtc_store[] = { +#define STORE(name, _dummy, func_table) \ + { name, "provider=smtc", (func_table) }, + +#include "../stores.inc" + { NULL, NULL, NULL } +#undef STORE +}; + static const OSSL_ALGORITHM *smtc_query(void *provctx, int operation_id, int *no_cache) { @@ -390,35 +474,113 @@ static const OSSL_ALGORITHM *smtc_query(void *provctx, int operation_id, return smtc_asym_cipher; case OSSL_OP_KEM: return smtc_asym_kem; + case OSSL_OP_ENCODER: + return smtc_encoder; case OSSL_OP_DECODER: return smtc_decoder; + case OSSL_OP_STORE: + return smtc_store; } return NULL; } +static void smtc_teardown(void *provctx) +{ + 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_STATUS, (void (*)(void))smtc_status }, + { 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; + BIO_METHOD *corebiometh = NULL; + OSSL_LIB_CTX *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; + + if ((corebiometh = ossl_bio_prov_init_bio_method()) == NULL) + goto err; + + /* + * 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. + */ + libctx = (OSSL_LIB_CTX *)c_internal_get_libctx(handle); + + ossl_prov_ctx_set0_libctx(*provctx, libctx); + ossl_prov_ctx_set0_handle(*provctx, handle); + ossl_prov_ctx_set0_core_bio_method(*provctx, corebiometh); + + *out = intern_dispatch_table; + return 1; + +err: + BIO_meth_free(corebiometh); + smtc_intern_teardown(*provctx); + *provctx = NULL; + OSSL_LIB_CTX_free(libctx); + return 0; +} + +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 +588,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 +648,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 +675,48 @@ int OSSL_provider_init_int(const OSSL_CORE_HANDLE *handle, goto err; } + ossl_prov_cache_exported_algorithms(smtc_ciphers, exported_ciphers); + + if (fgbl->selftest_params.syslog && atoi(fgbl->selftest_params.syslog) != 0) + OSSL_enable_syslog(); + + OSSL_syslog(LOG_INFO, "[SMTC] SMTC module init\n"); + + if (!SELF_TEST_post(&fgbl->selftest_params, 0)) { + OSSL_TRACE(SMTC, "SELF_TEST_post failed\n"); + ERR_raise(ERR_LIB_PROV, PROV_R_SELF_TEST_POST_FAILURE); + goto err; + } + + pub_drbg = RAND_get0_public(libctx); + if (pub_drbg == NULL) + goto err; + + pri_drbg = RAND_get0_private(libctx); + if (pri_drbg == NULL) + goto err; + + params[0] = OSSL_PARAM_construct_uint(OSSL_DRBG_PARAM_RESEED_REQUESTS, + &reseed_interval); + params[1] = OSSL_PARAM_construct_time_t( + OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL, + &reseed_time_interval); + params[2] = OSSL_PARAM_construct_end(); + + if (!EVP_RAND_CTX_set_params(pub_drbg, params) + || !EVP_RAND_CTX_set_params(pri_drbg, params)) + goto err; + ossl_prov_ctx_set0_libctx(*provctx, libctx); ossl_prov_ctx_set0_handle(*provctx, handle); ossl_prov_ctx_set0_core_bio_method(*provctx, corebiometh); *out = smtc_dispatch_table; - ossl_prov_cache_exported_algorithms(smtc_ciphers, exported_ciphers); + return 1; err: - smtc_intern_teardown(*provctx); + BIO_meth_free(corebiometh); + smtc_teardown(*provctx); *provctx = NULL; OSSL_LIB_CTX_free(libctx); return 0; diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c index 2b449e1bc..b7598056c 100644 --- a/ssl/t1_enc.c +++ b/ssl/t1_enc.c @@ -547,6 +547,13 @@ int tls1_setup_key_block(SSL *s) goto err; } +#if defined(SMTC_MODULE) && !defined(OPENSSL_NO_NTLS) + if (SSL_IS_NTLS(s) && (s->options & SSL_OP_NO_TICKET) + && (s->ctx->session_cache_mode == SSL_SESS_CACHE_OFF)) { + OPENSSL_cleanse(s->session->master_key, s->session->master_key_length); + } +#endif + OSSL_TRACE_BEGIN(TLS) { BIO_printf(trc_out, "key block\n"); BIO_dump_indent(trc_out, p, num, 4); diff --git a/test/build.info b/test/build.info index 6d53ee12f..a03023f4a 100644 --- a/test/build.info +++ b/test/build.info @@ -59,7 +59,7 @@ IF[{- !$disabled{tests} -}] context_internal_test aesgcmtest params_test evp_pkey_dparams_test \ keymgmt_internal_test hexstr_test provider_status_test defltfips_test \ bio_readbuffer_test user_property_test pkcs7_test upcallstest \ - provfetchtest prov_config_test rand_test babasslapitest + provfetchtest prov_config_test rand_test babasslapitest tsapi_test IF[{- !$disabled{'deprecated-3.0'} -}] PROGRAMS{noinst}=enginetest @@ -580,6 +580,10 @@ IF[{- !$disabled{tests} -}] INCLUDE[cmp_client_test]=.. ../include ../apps/include DEPEND[cmp_client_test]=../libcrypto.a libtestutil.a + SOURCE[tsapi_test]=tsapi_test.c + INCLUDE[tsapi_test]=.. ../include ../apps/include + DEPEND[tsapi_test]=../libcrypto.a libtestutil.a + # Internal test programs. These are essentially a collection of internal # test routines. Some of them need to reach internal symbols that aren't # available through the shared library (at least on Linux and Windows diff --git a/test/recipes/00-prep_smtc_cnf.t b/test/recipes/00-prep_smtc_cnf.t index d32104921..004fed298 100644 --- a/test/recipes/00-prep_smtc_cnf.t +++ b/test/recipes/00-prep_smtc_cnf.t @@ -30,7 +30,6 @@ my $smtcconf = bldtop_file('test', 'smtcmodule.cnf'); plan tests => 1; # Create the smtc conf file -ok(run(app(['openssl', 'mod', - '-module', $bin, '-provider_name', 'smtc', '-no_pass', - '-section_name', 'smtc_sect', '-out', $smtcconf])), - "smtc install"); +ok(run(app(['openssl', 'mod', '-install', '-no_verify', '-no_auth', + '-no_rand_poweron_test', '-module', $bin, '-out', $smtcconf])), + "smtc install"); diff --git a/test/recipes/20-test_cli_smtc.t b/test/recipes/20-test_cli_smtc.t index 6996c3084..3141e5449 100644 --- a/test/recipes/20-test_cli_smtc.t +++ b/test/recipes/20-test_cli_smtc.t @@ -27,7 +27,7 @@ plan skip_all => "Test only supported in a smtc build" plan tests => 9; my $defaultconf = srctop_file("test", "default.cnf"); -my $smtcconf = srctop_file("test", "smtc-and-base.cnf"); +my $smtcconf = srctop_file("test", "smtc.cnf"); my $tbs_data = abs_path(bldtop_file('apps', 'openssl' . platform->binext())); my $bogus_data = $smtcconf; diff --git a/test/recipes/20-test_mod.t b/test/recipes/20-test_mod.t index 92876338a..f1a2a1c3a 100644 --- a/test/recipes/20-test_mod.t +++ b/test/recipes/20-test_mod.t @@ -19,6 +19,6 @@ setup("test_mod"); plan skip_all => "Test only supported in a smtc build" if disabled("smtc"); plan tests => 1; -$ENV{OPENSSL_CONF} = abs_path(srctop_file("test", "smtc-and-base.cnf")); +$ENV{OPENSSL_CONF} = abs_path(srctop_file("test", "smtc.cnf")); ok(run(app(['openssl', 'mod', '-test'])), "mod self test"); diff --git a/test/recipes/80-test_ssl_new.t b/test/recipes/80-test_ssl_new.t index edb42c3a3..3186ae31f 100644 --- a/test/recipes/80-test_ssl_new.t +++ b/test/recipes/80-test_ssl_new.t @@ -203,7 +203,7 @@ sub test_conf { "running ssl_test $conf"); } elsif ($provider eq "smtc") { ok(run(test(["ssl_test", $output_file, $provider, - srctop_file("test", "smtc-and-base.cnf")])), + srctop_file("test", "smtc.cnf")])), "running ssl_test $conf"); } else { ok(run(test(["ssl_test", $output_file, $provider])), diff --git a/test/recipes/92-test_tsapi.t b/test/recipes/92-test_tsapi.t new file mode 100644 index 000000000..ba7bb0e0e --- /dev/null +++ b/test/recipes/92-test_tsapi.t @@ -0,0 +1,22 @@ +#! /usr/bin/env perl +# 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 + +use OpenSSL::Test qw/:DEFAULT srctop_file/; +use OpenSSL::Test::Simple; +use OpenSSL::Test::Utils; + +setup("test_tsapi"); + +my $no_smtc = disabled('smtc') || disabled('smtc-debug'); + +if (!$no_smtc) { + my $smtcconf = srctop_file("test", "smtc.cnf"); + $ENV{OPENSSL_CONF} = $smtcconf; +} + +simple_test("test_tsapi", "tsapi_test"); diff --git a/test/smtc-and-base.cnf b/test/smtc.cnf similarity index 82% rename from test/smtc-and-base.cnf rename to test/smtc.cnf index 4149104d4..c63fd0b03 100644 --- a/test/smtc-and-base.cnf +++ b/test/smtc.cnf @@ -9,9 +9,8 @@ config_diagnostics = 1 providers = provider_sect [provider_sect] +inner-smtc = inner_smtc_sect smtc = smtc_sect -base = base_sect -[base_sect] +[inner_smtc_sect] activate = 1 - diff --git a/test/tsapi_test.c b/test/tsapi_test.c new file mode 100644 index 000000000..1c3dabb26 --- /dev/null +++ b/test/tsapi_test.c @@ -0,0 +1,484 @@ +/* + * 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 +#include +#include +#include +#include +#include "testutil.h" +#include "../crypto/sdf/sdf_local.h" +#ifdef SDF_LIB +# include "sdfe_api.h" +#endif + +static int test_TSAPI_Version(void) +{ + char *version = TSAPI_Version(); + + if (!TEST_ptr(version)) + return 0; + + OPENSSL_free(version); + return 1; +} + +static int test_TSAPI_RandBytes(void) +{ + int ret = 0; + size_t len = 32; + unsigned char *buf1 = NULL; + unsigned char *buf2 = NULL; + + buf1 = TSAPI_RandBytes(len); + if (!TEST_ptr(buf1)) + goto end; + + buf2 = TSAPI_RandBytes(len); + if (!TEST_ptr(buf2)) + goto end; + + if (!TEST_mem_ne(buf1, len, buf2, len)) + goto end; + + ret = 1; +end: + OPENSSL_free(buf1); + OPENSSL_free(buf2); + return ret; +} + +#ifndef OPENSSL_NO_SM2 +static int test_TSAPI_SM2Keygen(void) +{ + int ok = 0; + EVP_PKEY *key = NULL, *pubkey = NULL; + unsigned char *sig = NULL; + const char *input = "test"; + size_t siglen; + BIO *tmpbio = NULL; + + key = TSAPI_SM2Keygen(); + if (!TEST_ptr(key)) + return 0; + + tmpbio = BIO_new(BIO_s_mem()); + if (!TEST_ptr(tmpbio)) + goto end; + + if (!TEST_true(PEM_write_bio_PUBKEY(tmpbio, key))) + goto end; + + pubkey = PEM_read_bio_PUBKEY(tmpbio, NULL, NULL, NULL); + if (!TEST_ptr(pubkey)) + goto end; + + sig = TSAPI_SM2Sign(key, (const unsigned char *)input, strlen(input), + &siglen); + if (!TEST_ptr(sig)) + goto end; + + if (!TEST_true(TSAPI_SM2Verify(pubkey, (const unsigned char *)input, + strlen(input), sig, siglen))) + goto end; + + ok = 1; +end: + BIO_free(tmpbio); + OPENSSL_free(sig); + EVP_PKEY_free(pubkey); + EVP_PKEY_free(key); + return ok; +} + +static int test_TSAPI_SM2Sign(void) +{ + int ok = 0; + EVP_PKEY *key = NULL; + const char *input = "test"; + unsigned char *sig = NULL; + size_t siglen; + + key = TSAPI_SM2Keygen(); + if (!TEST_ptr(key)) + return 0; + + sig = TSAPI_SM2Sign(key, (const unsigned char *)input, strlen(input), + &siglen); + if (!TEST_ptr(sig) || !TEST_true(siglen > 0)) + goto end; + + ok = 1; +end: + OPENSSL_free(sig); + EVP_PKEY_free(key); + return ok; +} + +static int test_TSAPI_SM2Verify(void) +{ + int ok = 0; + EVP_PKEY *key = NULL; + BIO *bio = NULL; + const char *pem = "-----BEGIN PUBLIC KEY-----\n" +"MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEOToq2eJ+Q6yqq4WhnTuFWR4UQGFX\n" +"F1rd03v3f/DK+e03/POotPVcA4UjJh/KZjav5qevoqFIKmBvXLOhiy4qHg==\n" +"-----END PUBLIC KEY-----"; + const char *input = "hello world"; + unsigned char sig[] = { + 0x30, 0x45, 0x02, 0x20, 0x6b, 0xa1, 0x2c, 0x29, 0xaf, 0x6a, 0x4d, 0xe7, + 0x6d, 0xb0, 0x85, 0xa1, 0xd3, 0x5f, 0xfa, 0x1d, 0x00, 0x77, 0xfc, 0x6a, + 0x13, 0xe4, 0xac, 0x1b, 0x64, 0xe6, 0x82, 0x9e, 0x34, 0x89, 0x71, 0xfb, + 0x02, 0x21, 0x00, 0xcb, 0xfe, 0xab, 0xc6, 0xcb, 0x61, 0x2d, 0x25, 0xe9, + 0x0a, 0xdc, 0x71, 0xde, 0xe3, 0x9a, 0xdb, 0xfa, 0xcf, 0x62, 0x4e, 0x5a, + 0xa9, 0x4b, 0x8d, 0xac, 0x7c, 0x7b, 0xa8, 0x4b, 0x7b, 0x77, 0x9c,}; + size_t siglen = sizeof(sig); + + bio = BIO_new_mem_buf(pem, -1); + if (!TEST_ptr(bio)) + return 0; + + key = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL); + if (!TEST_ptr(key)) + goto end; + + if (!TEST_true(TSAPI_SM2Verify(key, (const unsigned char *)input, + strlen(input), sig, siglen))) + goto end; + + ok = 1; +end: + BIO_free(bio); + EVP_PKEY_free(key); + return ok; +} + +static int test_TSAPI_SM2Encrypt(void) +{ + int ok = 0; + EVP_PKEY *key = NULL; + BIO *bio = NULL; + const char *pem = "-----BEGIN PUBLIC KEY-----\n" +"MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEOToq2eJ+Q6yqq4WhnTuFWR4UQGFX\n" +"F1rd03v3f/DK+e03/POotPVcA4UjJh/KZjav5qevoqFIKmBvXLOhiy4qHg==\n" +"-----END PUBLIC KEY-----"; + const char *input = "test"; + unsigned char *out = NULL; + size_t outlen; + + bio = BIO_new_mem_buf(pem, -1); + if (!TEST_ptr(bio)) + return 0; + + key = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL); + if (!TEST_ptr(key)) + goto end; + + out = TSAPI_SM2Encrypt(key, (const unsigned char *)input, strlen(input), + &outlen); + if (!TEST_ptr(out) + || !TEST_true(outlen > 0)) + goto end; + + ok = 1; +end: + BIO_free(bio); + EVP_PKEY_free(key); + OPENSSL_free(out); + return ok; +} + +# ifdef SDF_LIB +static int bitmap_is_inuse(uint64_t *pu64, int32_t index) +{ + + int32_t pos, offset; + uint64_t mask; + + mask = 0x1ull; + + pos = index >> 6; + offset = (63 - (index & 0x3f)); + mask <<= offset; + + return (pu64[pos] & mask) ? 1 : 0; +} +# endif + +static int test_TSAPI_SM2Decrypt(void) +{ + int ok = 0; +# ifdef SDF_LIB + void *hDeviceHandle = NULL; + void *hSessionHandle = NULL; + sdfe_login_arg_t login_arg; + OSSL_ECCrefPrivateKey *privkey = NULL; + OSSL_ECCrefPublicKey *pubkey = NULL; + sdfe_bitmap_t bitmap; + sdfe_asym_key_ecc_t asym; + OSSL_ECCCipher *pECCCipher = NULL; + uint32_t cnt, i; + int index = -1; + unsigned char out[256]; + unsigned int outlen = sizeof(out); +# else + unsigned char *out = NULL; + size_t outlen; +# endif + EVP_PKEY *key = NULL; + BIO *bio = NULL; + const char *pem = "-----BEGIN PRIVATE KEY-----\n" +"MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQg0JFWczAXva2An9m7\n" +"2MaT9gIwWTFptvlKrxyO4TjMmbWhRANCAAQ5OirZ4n5DrKqrhaGdO4VZHhRAYVcX\n" +"Wt3Te/d/8Mr57Tf886i09VwDhSMmH8pmNq/mp6+ioUgqYG9cs6GLLioe\n" +"-----END PRIVATE KEY-----"; + unsigned char in[] = { + 0x30, 0x81, 0x8A, 0x02, 0x20, 0x46, 0x6B, 0xE2, 0xEF, 0x5C, 0x11, 0x78, + 0x2E, 0xC7, 0x78, 0x64, 0xA0, 0x05, 0x54, 0x17, 0xF4, 0x07, 0xA5, 0xAF, + 0xC1, 0x1D, 0x65, 0x3C, 0x6B, 0xCE, 0x69, 0xE4, 0x17, 0xBB, 0x1D, 0x05, + 0xB6, 0x02, 0x20, 0x62, 0xB5, 0x72, 0xE2, 0x1F, 0xF0, 0xDD, 0xF5, 0xC7, + 0x26, 0xBD, 0x3F, 0x9F, 0xF2, 0xEA, 0xE5, 0x6E, 0x62, 0x94, 0x71, 0x3A, + 0x60, 0x7E, 0x9B, 0x95, 0x25, 0x62, 0x89, 0x65, 0xF6, 0x2C, 0xC8, 0x04, + 0x20, 0x3C, 0x1B, 0x57, 0x13, 0xB5, 0xDB, 0x27, 0x28, 0xEB, 0x7B, 0xF7, + 0x75, 0xE4, 0x4F, 0x46, 0x89, 0xFC, 0x32, 0x66, 0x8B, 0xDC, 0x56, 0x4F, + 0x52, 0xEA, 0x45, 0xB0, 0x9E, 0x8D, 0xF2, 0xA5, 0xF4, 0x04, 0x22, 0x08, + 0x4A, 0x9D, 0x0C, 0xC2, 0x99, 0x70, 0x92, 0xB7, 0xD3, 0xC4, 0x04, 0xFC, + 0xE9, 0x59, 0x56, 0xEB, 0x60, 0x4D, 0x73, 0x2B, 0x23, 0x07, 0xA8, 0xE5, + 0xB8, 0x90, 0x0E, 0xD6, 0x60, 0x8C, 0xA5, 0xB1, 0x97,}; + const char *expected = "The floofy bunnies hop at midnight"; + + bio = BIO_new_mem_buf(pem, -1); + if (!TEST_ptr(bio)) + return 0; + + key = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL); + if (!TEST_ptr(key)) + goto end; + +# ifdef SDF_LIB + memset(&login_arg, 0, sizeof(login_arg)); + + strcpy((char *)login_arg.name, "admin"); + login_arg.passwd = (uint8_t *)"123123"; + login_arg.passwd_len = 6; + + if (TSAPI_SDF_OpenDevice(&hDeviceHandle) != OSSL_SDR_OK) + goto end; + + if (TSAPI_SDF_OpenSession(hDeviceHandle, &hSessionHandle) != OSSL_SDR_OK) + goto end; + + if (SDFE_LoginUsr(hSessionHandle, &login_arg) != OSSL_SDR_OK) + goto end; + + bitmap.start = 0; + bitmap.cnt = SDFE_BITMAP_U64_MAX_CNT; + if (SDFE_BitmapAsymKey(hSessionHandle, SDFE_ASYM_KEY_AREA_ENC, + SDFE_ASYM_KEY_TYPE_SM2, &bitmap) != OSSL_SDR_OK) + goto end; + + cnt = bitmap.cnt << 6; + for(i = 0; i < cnt; i++){ + if(!bitmap_is_inuse(bitmap.bitmap, i)) { + index = i; + break; + } + } + + if (index < 0) + goto end; + + asym.area = SDFE_ASYM_KEY_AREA_ENC; + asym.index = index; + asym.type = SDFE_ASYM_KEY_TYPE_SM2; + asym.privkey_bits = 256; + asym.privkey_len = asym.privkey_bits >> 3; + asym.pubkey_bits = 256; + asym.pubkey_len = (asym.pubkey_bits >> 3) << 1; + + pubkey = TSAPI_EVP_PKEY_get_ECCrefPublicKey(key); + if (!TEST_ptr(pubkey)) + goto end; + + privkey = TSAPI_EVP_PKEY_get_ECCrefPrivateKey(key); + if (!TEST_ptr(privkey)) + goto end; + + memcpy(asym.pubkey, pubkey, sizeof(*pubkey)); + memcpy(asym.privkey, privkey, sizeof(*privkey)); + + if (SDFE_ImportECCKey(hSessionHandle, &asym, NULL) != OSSL_SDR_OK) + goto end; + + if (TSAPI_SDF_GetPrivateKeyAccessRight(hSessionHandle, index, NULL, 0) + != OSSL_SDR_OK) + goto end; + + pECCCipher = TSAPI_SM2Ciphertext_to_ECCCipher(in, sizeof(in)); + + if (TSAPI_SDF_InternalDecrypt_ECC(hSessionHandle, index, pECCCipher, + out, &outlen) != OSSL_SDR_OK) + goto end; +# else + out = TSAPI_SM2Decrypt(key, in, sizeof(in), &outlen); + if (!TEST_ptr(out)) + goto end; +# endif + + if (!TEST_true(outlen == strlen(expected)) + || !TEST_mem_eq(out, outlen, expected, strlen(expected))) + goto end; + + ok = 1; +end: + BIO_free(bio); + EVP_PKEY_free(key); +# ifdef SDF_LIB + OPENSSL_free(pubkey); + OPENSSL_free(privkey); + OPENSSL_free(pECCCipher); + (void)SDFE_DelECCKey(hSessionHandle, asym.area, index); + TSAPI_SDF_CloseSession(hSessionHandle); + TSAPI_SDF_CloseDevice(hDeviceHandle); +# else + OPENSSL_free(out); +# endif + return ok; +} +#endif + +#ifndef OPENSSL_NO_SM4 +static int test_TSAPI_SM4Encrypt(void) +{ + unsigned char key[] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + }; + unsigned char iv[] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + }; + unsigned char in[] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, + 0x76, 0x54, 0x32, 0x10, 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + }; + unsigned char expected[] = { + 0x26, 0x77, 0xF4, 0x6B, 0x09, 0xC1, 0x22, 0xCC, 0x97, 0x55, 0x33, 0x10, + 0x5B, 0xD4, 0xA2, 0x2A, 0xF6, 0x12, 0x5F, 0x72, 0x75, 0xCE, 0x55, 0x2C, + 0x3A, 0x2B, 0xBC, 0xF5, 0x33, 0xDE, 0x8A, 0x3B, + }; + unsigned char *out = NULL; + size_t outlen; + + out = TSAPI_SM4Encrypt(OSSL_SGD_MODE_CBC, key, sizeof(key), -1, iv, in, + sizeof(in), &outlen); + if (!TEST_ptr(out)) + return 0; + + if (!TEST_mem_eq(out, outlen, expected, sizeof(expected))) { + OPENSSL_free(out); + return 0; + } + + OPENSSL_free(out); + return 1; +} + +static int test_TSAPI_SM4Decrypt(void) +{ + unsigned char key[] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + }; + unsigned char iv[] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + }; + unsigned char in[] = { + 0x26, 0x77, 0xF4, 0x6B, 0x09, 0xC1, 0x22, 0xCC, 0x97, 0x55, 0x33, 0x10, + 0x5B, 0xD4, 0xA2, 0x2A, 0xF6, 0x12, 0x5F, 0x72, 0x75, 0xCE, 0x55, 0x2C, + 0x3A, 0x2B, 0xBC, 0xF5, 0x33, 0xDE, 0x8A, 0x3B, + }; + unsigned char expected[] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, + 0x76, 0x54, 0x32, 0x10, 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + }; + unsigned char *out = NULL; + size_t outlen; + + out = TSAPI_SM4Decrypt(OSSL_SGD_MODE_CBC, key, sizeof(key), -1, iv, in, + sizeof(in), &outlen); + if (!TEST_ptr(out)) + return 0; + + if (!TEST_mem_eq(out, outlen, expected, sizeof(expected))) { + OPENSSL_free(out); + return 0; + } + + OPENSSL_free(out); + return 1; +} +#endif + +#ifndef OPENSSL_NO_SM3 +static int test_TSAPI_SM3(void) +{ + unsigned char in[] = { + 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, + 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, + 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, + 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, + 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, + 0x61, 0x62, 0x63, 0x64, + }; + unsigned char expected[] = { + 0xDE, 0xBE, 0x9F, 0xF9, 0x22, 0x75, 0xB8, 0xA1, 0x38, 0x60, 0x48, 0x89, + 0xC1, 0x8E, 0x5A, 0x4D, 0x6F, 0xDB, 0x70, 0xE5, 0x38, 0x7E, 0x57, 0x65, + 0x29, 0x3d, 0xCb, 0xA3, 0x9C, 0x0C, 0x57, 0x32, + }; + size_t outlen; + unsigned char *out = TSAPI_SM3(in, sizeof(in), &outlen); + + if (!TEST_ptr(out)) + return 0; + + if (!TEST_mem_eq(out, outlen, expected, sizeof(expected))) { + OPENSSL_free(out); + return 0; + } + + OPENSSL_free(out); + return 1; +} +#endif + +int setup_tests(void) +{ + ADD_TEST(test_TSAPI_Version); + ADD_TEST(test_TSAPI_RandBytes); +#ifndef OPENSSL_NO_SM2 + ADD_TEST(test_TSAPI_SM2Keygen); + ADD_TEST(test_TSAPI_SM2Sign); + ADD_TEST(test_TSAPI_SM2Verify); + ADD_TEST(test_TSAPI_SM2Encrypt); + ADD_TEST(test_TSAPI_SM2Decrypt); +#endif +#ifndef OPENSSL_NO_SM4 + ADD_TEST(test_TSAPI_SM4Encrypt); + ADD_TEST(test_TSAPI_SM4Decrypt); +#endif +#ifndef OPENSSL_NO_SM3 + ADD_TEST(test_TSAPI_SM3); +#endif + + return 1; +} diff --git a/util/libcrypto.num b/util/libcrypto.num index 68c6edbf5..2602396b4 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -5643,3 +5643,57 @@ PKCS12_create_ex2 5958 3_0_3 EXIST::FUNCTION: ASN1_item_unpack_ex 5960 3_0_3 EXIST::FUNCTION: PKCS12_SAFEBAG_get1_cert_ex 5961 3_0_3 EXIST::FUNCTION: PKCS12_SAFEBAG_get1_crl_ex 5962 3_0_3 EXIST::FUNCTION: +RAND_set_entropy_source 5963 3_0_3 EXIST::FUNCTION: +TSAPI_SDF_OpenDevice 5964 3_0_3 EXIST::FUNCTION: +TSAPI_SDF_CloseDevice 5965 3_0_3 EXIST::FUNCTION: +TSAPI_SDF_OpenSession 5966 3_0_3 EXIST::FUNCTION: +TSAPI_SDF_CloseSession 5967 3_0_3 EXIST::FUNCTION: +TSAPI_SDF_ImportKeyWithKEK 5968 3_0_3 EXIST::FUNCTION: +TSAPI_SDF_Encrypt 5969 3_0_3 EXIST::FUNCTION: +TSAPI_SDF_Decrypt 5970 3_0_3 EXIST::FUNCTION: +TSAPI_SDF_CalculateMAC 5971 3_0_3 EXIST::FUNCTION: +OSSL_enable_syslog 5972 3_0_3 EXIST::FUNCTION: +OSSL_disable_syslog 5973 3_0_3 EXIST::FUNCTION: +OSSL_syslog 5974 3_0_3 EXIST::FUNCTION: +TSAPI_SDF_GetPrivateKeyAccessRight 5975 3_0_3 EXIST::FUNCTION: +TSAPI_SDF_ReleasePrivateKeyAccessRight 5976 3_0_3 EXIST::FUNCTION: +TSAPI_SDF_ImportKeyWithISK_ECC 5977 3_0_3 EXIST::FUNCTION: +TSAPI_GenerateSM2KeyWithIndex 5978 3_0_3 EXIST::FUNCTION:SM2 +TSAPI_SDF_GenerateKey 5979 3_0_3 EXIST::FUNCTION: +TSAPI_SDF_DestroyKey 5980 3_0_3 EXIST::FUNCTION: +TSAPI_DelSm2KeyWithIndex 5981 3_0_3 EXIST::FUNCTION:SM2 +TSAPI_UpdateSm2KeyWithIndex 5982 3_0_3 EXIST::FUNCTION:SM2 +TSAPI_ExportSM2PubKeyWithIndex 5983 3_0_3 EXIST::FUNCTION:SM2 +TSAPI_SDF_ExportSignPublicKey_ECC 5984 3_0_3 EXIST::FUNCTION: +TSAPI_ImportSM2KeyWithEvlp 5985 3_0_3 EXIST::FUNCTION:SM2 +TSAPI_ExportSM2KeyWithEvlp 5986 3_0_3 EXIST::FUNCTION:SM2 +TSAPI_SM2Encrypt 5987 3_0_3 EXIST::FUNCTION:SM2 +TSAPI_EVP_PKEY_new_from_ECCrefKey 5988 3_0_3 EXIST::FUNCTION:SM2 +TSAPI_EVP_PKEY_get_ECCrefPublicKey 5989 3_0_3 EXIST::FUNCTION:SM2 +TSAPI_EVP_PKEY_get_ECCrefPrivateKey 5990 3_0_3 EXIST::FUNCTION:SM2 +TSAPI_ExportSM2KeyWithIndex 5991 3_0_3 EXIST::FUNCTION:SM2 +TSAPI_SDF_ExportEncPublicKey_ECC 5992 3_0_3 EXIST::FUNCTION: +TSAPI_ImportSM2Key 5993 3_0_3 EXIST::FUNCTION:SM2 +TSAPI_SM3 5994 3_0_3 EXIST::FUNCTION:SM3 +TSAPI_SM2Ciphertext_to_ECCCipher 5995 3_0_3 EXIST::FUNCTION:SM2 +TSAPI_SM4Encrypt 5996 3_0_3 EXIST::FUNCTION:SM4 +TSAPI_SM4Decrypt 5997 3_0_3 EXIST::FUNCTION:SM4 +TSAPI_Version 5998 3_0_3 EXIST::FUNCTION: +TSAPI_RandBytes 5999 3_0_3 EXIST::FUNCTION: +OSSL_PROVIDER_reset 6000 3_0_3 EXIST::FUNCTION: +OSSL_PROVIDER_status 6001 3_0_3 EXIST::FUNCTION: +TSAPI_SDF_InternalEncrypt_ECC 6002 3_0_3 EXIST::FUNCTION: +TSAPI_SDF_InternalDecrypt_ECC 6003 3_0_3 EXIST::FUNCTION: +TSAPI_SDF_InternalSign_ECC 6004 3_0_3 EXIST::FUNCTION: +EVP_PKEY_CTX_new_from_name_provided 6005 3_0_3 EXIST::FUNCTION: +EVP_PKEY_CTX_new_from_pkey_provided 6006 3_0_3 EXIST::FUNCTION: +TSAPI_GetEntropy 6007 3_0_3 EXIST::FUNCTION: +TSAPI_FreeEntropy 6008 3_0_3 EXIST::FUNCTION: +TSAPI_ECCCipher_to_SM2Ciphertext 6009 3_0_3 EXIST::FUNCTION:SM2 +TSAPI_SM2EncryptWithISK 6010 3_0_3 EXIST::FUNCTION:SM2 +TSAPI_SM2DecryptWithISK 6011 3_0_3 EXIST::FUNCTION:SM2 +TSAPI_SM2Keygen 6012 3_0_3 EXIST::FUNCTION:SM2 +TSAPI_SM2Sign 6013 3_0_3 EXIST::FUNCTION:SM2,SM3 +TSAPI_SM2Verify 6014 3_0_3 EXIST::FUNCTION:SM2,SM3 +TSAPI_SM2Decrypt 6015 3_0_3 EXIST::FUNCTION:SM2 +TSAPI_SDF_GenerateRandom 6016 3_0_3 EXIST::FUNCTION: