diff --git a/CMakeLists.txt b/CMakeLists.txt index ce2dcc8a..d89cd52b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -216,10 +216,12 @@ set(src src/rsa.c src/socket.c src/file.c + src/passwd.c ) set(tools tools/gmssl.c + tools/passwd.c tools/version.c # tools/sm4.c tools/sm4_cbc.c @@ -1024,7 +1026,7 @@ endif() # set(CPACK_PACKAGE_NAME "GmSSL") set(CPACK_PACKAGE_VENDOR "GmSSL develop team") -set(CPACK_PACKAGE_VERSION "3.3.0-dev.1172") +set(CPACK_PACKAGE_VERSION "3.3.0-dev.1173") set(CPACK_PACKAGE_DESCRIPTION_FILE ${PROJECT_SOURCE_DIR}/README.md) set(CPACK_NSIS_MODIFY_PATH ON) include(CPack) diff --git a/include/gmssl/passwd.h b/include/gmssl/passwd.h new file mode 100644 index 00000000..3e986500 --- /dev/null +++ b/include/gmssl/passwd.h @@ -0,0 +1,26 @@ +/* + * Copyright 2014-2026 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#ifndef GMSSL_PASSWD_H +#define GMSSL_PASSWD_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +int gmssl_read_password(const char *prompt, char *pass, size_t passlen); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/gmssl/version.h b/include/gmssl/version.h index bddc6cf8..0989552a 100644 --- a/include/gmssl/version.h +++ b/include/gmssl/version.h @@ -18,7 +18,7 @@ extern "C" { #define GMSSL_VERSION_NUM 30300 -#define GMSSL_VERSION_STR "GmSSL 3.3.0-dev.1172" +#define GMSSL_VERSION_STR "GmSSL 3.3.0-dev.1173" int gmssl_version_num(void); const char *gmssl_version_str(void); diff --git a/src/passwd.c b/src/passwd.c new file mode 100644 index 00000000..4079ee47 --- /dev/null +++ b/src/passwd.c @@ -0,0 +1,166 @@ +/* + * Copyright 2014-2026 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include +#include +#include + +#if defined(_WIN32) +#include +#include +#else +#include +#include +#endif + + +static int gmssl_password_read_line(FILE *in, FILE *out, const char *prompt, char *pass, size_t passlen) +{ + size_t len; + int too_long = 0; + int ch; + + if (prompt && prompt[0]) { + fputs(prompt, out); + } else { + fputs("Password: ", out); + } + fflush(out); + + if (!fgets(pass, (int)passlen, in)) { + error_print(); + pass[0] = '\0'; + return -1; + } + + len = strlen(pass); + if (len > 0 && pass[len - 1] == '\n') { + pass[--len] = '\0'; + if (len > 0 && pass[len - 1] == '\r') { + pass[--len] = '\0'; + } + } else if (!feof(in)) { + too_long = 1; + while ((ch = fgetc(in)) != EOF && ch != '\n') { + } + } + + if (too_long) { + gmssl_secure_clear(pass, passlen); + error_print(); + return -1; + } + + return 1; +} + +#if defined(_WIN32) + +int gmssl_read_password(const char *prompt, char *pass, size_t passlen) +{ + FILE *in = NULL; + FILE *out = NULL; + HANDLE in_handle; + DWORD old_mode; + DWORD new_mode; + int ret = -1; + + if (!pass || passlen < 2 || passlen > INT_MAX) { + error_print(); + return -1; + } + pass[0] = '\0'; + + if (!(in = fopen("CONIN$", "r")) || !(out = fopen("CONOUT$", "w"))) { + error_print(); + goto end; + } + + in_handle = (HANDLE)_get_osfhandle(_fileno(in)); + if (in_handle == INVALID_HANDLE_VALUE + || !GetConsoleMode(in_handle, &old_mode)) { + error_print(); + goto end; + } + + new_mode = old_mode & ~ENABLE_ECHO_INPUT; + if (!SetConsoleMode(in_handle, new_mode)) { + error_print(); + goto end; + } + + ret = gmssl_password_read_line(in, out, prompt, pass, passlen); + + if (!SetConsoleMode(in_handle, old_mode)) { + error_print(); + ret = -1; + } + fputc('\n', out); + fflush(out); + +end: + if (in) fclose(in); + if (out) fclose(out); + if (ret != 1 && pass) gmssl_secure_clear(pass, passlen); + return ret; +} + +#else + +int gmssl_read_password(const char *prompt, char *pass, size_t passlen) +{ + FILE *tty = NULL; + int fd; + struct termios old_termios; + struct termios new_termios; + int ret = -1; + + if (!pass || passlen < 2 || passlen > INT_MAX) { + error_print(); + return -1; + } + pass[0] = '\0'; + + if (!(tty = fopen("/dev/tty", "r+"))) { + error_print(); + goto end; + } + + fd = fileno(tty); + if (tcgetattr(fd, &old_termios) < 0) { + error_print(); + goto end; + } + + new_termios = old_termios; + new_termios.c_lflag &= (tcflag_t)~ECHO; + if (tcsetattr(fd, TCSAFLUSH, &new_termios) < 0) { + error_print(); + goto end; + } + + ret = gmssl_password_read_line(tty, tty, prompt, pass, passlen); + + if (tcsetattr(fd, TCSAFLUSH, &old_termios) < 0) { + error_print(); + ret = -1; + } + fputc('\n', tty); + fflush(tty); + +end: + if (tty) fclose(tty); + if (ret != 1 && pass) gmssl_secure_clear(pass, passlen); + return ret; +} + +#endif diff --git a/tools/certgen.c b/tools/certgen.c index b3dd236a..829b5435 100644 --- a/tools/certgen.c +++ b/tools/certgen.c @@ -20,6 +20,7 @@ #include #include #include +#include "passwd.h" static const char *options = @@ -48,7 +49,7 @@ static char *usage = " -days num Validity peroid in days\n" " -key file Private key file in PEM format\n" " -algor str Public key algorithm\n" -" -pass pass Password for decrypting private key file\n" +" -pass pass Password for decrypting private key file, prompt if not given\n" " -sig_alg str Signature algorithm OID name, default sm2sign-with-sm3\n" " -sm2_id str Signer's ID in SM2 signature algorithm\n" " -sm2_id_hex hex Signer's ID in hex format\n" @@ -157,7 +158,9 @@ int certgen_main(int argc, char **argv) // Private Key FILE *keyfp = NULL; + char *keyfile = NULL; char *pass = NULL; + char passbuf[GMSSL_PASSWORD_MAX_SIZE] = {0}; X509_KEY x509_key; int algor = OID_ec_public_key; int sign_algor = OID_sm2sign_with_sm3; @@ -265,6 +268,7 @@ int certgen_main(int argc, char **argv) } else if (!strcmp(*argv, "-key")) { if (--argc < 1) goto bad; str = *(++argv); + keyfile = str; if (!(keyfp = fopen(str, "rb"))) { fprintf(stderr, "%s: open '%s' failure : %s\n", prog, str, strerror(errno)); goto end; @@ -410,9 +414,10 @@ bad: goto end; } if (!pass && algor != OID_ec_public_key) { - fprintf(stderr, "%s: option `-pass` required\n", prog); - printf("usage: gmssl %s %s\n\n", prog, options); - goto end; + if (gmssl_tool_get_password(prog, "Password to decrypt private key", keyfile, &pass, + passbuf, sizeof(passbuf)) != 1) { + goto end; + } } if (x509_private_key_from_file(&x509_key, algor, pass, keyfp) != 1) { fprintf(stderr, "%s: load private key failed\n", prog); @@ -566,6 +571,7 @@ bad: end: x509_key_cleanup(&x509_key); + gmssl_secure_clear(passbuf, sizeof(passbuf)); if (cert) free(cert); if (keyfp) fclose(keyfp); if (outfile && outfp) fclose(outfp); diff --git a/tools/cmsdecrypt.c b/tools/cmsdecrypt.c index d39d03d0..185787dd 100644 --- a/tools/cmsdecrypt.c +++ b/tools/cmsdecrypt.c @@ -13,12 +13,14 @@ #include #include #include +#include #include #include #include +#include "passwd.h" -static const char *options = "-key file -pass str -cert file -in file [-out file]"; +static const char *options = "-key file [-pass str] -cert file -in file [-out file]"; int cmsdecrypt_main(int argc, char **argv) { @@ -26,6 +28,7 @@ int cmsdecrypt_main(int argc, char **argv) char *prog = argv[0]; char *keyfile = NULL; char *pass = NULL; + char passbuf[GMSSL_PASSWORD_MAX_SIZE] = {0}; char *certfile = NULL; char *infile = NULL; char *outfile = NULL; @@ -109,8 +112,8 @@ bad: fprintf(stderr, "%s: '-key' option required\n", prog); goto end; } - if (!pass) { - fprintf(stderr, "%s: '-pass' option required\n", prog); + if (gmssl_tool_get_password(prog, "Password to decrypt private key", keyfile, &pass, + passbuf, sizeof(passbuf)) != 1) { goto end; } if (!certfile) { @@ -177,6 +180,7 @@ bad: ret = 0; end: + gmssl_secure_clear(passbuf, sizeof(passbuf)); if (infile && infp) fclose(infp); if (outfile && outfp) fclose(outfp); if (keyfile && keyfp) fclose(keyfp); diff --git a/tools/cmssign.c b/tools/cmssign.c index 332c08bf..4c32a89a 100644 --- a/tools/cmssign.c +++ b/tools/cmssign.c @@ -13,12 +13,14 @@ #include #include #include +#include #include #include #include +#include "passwd.h" -static const char *options = "-key file -pass str -cert file -in file [-out file]"; +static const char *options = "-key file [-pass str] -cert file -in file [-out file]"; int cmssign_main(int argc, char **argv) { @@ -26,6 +28,7 @@ int cmssign_main(int argc, char **argv) char *prog = argv[0]; char *keyfile = NULL; char *pass = NULL; + char passbuf[GMSSL_PASSWORD_MAX_SIZE] = {0}; char *certfile = NULL; char *infile = NULL; char *outfile = NULL; @@ -104,8 +107,8 @@ bad: fprintf(stderr, "%s: '-key' option required\n", prog); goto end; } - if (!pass) { - fprintf(stderr, "%s: '-pass' option required\n", prog); + if (gmssl_tool_get_password(prog, "Password to decrypt private key", keyfile, &pass, + passbuf, sizeof(passbuf)) != 1) { goto end; } if (!certfile) { @@ -177,6 +180,7 @@ bad: ret = 0; end: + gmssl_secure_clear(passbuf, sizeof(passbuf)); if (infile && infp) fclose(infp); if (outfile && outfp) fclose(outfp); if (keyfile && keyfp) fclose(keyfp); diff --git a/tools/crlgen.c b/tools/crlgen.c index 5741d87f..955acb12 100644 --- a/tools/crlgen.c +++ b/tools/crlgen.c @@ -21,6 +21,7 @@ #include #include #include +#include "passwd.h" static const char *usage = @@ -43,7 +44,7 @@ static const char *options = " revoked_certs.der can be generated by `gmssl certrevoke`\n" " -cacert pem The issuer certificate\n" " -key pem The issuer private key\n" -" -pass pass Password for decrypting private key file\n" +" -pass pass Password for decrypting private key file, prompt if not given\n" " -sig_alg str Signature algorithm OID name, default sm2sign-with-sm3\n" " -sm2_id str Authority's ID in SM2 signature algorithm\n" " -sm2_id_hex hex Authority's ID in hex format\n" @@ -78,7 +79,9 @@ int crlgen_main(int argc, char **argv) uint8_t *cacert = NULL; size_t cacert_len = 0; FILE *keyfp = NULL; + char *keyfile = NULL; char *pass = NULL; + char passbuf[GMSSL_PASSWORD_MAX_SIZE] = {0}; X509_KEY x509_key; X509_KEY x509_pub; char signer_id[SM2_MAX_ID_LENGTH + 1] = {0}; @@ -137,6 +140,7 @@ int crlgen_main(int argc, char **argv) } else if (!strcmp(*argv, "-key")) { if (--argc < 1) goto bad; str = *(++argv); + keyfile = str; if (!(keyfp = fopen(str, "rb"))) { fprintf(stderr, "%s: open '%s' failure : %s\n", prog, str, strerror(errno)); goto end; @@ -255,9 +259,10 @@ bad: } if (!pass && x509_pub.algor == OID_ec_public_key) { - fprintf(stderr, "usage: gmssl %s %s\n", prog, usage); - fprintf(stderr, "%s: `-pass` option required\n", prog); - goto end; + if (gmssl_tool_get_password(prog, "Password to decrypt private key", keyfile, &pass, + passbuf, sizeof(passbuf)) != 1) { + goto end; + } } if (x509_private_key_from_file(&x509_key, x509_pub.algor, pass, keyfp) != 1) { fprintf(stderr, "%s: load private key failure\n", prog); @@ -343,6 +348,7 @@ bad: end: x509_key_cleanup(&x509_key); + gmssl_secure_clear(passbuf, sizeof(passbuf)); if (revoked_certs) free(revoked_certs); if (keyfp) fclose(keyfp); if (cacert) free(cacert); diff --git a/tools/ocspsign.c b/tools/ocspsign.c index 2f33e777..ff3fa747 100644 --- a/tools/ocspsign.c +++ b/tools/ocspsign.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -20,6 +21,7 @@ #include #include #include +#include "passwd.h" #define OCSP_RESPONSE_MAX_SIZE 131072 @@ -42,7 +44,7 @@ static const char *help = " -cacert pem Issuer CA certificate of the requested certificate\n" " -signer pem OCSPResponse signer certificate\n" " -key pem OCSPResponse signer private key\n" -" -pass pass Password for decrypting private key file\n" +" -pass pass Password for decrypting private key file, prompt if not given\n" " -status status Certificate status: good, revoked or unknown, default good\n" " -sig_alg str Signature algorithm OID name, default sm2sign-with-sm3\n" " -revocation_time time Revocation time, required when status is revoked\n" @@ -166,6 +168,7 @@ int ocspsign_main(int argc, char **argv) FILE *cacertfp = NULL; FILE *signerfp = NULL; char *pass = NULL; + char passbuf[GMSSL_PASSWORD_MAX_SIZE] = {0}; char *str; int verbose = 0; @@ -403,8 +406,10 @@ bad: goto end; } if (!pass && signer_pub.algor == OID_ec_public_key) { - fprintf(stderr, "%s: `-pass` option required\n", prog); - goto end; + if (gmssl_tool_get_password(prog, "Password to decrypt private key", keyfile, &pass, + passbuf, sizeof(passbuf)) != 1) { + goto end; + } } if (x509_private_key_from_file(&sign_key, signer_pub.algor, pass, keyfp) != 1) { fprintf(stderr, "%s: load signer private key failure\n", prog); @@ -490,6 +495,7 @@ bad: ret = 0; end: + gmssl_secure_clear(passbuf, sizeof(passbuf)); if (keyfp) fclose(keyfp); if (cacertfp) fclose(cacertfp); if (signerfp) fclose(signerfp); diff --git a/tools/p256keygen.c b/tools/p256keygen.c index 02ad3617..5db54713 100644 --- a/tools/p256keygen.c +++ b/tools/p256keygen.c @@ -14,14 +14,15 @@ #include #include #include +#include "passwd.h" -static const char *usage = "-pass str [-out pem] [-pubout pem]\n"; +static const char *usage = "[-pass str] [-out pem] [-pubout pem]\n"; static const char *options = "Options\n" "\n" -" -pass pass Password to encrypt the private key\n" +" -pass pass Password to encrypt the private key, prompt if not given\n" " -out pem Output password-encrypted PKCS #8 private key in PEM format\n" " -pubout pem Output public key in PEM format\n" " -export pem Output non-encrypted PKCS#8 private key in PEM format\n" @@ -37,6 +38,7 @@ int p256keygen_main(int argc, char **argv) int ret = 1; char *prog = argv[0]; char *pass = NULL; + char passbuf[GMSSL_PASSWORD_MAX_SIZE] = {0}; char *outfile = NULL; char *puboutfile = NULL; char *exportfile = NULL; @@ -96,8 +98,8 @@ bad: argv++; } - if (!pass) { - fprintf(stderr, "gmssl %s: `-pass` option required\n", prog); + if (gmssl_tool_get_password(prog, "Password to encrypt private key", outfile, &pass, + passbuf, sizeof(passbuf)) != 1) { goto end; } @@ -124,6 +126,7 @@ bad: end: gmssl_secure_clear(&key, sizeof(key)); + gmssl_secure_clear(passbuf, sizeof(passbuf)); if (outfile && outfp) fclose(outfp); if (puboutfile && puboutfp) fclose(puboutfp); return ret; diff --git a/tools/passwd.c b/tools/passwd.c new file mode 100644 index 00000000..0435d6f4 --- /dev/null +++ b/tools/passwd.c @@ -0,0 +1,50 @@ +/* + * Copyright 2014-2026 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include "passwd.h" + + +int gmssl_tool_read_password(const char *prog, const char *label, + const char *file, char *pass, size_t passlen) +{ + char prompt[512]; + int len; + + if (!prog) prog = "gmssl"; + if (!label) label = "Password"; + + if (file && file[0]) { + len = snprintf(prompt, sizeof(prompt), "gmssl %s: %s '%s': ", prog, label, file); + } else { + len = snprintf(prompt, sizeof(prompt), "gmssl %s: %s: ", prog, label); + } + if (len < 0 || len >= (int)sizeof(prompt)) { + return -1; + } + + return gmssl_read_password(prompt, pass, passlen); +} + +int gmssl_tool_get_password(const char *prog, const char *label, + const char *file, char **pass, char *passbuf, size_t passlen) +{ + if (!pass || !passbuf) { + return -1; + } + if (*pass) { + return 1; + } + if (gmssl_tool_read_password(prog, label, file, passbuf, passlen) != 1) { + return -1; + } + *pass = passbuf; + return 1; +} diff --git a/tools/passwd.h b/tools/passwd.h new file mode 100644 index 00000000..21080d8e --- /dev/null +++ b/tools/passwd.h @@ -0,0 +1,31 @@ +/* + * Copyright 2014-2026 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#ifndef GMSSL_TOOL_PASSWD_H +#define GMSSL_TOOL_PASSWD_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +#define GMSSL_PASSWORD_MAX_SIZE 256 + +int gmssl_tool_read_password(const char *prog, const char *label, + const char *file, char *pass, size_t passlen); +int gmssl_tool_get_password(const char *prog, const char *label, + const char *file, char **pass, char *passbuf, size_t passlen); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/tools/quic_server.c b/tools/quic_server.c index 5183fd59..b5be8b7a 100644 --- a/tools/quic_server.c +++ b/tools/quic_server.c @@ -10,10 +10,12 @@ #include #include #include +#include #include #include #include #include +#include "passwd.h" int tls13_generate_application_secrets(TLS_CONNECT *conn); int tls13_generate_client_application_keys(TLS_CONNECT *conn); @@ -28,7 +30,7 @@ static const char *help = " -port num Listening UDP port number, default 443\n" " -cert pem Server's certificate chain in PEM format\n" " -key pem Server's encrypted private key in PEM format\n" -" -pass str Password to decrypt private key\n" +" -pass str Password to decrypt private key, prompt if not given\n" " -cipher_suite str TLS 1.3 cipher suite, default TLS_AES_128_GCM_SHA256 and TLS_AES_128_CCM_SHA256\n" " -supported_group str Supported elliptic curve, default prime256v1\n" " -sig_alg str Supported signature algorithm, default ecdsa_secp256r1_sha256\n" @@ -655,6 +657,7 @@ int quic_server_main(int argc, char **argv) char *certfile = NULL; char *keyfile = NULL; char *pass = NULL; + char passbuf[GMSSL_PASSWORD_MAX_SIZE] = {0}; int verbose = 0; TLS_CTX ctx; TLS_CONNECT conn; @@ -770,6 +773,10 @@ bad: fprintf(stderr, "%s: -cert and -key required\n", prog); return 1; } + if (gmssl_tool_get_password(prog, "Password to decrypt private key", keyfile, &pass, + passbuf, sizeof(passbuf)) != 1) { + return 1; + } memset(&ctx, 0, sizeof(ctx)); memset(&conn, 0, sizeof(conn)); @@ -779,7 +786,7 @@ bad: || tls_ctx_set_supported_groups(&ctx, &supported_group, 1) != 1 || tls_ctx_set_signature_algorithms(&ctx, &sig_alg, 1) != 1 || tls_ctx_set_application_layer_protocol_negotiation(&ctx, &alpn, 1) != 1 - || tls_ctx_add_certificate_chain_and_key(&ctx, certfile, keyfile, pass ? pass : "") != 1 + || tls_ctx_add_certificate_chain_and_key(&ctx, certfile, keyfile, pass) != 1 || tls_init(&conn, &ctx) != 1) { error_print(); goto end; @@ -1001,6 +1008,7 @@ bad: } end: + gmssl_secure_clear(passbuf, sizeof(passbuf)); if (tls_socket_is_valid(sock)) { tls_socket_close(sock); } diff --git a/tools/reqgen.c b/tools/reqgen.c index 47c7fdab..1c75203e 100644 --- a/tools/reqgen.c +++ b/tools/reqgen.c @@ -19,6 +19,7 @@ #include #include #include +#include "passwd.h" static const char *options = @@ -39,7 +40,7 @@ static char *usage = " * xmss-hashsig\n" " * xmssmt-hashsig\n" " * shpincs-hashsig\n" -" -pass pass Password for decrypting private key file\n" +" -pass pass Password for decrypting private key file, prompt if not given\n" " -sig_alg str Signature algorithm OID name, default sm2sign-with-sm3\n" " -sm2_id str Signer's ID in SM2 signature algorithm\n" " -sm2_id_hex hex Signer's ID in hex format\n" @@ -90,7 +91,9 @@ int reqgen_main(int argc, char **argv) // Private Key FILE *keyfp = NULL; + char *keyfile = NULL; char *pass = NULL; + char passbuf[GMSSL_PASSWORD_MAX_SIZE] = {0}; X509_KEY x509_key; int algor = OID_ec_public_key; int sign_algor = OID_sm2sign_with_sm3; @@ -140,6 +143,7 @@ int reqgen_main(int argc, char **argv) } else if (!strcmp(*argv, "-key")) { if (--argc < 1) goto bad; str = *(++argv); + keyfile = str; if (!(keyfp = fopen(str, "rb"))) { fprintf(stderr, "%s: open '%s' failure : %s\n", prog, str, strerror(errno)); goto end; @@ -213,9 +217,10 @@ bad: } if (!pass && algor == OID_ec_public_key) { - fprintf(stderr, "%s: `-pass` option required\n", prog); - printf("usage: gmssl %s %s\n\n", prog, options); - goto end; + if (gmssl_tool_get_password(prog, "Password to decrypt private key", keyfile, &pass, + passbuf, sizeof(passbuf)) != 1) { + goto end; + } } if (x509_private_key_from_file(&x509_key, algor, pass, keyfp) != 1) { @@ -251,6 +256,7 @@ bad: ret = 0; end: x509_key_cleanup(&x509_key); + gmssl_secure_clear(passbuf, sizeof(passbuf)); if (keyfp) fclose(keyfp); if (outfile && outfp) fclose(outfp); return ret; diff --git a/tools/reqsign.c b/tools/reqsign.c index 6c69f504..6e28f48e 100644 --- a/tools/reqsign.c +++ b/tools/reqsign.c @@ -21,6 +21,7 @@ #include #include #include +#include "passwd.h" static const char *options = @@ -64,7 +65,7 @@ static char *usage = " must use the same ID in other commands explicitly.\n" " If neither `-sm2_id` nor `-sm2_id_hex` is specified,\n" " the default string '1234567812345678' is used\n" -" -pass pass Password for decrypting private key file\n" +" -pass pass Password for decrypting private key file, prompt if not given\n" " -out pem Output certificate file in PEM format\n" "\n" " Extension options\n" @@ -176,7 +177,9 @@ int reqsign_main(int argc, char **argv) uint8_t *cacert = NULL; size_t cacertlen; FILE *keyfp = NULL; + char *keyfile = NULL; char *pass = NULL; + char passbuf[GMSSL_PASSWORD_MAX_SIZE] = {0}; X509_KEY x509_key; char signer_id[SM2_MAX_ID_LENGTH + 1] = {0}; size_t signer_id_len = 0; @@ -312,6 +315,7 @@ int reqsign_main(int argc, char **argv) } else if (!strcmp(*argv, "-key")) { if (--argc < 1) goto bad; str = *(++argv); + keyfile = str; if (!(keyfp = fopen(str, "rb"))) { fprintf(stderr, "%s: open '%s' failure : %s\n", prog, str, strerror(errno)); goto end; @@ -469,9 +473,10 @@ bad: goto end; } if (!pass && issuer_public_key.algor == OID_ec_public_key) { - fprintf(stderr, "%s: '-pass' option required\n", prog); - printf("usage: gmssl %s %s\n\n", prog, options); - goto end; + if (gmssl_tool_get_password(prog, "Password to decrypt private key", keyfile, &pass, + passbuf, sizeof(passbuf)) != 1) { + goto end; + } } if (x509_private_key_from_file(&x509_key, issuer_public_key.algor, pass, keyfp) != 1) { @@ -622,6 +627,7 @@ bad: ret = 0; end: x509_key_cleanup(&x509_key); + gmssl_secure_clear(passbuf, sizeof(passbuf)); if (cert) free(cert); if (keyfp) fclose(keyfp); if (infile && infp) fclose(infp); diff --git a/tools/sdfdecrypt.c b/tools/sdfdecrypt.c index 53933e53..5c3b3209 100755 --- a/tools/sdfdecrypt.c +++ b/tools/sdfdecrypt.c @@ -19,9 +19,10 @@ #include #include #include +#include "passwd.h" -static const char *usage = "-lib so_path -key num -pass str [-in file] [-out file]"; +static const char *usage = "-lib so_path -key num [-pass str] [-in file] [-out file]"; static const char *options = "\n" @@ -29,7 +30,7 @@ static const char *options = "\n" " -lib so_path Vendor's SDF dynamic library\n" " -key num Decryption private key index number\n" -" -pass str Password to get the private key access right\n" +" -pass str Password to get the private key access right, prompt if not given\n" " -in file | stdin Input data\n" " -out file | stdout Output data\n" "\n" @@ -47,6 +48,7 @@ int sdfdecrypt_main(int argc, char **argv) char *lib = NULL; int key_index = -1; char *pass = NULL; + char passbuf[GMSSL_PASSWORD_MAX_SIZE] = {0}; char *infile = NULL; char *outfile = NULL; FILE *infp = stdin; @@ -139,8 +141,8 @@ bad: fprintf(stderr, "gmssl %s: '-key' option required\n", prog); goto end; } - if (!pass) { - fprintf(stderr, "gmssl %s: '-pass' option required\n", prog); + if (gmssl_tool_get_password(prog, "Password to access SDF private key", NULL, &pass, + passbuf, sizeof(passbuf)) != 1) { goto end; } @@ -220,6 +222,7 @@ end: (void)sdf_close_device(&dev); (void)sdf_unload_library(); gmssl_secure_clear(iv, sizeof(iv)); + gmssl_secure_clear(passbuf, sizeof(passbuf)); if (infile && infp) fclose(infp); if (outfile && outfp) fclose(outfp); return ret; diff --git a/tools/sdfsign.c b/tools/sdfsign.c index 0510283f..90955f4f 100644 --- a/tools/sdfsign.c +++ b/tools/sdfsign.c @@ -14,9 +14,10 @@ #include #include #include +#include "passwd.h" -static const char *usage = "-lib so_path -key num -pass str [-id str] [-in file] [-out file]"; +static const char *usage = "-lib so_path -key num [-pass str] [-id str] [-in file] [-out file]"; static const char *options = "\n" @@ -24,7 +25,7 @@ static const char *options = "\n" " -lib so_path Vendor's SDF dynamic library\n" " -key num Signing private key index number\n" -" -pass str Password to get the private key access right\n" +" -pass str Password to get the private key access right, prompt if not given\n" " -id str Signer's identity string, '1234567812345678' by default\n" " -in file | stdin To be signed file or data\n" " -out file | stdout Output signature in binary DER encoding\n" @@ -44,6 +45,7 @@ int sdfsign_main(int argc, char **argv) char *lib = NULL; int key_index = -1; char *pass = NULL; + char passbuf[GMSSL_PASSWORD_MAX_SIZE] = {0}; char *id = SM2_DEFAULT_ID; char *infile = NULL; char *outfile = NULL; @@ -125,8 +127,8 @@ bad: fprintf(stderr, "gmssl %s: '-key' option required\n", prog); goto end; } - if (!pass) { - fprintf(stderr, "gmssl %s: '-pass' option required\n", prog); + if (gmssl_tool_get_password(prog, "Password to access SDF private key", NULL, &pass, + passbuf, sizeof(passbuf)) != 1) { goto end; } @@ -171,6 +173,7 @@ bad: end: gmssl_secure_clear(&ctx, sizeof(ctx)); + gmssl_secure_clear(passbuf, sizeof(passbuf)); (void)sdf_release_private_key(&key); (void)sdf_close_device(&dev); sdf_unload_library(); diff --git a/tools/sdftest.c b/tools/sdftest.c index 6447f6bf..f8bffdbe 100644 --- a/tools/sdftest.c +++ b/tools/sdftest.c @@ -17,13 +17,15 @@ #include #include #include +#include #include #include +#include "passwd.h" #include "../src/sdf/sdf.h" #include "../src/sdf/sdf_ext.h" -static const char *usage = "-lib so_path -kek num -key num -pass str"; +static const char *usage = "-lib so_path -kek num -key num [-pass str]"; static const char *options = "\n" @@ -32,7 +34,7 @@ static const char *options = " -lib so_path Path to vendor's SDF dynamic lib (.so or .dylib)\n" " -kek num KEK index\n" " -key num Private key index\n" -" -pass str Password for accessing the private key\n" +" -pass str Password for accessing the private key, prompt if not given\n" "\n" "Examples\n" "\n" @@ -2150,6 +2152,7 @@ int sdftest_main(int argc, char **argv) int kek = 1; int key = 1; char *pass = NULL; + char passbuf[GMSSL_PASSWORD_MAX_SIZE] = {0}; argc--; argv++; @@ -2201,8 +2204,8 @@ bad: fprintf(stderr, "gmssl %s: option `-lib` missing\n", prog); goto end; } - if (!pass) { - fprintf(stderr, "gmssl %s: option `-pass` missing\n", prog); + if (gmssl_tool_get_password(prog, "Password to access SDF private key", NULL, &pass, + passbuf, sizeof(passbuf)) != 1) { goto end; } @@ -2251,7 +2254,9 @@ bad: err: error_print(); + gmssl_secure_clear(passbuf, sizeof(passbuf)); return 1; end: + gmssl_secure_clear(passbuf, sizeof(passbuf)); return ret; } diff --git a/tools/sdfutil.c b/tools/sdfutil.c index a64af0c9..bc96b1e3 100644 --- a/tools/sdfutil.c +++ b/tools/sdfutil.c @@ -17,6 +17,7 @@ #include #include #include +#include "passwd.h" #define OP_NONE 0 @@ -30,8 +31,8 @@ static void print_usage(FILE *fp, const char *prog) { fprintf(fp, "usage:\n"); fprintf(fp, " %s -lib so_path -devinfo\n", prog); - fprintf(fp, " %s -lib so_path -exportpubkey -key index [-out file]\n", prog); - fprintf(fp, " %s -lib so_path -sign [-in file] [-out file]\n", prog); + fprintf(fp, " %s -lib so_path -exportpubkey -key index [-pass str] [-out file]\n", prog); + fprintf(fp, " %s -lib so_path -sign -key index [-pass str] [-in file] [-out file]\n", prog); fprintf(fp, " %s -lib so_path -rand num [-out file]\n", prog); } @@ -43,6 +44,7 @@ int sdfutil_main(int argc, char **argv) int op = 0; int keyindex = -1; char *pass = NULL; + char passbuf[GMSSL_PASSWORD_MAX_SIZE] = {0}; char *id = SM2_DEFAULT_ID; int num = 0; char *infile = NULL; @@ -143,6 +145,10 @@ bad: fprintf(stderr, "%s: invalid key index\n", prog); goto end; } + if (gmssl_tool_get_password(prog, "Password to access SDF private key", NULL, &pass, + passbuf, sizeof(passbuf)) != 1) { + goto end; + } if (sdf_load_sign_key(&dev, &key, keyindex, pass) != 1) { fprintf(stderr, "%s: load sign key failed\n", prog); goto end; @@ -161,6 +167,14 @@ bad: uint8_t sig[SM2_MAX_SIGNATURE_SIZE]; size_t siglen; + if (keyindex < 0) { + fprintf(stderr, "%s: invalid key index\n", prog); + goto end; + } + if (gmssl_tool_get_password(prog, "Password to access SDF private key", NULL, &pass, + passbuf, sizeof(passbuf)) != 1) { + goto end; + } if (sdf_load_sign_key(&dev, &key, keyindex, pass) != 1) { fprintf(stderr, "%s: load sign key failed\n", prog); goto end; @@ -211,6 +225,7 @@ bad: end: gmssl_secure_clear(buf, sizeof(buf)); + gmssl_secure_clear(passbuf, sizeof(passbuf)); if (key_opened) sdf_destroy_key(&key); if (dev_opened) sdf_close_device(&dev); if (lib) sdf_unload_library(); diff --git a/tools/skfutil.c b/tools/skfutil.c index 762d1dcc..044a86e4 100644 --- a/tools/skfutil.c +++ b/tools/skfutil.c @@ -18,6 +18,7 @@ #include #include #include +#include "passwd.h" #define OP_NONE 0 @@ -48,6 +49,7 @@ int skfutil_main(int argc, char **argv) char *appname = NULL; char *container_name = NULL; char *pass = NULL; + char passbuf[GMSSL_PASSWORD_MAX_SIZE] = {0}; char *id = SM2_DEFAULT_ID; int num = 0; char *infile = NULL; @@ -194,8 +196,8 @@ bad: fprintf(stderr, "%s: option '-container' required\n", prog); goto end; } - if (!pass) { - fprintf(stderr, "%s: option '-pass' required\n", prog); + if (gmssl_tool_get_password(prog, "Password to access SKF container", container_name, &pass, + passbuf, sizeof(passbuf)) != 1) { goto end; } @@ -255,6 +257,7 @@ bad: end: gmssl_secure_clear(buf, sizeof(buf)); + gmssl_secure_clear(passbuf, sizeof(passbuf)); if (key_opened) skf_release_key(&key); if (dev_opened) skf_close_device(&dev); if (lib) skf_unload_library(); diff --git a/tools/sm2decrypt.c b/tools/sm2decrypt.c index c73bacc5..7cf27049 100644 --- a/tools/sm2decrypt.c +++ b/tools/sm2decrypt.c @@ -14,16 +14,17 @@ #include #include #include +#include "passwd.h" -static const char *usage = "-key pem -pass str [-in file] [-out file]"; +static const char *usage = "-key pem [-pass str] [-in file] [-out file]"; static const char *options = "\n" "Options\n" "\n" " -key pem Decryption private key file in PEM format\n" -" -pass str Password to open the private key\n" +" -pass str Password to open the private key, prompt if not given\n" " -in file | stdin Input ciphertext in binary DER-encoding\n" " -in file | stdout Output decrypted data\n" "\n" @@ -40,6 +41,7 @@ int sm2decrypt_main(int argc, char **argv) char *prog = argv[0]; char *keyfile = NULL; char *pass = NULL; + char passbuf[GMSSL_PASSWORD_MAX_SIZE] = {0}; char *infile = NULL; char *outfile = NULL; FILE *keyfp = NULL; @@ -105,8 +107,8 @@ bad: fprintf(stderr, "gmssl %s: '-key' option required\n", prog); goto end; } - if (!pass) { - fprintf(stderr, "gmssl %s: '-pass' option required\n", prog); + if (gmssl_tool_get_password(prog, "Password to open private key", keyfile, &pass, + passbuf, sizeof(passbuf)) != 1) { goto end; } @@ -141,6 +143,7 @@ end: gmssl_secure_clear(&key, sizeof(key)); gmssl_secure_clear(&ctx, sizeof(ctx)); gmssl_secure_clear(outbuf, sizeof(outbuf)); + gmssl_secure_clear(passbuf, sizeof(passbuf)); if (keyfp) fclose(keyfp); if (infile && infp) fclose(infp); if (outfile && outfp) fclose(outfp); diff --git a/tools/sm2exch.c b/tools/sm2exch.c index a59e4a00..bf23f5f4 100644 --- a/tools/sm2exch.c +++ b/tools/sm2exch.c @@ -19,6 +19,7 @@ #include #include #include +#include "passwd.h" #define SM2EXCH_RA_SIZE 65 @@ -46,7 +47,7 @@ static const char *options = " -cert pem Optional local SM2 certificate for checking against -key\n" " -pubkey pem Optional local SM2 public key for checking against -key\n" " -key pem Local SM2 private key in PEM format\n" -" -pass str Password to open local private key\n" +" -pass str Password to open local private key, prompt if not given\n" " -peer_cert pem Peer SM2 key exchange/encryption certificate in PEM format\n" " -peer_pubkey pem Peer SM2 public key in PEM format\n" " -id str Local SM2 identity, '1234567812345678' by default\n" @@ -63,7 +64,7 @@ static const char *options = " confirm: SA, 32 bytes\n" " -exch_keyout pem Output local ephemeral private key\n" " -exch_key pem Input local ephemeral private key\n" -" -exch_pass str Password for local ephemeral private key\n" +" -exch_pass str Password for local ephemeral private key, prompt if not given\n" " -secret_state_out file\n" " Output 65-byte secret_state point\n" " -secret_state file Input 65-byte secret_state point\n" @@ -729,6 +730,7 @@ int sm2exch_main(int argc, char **argv) char *pubkeyfile = NULL; char *keyfile = NULL; char *pass = NULL; + char passbuf[GMSSL_PASSWORD_MAX_SIZE] = {0}; char *peer_certfile = NULL; char *peer_pubkeyfile = NULL; char *id = NULL; @@ -744,6 +746,7 @@ int sm2exch_main(int argc, char **argv) char *exch_keyfile = NULL; char *exch_keyoutfile = NULL; char *exch_pass = NULL; + char exch_passbuf[GMSSL_PASSWORD_MAX_SIZE] = {0}; char *secret_statefile = NULL; char *secret_stateoutfile = NULL; char *keyoutfile = NULL; @@ -903,18 +906,50 @@ bad: } if (!strcmp(stage, "init")) { + if (exch_keyoutfile && gmssl_tool_get_password(prog, + "Password to encrypt exchange private key", exch_keyoutfile, + &exch_pass, exch_passbuf, sizeof(exch_passbuf)) != 1) { + goto end; + } ret = sm2exch_stage_init(exch_keyoutfile, exch_pass, outfile, format, prog); } else if (!strcmp(stage, "respond")) { + if (keyfile && gmssl_tool_get_password(prog, "Password to open private key", + keyfile, &pass, passbuf, sizeof(passbuf)) != 1) { + goto end; + } + if (exch_keyoutfile && gmssl_tool_get_password(prog, + "Password to encrypt exchange private key", exch_keyoutfile, + &exch_pass, exch_passbuf, sizeof(exch_passbuf)) != 1) { + goto end; + } ret = sm2exch_stage_respond(keyfile, pass, pubkeyfile, certfile, peer_pubkeyfile, peer_certfile, id, id_len, peer_id, peer_id_len, infile, exch_keyoutfile, exch_pass, secret_stateoutfile, outfile, keylen, format, prog); } else if (!strcmp(stage, "confirm")) { + if (keyfile && gmssl_tool_get_password(prog, "Password to open private key", + keyfile, &pass, passbuf, sizeof(passbuf)) != 1) { + goto end; + } + if (exch_keyfile && gmssl_tool_get_password(prog, + "Password to open exchange private key", exch_keyfile, + &exch_pass, exch_passbuf, sizeof(exch_passbuf)) != 1) { + goto end; + } ret = sm2exch_stage_confirm(keyfile, pass, pubkeyfile, certfile, peer_pubkeyfile, peer_certfile, id, id_len, peer_id, peer_id_len, exch_keyfile, exch_pass, infile, secret_stateoutfile, keyoutfile, outfile, keylen, format, prog); } else if (!strcmp(stage, "finish")) { + if (keyfile && gmssl_tool_get_password(prog, "Password to open private key", + keyfile, &pass, passbuf, sizeof(passbuf)) != 1) { + goto end; + } + if (exch_keyfile && gmssl_tool_get_password(prog, + "Password to open exchange private key", exch_keyfile, + &exch_pass, exch_passbuf, sizeof(exch_passbuf)) != 1) { + goto end; + } ret = sm2exch_stage_finish(keyfile, pass, pubkeyfile, certfile, peer_pubkeyfile, peer_certfile, id, id_len, peer_id, peer_id_len, exch_keyfile, exch_pass, secret_statefile, infile, @@ -925,5 +960,7 @@ bad: } end: + gmssl_secure_clear(passbuf, sizeof(passbuf)); + gmssl_secure_clear(exch_passbuf, sizeof(exch_passbuf)); return ret == 0 ? 0 : 1; } diff --git a/tools/sm2keygen.c b/tools/sm2keygen.c index ec10d10d..573cec98 100644 --- a/tools/sm2keygen.c +++ b/tools/sm2keygen.c @@ -14,14 +14,15 @@ #include #include #include +#include "passwd.h" -static const char *usage = "-pass str [-out pem] [-pubout pem]\n"; +static const char *usage = "[-pass str] [-out pem] [-pubout pem]\n"; static const char *options = "Options\n" "\n" -" -pass pass Password to encrypt the private key\n" +" -pass pass Password to encrypt the private key, prompt if not given\n" " -out pem Output password-encrypted PKCS #8 private key in PEM format\n" " -pubout pem Output public key in PEM format\n" "\n" @@ -36,6 +37,7 @@ int sm2keygen_main(int argc, char **argv) int ret = 1; char *prog = argv[0]; char *pass = NULL; + char passbuf[GMSSL_PASSWORD_MAX_SIZE] = {0}; char *outfile = NULL; char *puboutfile = NULL; FILE *outfp = stdout; @@ -85,8 +87,8 @@ bad: argv++; } - if (!pass) { - fprintf(stderr, "gmssl %s: `-pass` option required\n", prog); + if (gmssl_tool_get_password(prog, "Password to encrypt private key", outfile, &pass, + passbuf, sizeof(passbuf)) != 1) { goto end; } @@ -100,6 +102,7 @@ bad: end: gmssl_secure_clear(&key, sizeof(key)); + gmssl_secure_clear(passbuf, sizeof(passbuf)); if (outfile && outfp) fclose(outfp); if (puboutfile && puboutfp) fclose(puboutfp); return ret; diff --git a/tools/sm2sign.c b/tools/sm2sign.c index 89d058f0..0c07c76d 100644 --- a/tools/sm2sign.c +++ b/tools/sm2sign.c @@ -14,16 +14,17 @@ #include #include #include +#include "passwd.h" -static const char *usage = "-key pem -pass str [-id str] [-in file] [-out file]"; +static const char *usage = "-key pem [-pass str] [-id str] [-in file] [-out file]"; static const char *options = "\n" "Options\n" "\n" " -key pem Signing private key file in PEM format\n" -" -pass str Password to open the private key\n" +" -pass str Password to open the private key, prompt if not given\n" " -id str Signer's identity string, '1234567812345678' by default\n" " -in file | stdin To be signed file or data\n" " -out file | stdout Output signature in binary DER encoding\n" @@ -42,6 +43,7 @@ int sm2sign_main(int argc, char **argv) char *prog = argv[0]; char *keyfile = NULL; char *pass = NULL; + char passbuf[GMSSL_PASSWORD_MAX_SIZE] = {0}; char *id = SM2_DEFAULT_ID; char *infile = NULL; char *outfile = NULL; @@ -112,8 +114,8 @@ bad: fprintf(stderr, "gmssl %s: '-key' option required\n", prog); goto end; } - if (!pass) { - fprintf(stderr, "gmssl %s: '-pass' option required\n", prog); + if (gmssl_tool_get_password(prog, "Password to open private key", keyfile, &pass, + passbuf, sizeof(passbuf)) != 1) { goto end; } if (sm2_private_key_info_decrypt_from_pem(&key, pass, keyfp) != 1) { @@ -147,6 +149,7 @@ bad: end: gmssl_secure_clear(&key, sizeof(key)); gmssl_secure_clear(&sign_ctx, sizeof(sign_ctx)); + gmssl_secure_clear(passbuf, sizeof(passbuf)); if (keyfp) fclose(keyfp); if (infile && infp) fclose(infp); if (outfile && outfp) fclose(outfp); diff --git a/tools/sm3_pbkdf2.c b/tools/sm3_pbkdf2.c index b448cefb..4002fc68 100644 --- a/tools/sm3_pbkdf2.c +++ b/tools/sm3_pbkdf2.c @@ -15,15 +15,16 @@ #include #include #include +#include "passwd.h" -static const char *usage = "-pass str -salt hex -iter num -outlen num [-bin|-hex] [-out file]"; +static const char *usage = "[-pass str] -salt hex -iter num -outlen num [-bin|-hex] [-out file]"; static const char *options = "\n" "Options\n" "\n" -" -pass str Password to be converted into key\n" +" -pass str Password to be converted into key, prompt if not given\n" " -salt hex Salt value, 8 to 64 bytes\n" " -iter num Iteration count, larger iter make it more secure but slower\n" " -outlen num Generate key bytes\n" @@ -43,6 +44,7 @@ int sm3_pbkdf2_main(int argc, char **argv) int ret = 1; char *prog = argv[0]; char *pass = NULL; + char passbuf[GMSSL_PASSWORD_MAX_SIZE] = {0}; char *salthex = NULL; uint8_t salt[SM3_PBKDF2_MAX_SALT_SIZE]; size_t saltlen; @@ -122,8 +124,8 @@ bad: argv++; } - if (!pass) { - fprintf(stderr, "gmssl %s: option '-pass' required\n", prog); + if (gmssl_tool_get_password(prog, "Password", NULL, &pass, + passbuf, sizeof(passbuf)) != 1) { goto end; } if (!salthex) { @@ -160,6 +162,7 @@ bad: end: gmssl_secure_clear(outbuf, sizeof(outbuf)); gmssl_secure_clear(salt, sizeof(salt)); + gmssl_secure_clear(passbuf, sizeof(passbuf)); if (outfile && outfp) fclose(outfp); return ret; } diff --git a/tools/sm9decrypt.c b/tools/sm9decrypt.c index c8aa2701..efe58c5c 100644 --- a/tools/sm9decrypt.c +++ b/tools/sm9decrypt.c @@ -14,15 +14,16 @@ #include #include #include +#include "passwd.h" -static const char *usage = "-key pem -pass str -id str [-in file] [-out file]"; +static const char *usage = "-key pem [-pass str] -id str [-in file] [-out file]"; static const char *options = "Options\n" "\n" " -key pem Recipient's private key in PEM format\n" -" -pass str Password to open the private key\n" +" -pass str Password to open the private key, prompt if not given\n" " -id str Recipient's identity string\n" " -in file | stdin Encrypted file or data\n" " -out file | stdout Output plaintext\n" @@ -43,6 +44,7 @@ int sm9decrypt_main(int argc, char **argv) char *infile = NULL; char *keyfile = NULL; char *pass = NULL; + char passbuf[GMSSL_PASSWORD_MAX_SIZE] = {0}; char *id = NULL; char *outfile = NULL; FILE *keyfp = NULL; @@ -103,10 +105,14 @@ bad: argv++; } - if (!keyfile || !pass || !id) { + if (!keyfile || !id) { error_print(); goto end; } + if (gmssl_tool_get_password(prog, "Password to open private key", keyfile, &pass, + passbuf, sizeof(passbuf)) != 1) { + goto end; + } if (sm9_enc_key_info_decrypt_from_pem(&key, pass, keyfp) != 1) { error_print(); @@ -129,6 +135,7 @@ bad: end: gmssl_secure_clear(&key, sizeof(key)); gmssl_secure_clear(outbuf, sizeof(outbuf)); + gmssl_secure_clear(passbuf, sizeof(passbuf)); if (keyfp) fclose(keyfp); if (infile && infp) fclose(infp); if (outfile && outfp) fclose(outfp); diff --git a/tools/sm9exch.c b/tools/sm9exch.c index a4d95826..ae822e8b 100644 --- a/tools/sm9exch.c +++ b/tools/sm9exch.c @@ -17,6 +17,7 @@ #include #include #include +#include "passwd.h" #define SM9EXCH_R_SIZE 32 @@ -45,7 +46,7 @@ static const char *options = " SM9 key exchange stage\n" " -pubmaster pem SM9 exchange master public key in PEM format\n" " -key pem Local SM9 exchange private key in PEM format\n" -" -pass str Password to open local private key\n" +" -pass str Password to open local private key, prompt if not given\n" " -id str Local SM9 identity\n" " -id_hex hex Local SM9 identity in hex\n" " -peer_id str Peer SM9 identity\n" @@ -612,6 +613,7 @@ int sm9exch_main(int argc, char **argv) char *mpkfile = NULL; char *keyfile = NULL; char *pass = NULL; + char passbuf[GMSSL_PASSWORD_MAX_SIZE] = {0}; char *id = NULL; char *peer_id = NULL; char *id_hex = NULL; @@ -750,14 +752,26 @@ bad: ret = sm9exch_stage_init(mpkfile, peer_id, peer_id_len, exch_keyoutfile, outfile, format, prog); } else if (!strcmp(stage, "respond")) { + if (keyfile && gmssl_tool_get_password(prog, "Password to open private key", + keyfile, &pass, passbuf, sizeof(passbuf)) != 1) { + goto end; + } ret = sm9exch_stage_respond(mpkfile, keyfile, pass, id, id_len, peer_id, peer_id_len, infile, exch_keyoutfile, outfile, keylen, format, prog); } else if (!strcmp(stage, "confirm")) { + if (keyfile && gmssl_tool_get_password(prog, "Password to open private key", + keyfile, &pass, passbuf, sizeof(passbuf)) != 1) { + goto end; + } ret = sm9exch_stage_confirm(mpkfile, keyfile, pass, id, id_len, peer_id, peer_id_len, exch_keyfile, infile, keyoutfile, outfile, keylen, format, prog); } else if (!strcmp(stage, "finish")) { + if (keyfile && gmssl_tool_get_password(prog, "Password to open private key", + keyfile, &pass, passbuf, sizeof(passbuf)) != 1) { + goto end; + } ret = sm9exch_stage_finish(mpkfile, keyfile, pass, id, id_len, peer_id, peer_id_len, exch_keyfile, infile, keyoutfile, keylen, format, prog); @@ -767,5 +781,6 @@ bad: } end: + gmssl_secure_clear(passbuf, sizeof(passbuf)); return ret == 0 ? 0 : 1; } diff --git a/tools/sm9keygen.c b/tools/sm9keygen.c index 295329f0..c9a652a5 100644 --- a/tools/sm9keygen.c +++ b/tools/sm9keygen.c @@ -15,9 +15,10 @@ #include #include #include +#include "passwd.h" -static const char *usage = "-alg (sm9sign|sm9encrypt|sm9keyagreement) -in master_key.pem -inpass str -id str [-out pem] -outpass str"; +static const char *usage = "-alg (sm9sign|sm9encrypt|sm9keyagreement) -in master_key.pem [-inpass str] -id str [-out pem] [-outpass str]"; static const char *options = "Options\n" @@ -25,10 +26,10 @@ static const char *options = " -alg sm9sign|sm9encrypt|sm9keyagreement\n" " Generate user's private key for sm9sign, sm9encrypt or sm9keyagreement\n" " -in pem SM9 master private key in PEM format\n" -" -inpass pass Password to decrypt the master private key\n" +" -inpass pass Password to decrypt the master private key, prompt if not given\n" " -id str User's identity\n" " -out pem Output password-encrypted user's private key in PEM format\n" -" -outpass pass Password to encrypt user's private key\n" +" -outpass pass Password to encrypt user's private key, prompt if not given\n" "\n" "Examples\n" "\n" @@ -47,9 +48,11 @@ int sm9keygen_main(int argc, char **argv) char *alg = NULL; char *infile = NULL; char *inpass = NULL; + char inpassbuf[GMSSL_PASSWORD_MAX_SIZE] = {0}; char *id = NULL; char *outfile = NULL; char *outpass = NULL; + char outpassbuf[GMSSL_PASSWORD_MAX_SIZE] = {0}; int oid = 0; FILE *infp = stdin; FILE *outfp = stdout; @@ -116,8 +119,10 @@ bad: fprintf(stderr, "%s: option '-id' is required\n", prog); goto end; } - if (!inpass || !outpass) { - error_print(); + if (gmssl_tool_get_password(prog, "Password to decrypt master private key", infile, + &inpass, inpassbuf, sizeof(inpassbuf)) != 1 + || gmssl_tool_get_password(prog, "Password to encrypt user private key", outfile, + &outpass, outpassbuf, sizeof(outpassbuf)) != 1) { goto end; } @@ -156,6 +161,8 @@ end: gmssl_secure_clear(&enc_msk, sizeof(enc_msk)); gmssl_secure_clear(&sign_key, sizeof(sign_key)); gmssl_secure_clear(&enc_key, sizeof(enc_key)); + gmssl_secure_clear(inpassbuf, sizeof(inpassbuf)); + gmssl_secure_clear(outpassbuf, sizeof(outpassbuf)); if (infile && infp) fclose(infp); if (outfile && outfp) fclose(outfp); return ret; diff --git a/tools/sm9setup.c b/tools/sm9setup.c index dd3a6195..b177fb4b 100644 --- a/tools/sm9setup.c +++ b/tools/sm9setup.c @@ -15,6 +15,7 @@ #include #include #include +#include "passwd.h" static const char *usage = "-alg (sm9sign|sm9encrypt) [-pass password] [-out pem] [-pubout pem] [-verbose]"; @@ -22,7 +23,7 @@ static const char *options = "Options\n" "\n" " -alg sm9sign|sm9encrypt Generate maeter key for sm9sign or sm9encrypt\n" -" -pass pass Password to encrypt the master private key\n" +" -pass pass Password to encrypt the master private key, prompt if not given\n" " -out pem Output password-encrypted master private key in PEM format\n" " -pubout pem Output master public key in PEM format\n" " -verbose Print details\n" @@ -39,6 +40,7 @@ int sm9setup_main(int argc, char **argv) char *prog = argv[0]; char *alg = NULL; char *pass = NULL; + char passbuf[GMSSL_PASSWORD_MAX_SIZE] = {0}; char *outfile = NULL; char *puboutfile = NULL; int oid; @@ -99,11 +101,11 @@ bad: if (!alg) { error_print(); - return -1; + goto end; } - if (!pass) { - error_print(); - return -1; + if (gmssl_tool_get_password(prog, "Password to encrypt master private key", outfile, &pass, + passbuf, sizeof(passbuf)) != 1) { + goto end; } switch (oid) { @@ -140,6 +142,7 @@ bad: end: gmssl_secure_clear(&sign_msk, sizeof(sign_msk)); gmssl_secure_clear(&enc_msk, sizeof(enc_msk)); + gmssl_secure_clear(passbuf, sizeof(passbuf)); if (outfile && outfp) fclose(outfp); if (puboutfile && puboutfp) fclose(puboutfp); return ret; @@ -162,5 +165,3 @@ end: - - diff --git a/tools/sm9sign.c b/tools/sm9sign.c index 9a971b47..7f935540 100644 --- a/tools/sm9sign.c +++ b/tools/sm9sign.c @@ -14,15 +14,16 @@ #include #include #include +#include "passwd.h" -static const char *usage = "-key pem -pass str [-in file] [-out file]"; +static const char *usage = "-key pem [-pass str] [-in file] [-out file]"; static const char *options = "Options\n" "\n" " -key pem Signing private key file in PEM format\n" -" -pass str Password to open the private key\n" +" -pass str Password to open the private key, prompt if not given\n" " -in file | stdin To be signed file or data\n" " -out file | stdout Output signature in binary DER encoding\n" "\n" @@ -42,6 +43,7 @@ int sm9sign_main(int argc, char **argv) char *infile = NULL; char *keyfile = NULL; char *pass = NULL; + char passbuf[GMSSL_PASSWORD_MAX_SIZE] = {0}; char *outfile = NULL; FILE *infp = stdin; FILE *keyfp = NULL; @@ -100,10 +102,14 @@ bad: argv++; } - if (!keyfile || !pass) { + if (!keyfile) { error_print(); goto end; } + if (gmssl_tool_get_password(prog, "Password to open private key", keyfile, &pass, + passbuf, sizeof(passbuf)) != 1) { + goto end; + } if (sm9_sign_key_info_decrypt_from_pem(&key, pass, keyfp) != 1) { error_print(); @@ -142,6 +148,7 @@ end: gmssl_secure_clear(&key, sizeof(key)); gmssl_secure_clear(&ctx, sizeof(ctx)); gmssl_secure_clear(buf, sizeof(buf)); + gmssl_secure_clear(passbuf, sizeof(passbuf)); if (infile && infp) fclose(infp); if (outfile && outfp) fclose(outfp); return ret; diff --git a/tools/tlcp_client.c b/tools/tlcp_client.c index 7486305d..cd30e4ca 100644 --- a/tools/tlcp_client.c +++ b/tools/tlcp_client.c @@ -11,16 +11,18 @@ #include #include #include +#include #include #include #include +#include "passwd.h" #define TIMEOUT_SECONDS 1 static const char *usage = "-host str [-port num] [-cacert pem]" - " [-cert pem -key pem -pass str]" + " [-cert pem -key pem [-pass str]]" " [-certout pem]" " [-get path|-in file]" " [-alpn str]" @@ -39,7 +41,7 @@ static const char *help = " -verify_depth num Certificate verification depth\n" " -cert pem Client certificate(s) in PEM format, TLCP ECDHE requires a double certificate chain\n" " -key pem Private key of client certificate in PEM format, TLCP ECDHE requires signing and encryption keys\n" -" -pass password Password of encrypted private key\n" +" -pass password Password of encrypted private key, prompt if not given\n" " -client_cert_optional Allow client send empty Certificate\n" " -get path Send a GET request with given path of URI\n" " -in file | stdin Send input data and read response until close or timeout\n" @@ -242,6 +244,7 @@ int tlcp_client_main(int argc, char *argv[]) char *certfile = NULL; char *keyfile = NULL; char *pass = NULL; + char passbuf[GMSSL_PASSWORD_MAX_SIZE] = {0}; char *server_name = NULL; int trusted_ca_keys = 0; char *alpn_protocols[4]; @@ -404,8 +407,8 @@ bad: return -1; } has_ecdhe_cipher_suite = tlcp_cipher_suites_have_ecdhe(cipher_suites, cipher_suites_cnt); - if (has_ecdhe_cipher_suite && (!certfile || !keyfile || !pass)) { - fprintf(stderr, "%s: TLCP ECDHE cipher suites require '-cert', '-key' and '-pass' with a double certificate chain\n", prog); + if (has_ecdhe_cipher_suite && (!certfile || !keyfile)) { + fprintf(stderr, "%s: TLCP ECDHE cipher suites require '-cert' and '-key' with a double certificate chain\n", prog); return -1; } @@ -472,8 +475,8 @@ bad: fprintf(stderr, "%s: option '-key' missing\n", prog); goto end; } - if (!pass) { - fprintf(stderr, "%s: option '-pass' missing\n", prog); + if (gmssl_tool_get_password(prog, "Password to decrypt private key", keyfile, &pass, + passbuf, sizeof(passbuf)) != 1) { goto end; } if (has_ecdhe_cipher_suite) { @@ -670,6 +673,7 @@ bad: end: // FIXME: clean ctx and connection ASAP, as Ctrl-C is not handled + gmssl_secure_clear(passbuf, sizeof(passbuf)); if (tls_socket_is_valid(sock)) tls_socket_close(sock); tls_ctx_cleanup(&ctx); tls_cleanup(&conn); diff --git a/tools/tlcp_server.c b/tools/tlcp_server.c index e7c78959..9a82fbd9 100644 --- a/tools/tlcp_server.c +++ b/tools/tlcp_server.c @@ -30,9 +30,10 @@ #include #include #include +#include "passwd.h" -static const char *options = "[-port num] -cert pem -key pem -pass str [-cipher_suite str] [-alpn str] [-cert_request] [-cacert pem] [-verbose]"; +static const char *options = "[-port num] -cert pem -key pem [-pass str] [-cipher_suite str] [-alpn str] [-cert_request] [-cacert pem] [-verbose]"; static const char *help = @@ -41,7 +42,7 @@ static const char *help = " -port num Listening port number, default 443\n" " -cert pem Server's certificate chain in PEM format, may appear multiple times\n" " -key pem Server's signing and encryption private keys in PEM format: signing key first, encryption key second, may appear multiple times\n" -" -pass str Password to decrypt both private keys in the same -key PEM, may appear multiple times\n" +" -pass str Password to decrypt both private keys in the same -key PEM, may appear multiple times, prompt if not given\n" " -cipher_suite str Supported cipher suites, may appear multiple times, higher priority first\n" " -alpn str Application protocol name, may appear multiple times, higher priority first\n" " -cert_request Client certificate request\n" @@ -152,6 +153,7 @@ int tlcp_server_main(int argc , char **argv) char *signkeyfiles[sizeof(certfiles)/sizeof(certfiles[0])]; size_t signkeyfiles_cnt = 0; char *signpasses[sizeof(certfiles)/sizeof(certfiles[0])]; + char passbufs[sizeof(certfiles)/sizeof(certfiles[0])][GMSSL_PASSWORD_MAX_SIZE] = {{0}}; size_t signpasses_cnt = 0; char *alpn_protocols[4]; size_t alpn_protocols_cnt = 0; @@ -255,14 +257,22 @@ bad: fprintf(stderr, "%s: '-key' option required\n", prog); return 1; } - if (!signpasses_cnt) { - fprintf(stderr, "%s: '-pass' option required\n", prog); + if (signpasses_cnt > signkeyfiles_cnt) { + fprintf(stderr, "%s: too many -pass options\n", prog); return 1; } - if (certfiles_cnt != signkeyfiles_cnt || signkeyfiles_cnt != signpasses_cnt) { - fprintf(stderr, "%s: -cert/-key/-pass counts mismatch\n", prog); + if (certfiles_cnt != signkeyfiles_cnt) { + fprintf(stderr, "%s: -cert/-key counts mismatch\n", prog); return 1; } + for (i = signpasses_cnt; i < signkeyfiles_cnt; i++) { + if (gmssl_tool_read_password(prog, "Password to decrypt private key", + signkeyfiles[i], passbufs[i], sizeof(passbufs[i])) != 1) { + goto end; + } + signpasses[i] = passbufs[i]; + } + signpasses_cnt = signkeyfiles_cnt; if (!cipher_suites_cnt) { fprintf(stderr, "%s: '-cipher_suite' option required\n", prog); @@ -409,5 +419,6 @@ restart: end: + gmssl_secure_clear(passbufs, sizeof(passbufs)); return ret; } diff --git a/tools/tls12_client.c b/tools/tls12_client.c index 6dd383e5..03c646f7 100644 --- a/tools/tls12_client.c +++ b/tools/tls12_client.c @@ -11,13 +11,15 @@ #include #include #include +#include #include #include +#include "passwd.h" static int client_ciphers[] = { TLS_cipher_ecdhe_sm4_cbc_sm3 }; -static const char *options = "-host str [-port num] [-cacert pem] [-cert pem -key pem -pass str] [-get path|-in file] [-trusted_ca_keys] [-verbose]"; +static const char *options = "-host str [-port num] [-cacert pem] [-cert pem -key pem [-pass str]] [-get path|-in file] [-trusted_ca_keys] [-verbose]"; static const char *help = "Options\n" @@ -31,7 +33,7 @@ static const char *help = " -verify_depth num Certificate verification depth\n" " -cert pem Client's certificate chain in PEM format\n" " -key pem Client's encrypted private key in PEM format\n" -" -pass str Password to decrypt private key\n" +" -pass str Password to decrypt private key, prompt if not given\n" " -client_cert_optional Allow client send empty Certificate\n" " -server_name str Send server_name (SNI) request\n" " -trusted_ca_keys Send trusted_ca_keys request\n" @@ -210,6 +212,7 @@ int tls12_client_main(int argc, char *argv[]) char *certfile = NULL; char *keyfile = NULL; char *pass = NULL; + char passbuf[GMSSL_PASSWORD_MAX_SIZE] = {0}; int client_cert_optional = 0; char *server_name = NULL; int trusted_ca_keys = 0; @@ -437,8 +440,8 @@ bad: fprintf(stderr, "%s: option '-key' missing\n", prog); goto end; } - if (!pass) { - fprintf(stderr, "%s: option '-pass' missing\n", prog); + if (gmssl_tool_get_password(prog, "Password to decrypt private key", keyfile, &pass, + passbuf, sizeof(passbuf)) != 1) { goto end; } if (tls_ctx_set_certificate_and_key(&ctx, certfile, keyfile, pass) != 1) { @@ -604,6 +607,7 @@ bad: end: + gmssl_secure_clear(passbuf, sizeof(passbuf)); if (tls_socket_is_valid(sock)) tls_socket_close(sock); tls_ctx_cleanup(&ctx); tls_cleanup(&conn); diff --git a/tools/tls12_server.c b/tools/tls12_server.c index a2866151..34eb4bd7 100644 --- a/tools/tls12_server.c +++ b/tools/tls12_server.c @@ -15,9 +15,10 @@ #include #include #include +#include "passwd.h" -static const char *options = "[-port num] -cert pem -key pem -pass str [-cacert pem] [-verbose]"; +static const char *options = "[-port num] -cert pem -key pem [-pass str] [-cacert pem] [-verbose]"; static const char *help = "Options\n" @@ -28,7 +29,7 @@ static const char *help = " -sig_alg str Supported signature algorithms\n" " -cert pem Server's certificate chain in PEM format\n" " -key pem Server's encrypted private key in PEM format\n" -" -pass str Password to decrypt private key\n" +" -pass str Password to decrypt private key, prompt if not given\n" " -cert_request Client certificate request\n" " -cacert pem CA certificate for client certificate verification\n" " -verify_depth num Certificate verification depth\n" @@ -145,6 +146,7 @@ int tls12_server_main(int argc , char **argv) char *keyfiles[sizeof(certfiles)/sizeof(certfiles[0])]; size_t keyfiles_cnt = 0; char *passes[sizeof(certfiles)/sizeof(certfiles[0])]; + char passbufs[sizeof(certfiles)/sizeof(certfiles[0])][GMSSL_PASSWORD_MAX_SIZE] = {{0}}; size_t passes_cnt = 0; int cert_request = 0; char *cacertfile = NULL; @@ -282,14 +284,22 @@ bad: fprintf(stderr, "%s: '-key' option required\n", prog); return 1; } - if (!passes_cnt) { - fprintf(stderr, "%s: '-pass' option required\n", prog); + if (passes_cnt > keyfiles_cnt) { + fprintf(stderr, "%s: too many -pass options\n", prog); return 1; } - if (certfiles_cnt != keyfiles_cnt || keyfiles_cnt != passes_cnt) { + if (certfiles_cnt != keyfiles_cnt) { error_print(); return -1; } + for (i = passes_cnt; i < keyfiles_cnt; i++) { + if (gmssl_tool_read_password(prog, "Password to decrypt private key", + keyfiles[i], passbufs[i], sizeof(passbufs[i])) != 1) { + goto end; + } + passes[i] = passbufs[i]; + } + passes_cnt = keyfiles_cnt; if (tls_socket_lib_init() != 1) { error_print(); @@ -454,5 +464,6 @@ restart: end: + gmssl_secure_clear(passbufs, sizeof(passbufs)); return ret; } diff --git a/tools/tls13_client.c b/tools/tls13_client.c index 4ee92c6d..13b10ed5 100644 --- a/tools/tls13_client.c +++ b/tools/tls13_client.c @@ -11,9 +11,11 @@ #include #include #include +#include #include #include #include +#include "passwd.h" #ifdef _WIN32 #define tls_stdio_fileno(fp) _fileno(fp) @@ -169,7 +171,7 @@ static int do_send_file_select(TLS_CONNECT *conn, FILE *fp) return 1; } -static const char *options = "-host str [-port num] [-cacert pem] [-cert pem -key pem -pass str] [-get path|-in file] [-verbose]"; +static const char *options = "-host str [-port num] [-cacert pem] [-cert pem -key pem [-pass str]] [-get path|-in file] [-verbose]"; static const char *help = "Options\n" @@ -184,7 +186,7 @@ static const char *help = " -verify_depth num Certificate verification depth\n" " -cert pem Client's certificate chain in PEM format\n" " -key pem Client's encrypted private key in PEM format\n" -" -pass str Password to decrypt private key\n" +" -pass str Password to decrypt private key, prompt if not given\n" " -server_name str Send server_name (SNI) request\n" " -signature_algorithms_cert Send signature_algorithms_cert extension\n" " -certificate_authorities Send certificate_authorities extension\n" @@ -242,6 +244,7 @@ int tls13_client_main(int argc, char *argv[]) char *certfile = NULL; char *keyfile = NULL; char *pass = NULL; + char passbuf[GMSSL_PASSWORD_MAX_SIZE] = {0}; int client_cert_optional = 0; // supported_groups @@ -568,8 +571,8 @@ bad: fprintf(stderr, "%s: option -key is required\n", prog); goto end; } - if (!pass) { - fprintf(stderr, "%s: option -pass is requried\n", prog); + if (gmssl_tool_get_password(prog, "Password to decrypt private key", keyfile, &pass, + passbuf, sizeof(passbuf)) != 1) { goto end; } if (tls_ctx_add_certificate_chain_and_key(&ctx, certfile, keyfile, pass) != 1) { @@ -938,6 +941,7 @@ bad: } end: + gmssl_secure_clear(passbuf, sizeof(passbuf)); if (tls_socket_is_valid(sock)) tls_socket_close(sock); tls_ctx_cleanup(&ctx); tls_cleanup(&conn); diff --git a/tools/tls13_server.c b/tools/tls13_server.c index a502a013..1fe8f532 100644 --- a/tools/tls13_server.c +++ b/tools/tls13_server.c @@ -16,10 +16,11 @@ #include #include #include +#include "passwd.h" -static const char *options = "[-port num] -cert pem -key pem -pass str [-cacert pem] [-verbose]"; +static const char *options = "[-port num] -cert pem -key pem [-pass str] [-cacert pem] [-verbose]"; static const char *help = "Options\n" @@ -30,7 +31,7 @@ static const char *help = " -sig_alg str Supported signature algorithms\n" " -cert pem Server's certificate chain in PEM format\n" " -key pem Server's encrypted private key in PEM format\n" -" -pass str Password to decrypt private key\n" +" -pass str Password to decrypt private key, prompt if not given\n" " -cert_request Client certificate request\n" " -client_cert_optional Allow client send empty Certificate\n" " -cacert pem CA certificate for client certificate verification\n" @@ -120,6 +121,7 @@ int tls13_server_main(int argc , char **argv) char *keyfiles[sizeof(certfiles)/sizeof(certfiles[0])]; size_t keyfiles_cnt = 0; char *passes[sizeof(certfiles)/sizeof(certfiles[0])]; + char passbufs[sizeof(certfiles)/sizeof(certfiles[0])][GMSSL_PASSWORD_MAX_SIZE] = {{0}}; size_t passes_cnt = 0; TLS_CTX ctx; @@ -342,11 +344,22 @@ bad: } - // 不应该放在这里啊 - if (certfiles_cnt != keyfiles_cnt || keyfiles_cnt != passes_cnt) { + if (passes_cnt > keyfiles_cnt) { error_print(); return -1; } + if (certfiles_cnt != keyfiles_cnt) { + error_print(); + return -1; + } + for (i = passes_cnt; i < keyfiles_cnt; i++) { + if (gmssl_tool_read_password(prog, "Password to decrypt private key", + keyfiles[i], passbufs[i], sizeof(passbufs[i])) != 1) { + goto end; + } + passes[i] = passbufs[i]; + } + passes_cnt = keyfiles_cnt; if (!cipher_suites_cnt) { error_print(); @@ -667,5 +680,6 @@ bad: end: + gmssl_secure_clear(passbufs, sizeof(passbufs)); return ret; }