diff --git a/CMakeLists.txt b/CMakeLists.txt index c0d95770..67525494 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,8 +12,6 @@ include_directories(include) add_library( gmssl - SHARED - src/aes.c src/aes_modes.c src/asn1.c @@ -78,49 +76,36 @@ SET_TARGET_PROPERTIES(gmssl PROPERTIES VERSION 3.0 SOVERSION 3) # tools -add_executable (sm2keygen tools/sm2keygen.c) -add_executable (sm2sign tools/sm2sign.c) -add_executable (sm2verify tools/sm2verify.c) -add_executable (sm2encrypt tools/sm2encrypt.c) -add_executable (sm2decrypt tools/sm2decrypt.c) -add_executable (sm3 tools/sm3.c) -add_executable (sm3hmac tools/sm3hmac.c) -add_executable (sm4 tools/sm4.c) -add_executable (certgen tools/certgen.c) -add_executable (certparse tools/certparse.c) -add_executable (certverify tools/certverify.c) -add_executable (crlparse tools/crlparse.c) -add_executable (reqgen tools/reqgen.c) -add_executable (reqparse tools/reqparse.c) -add_executable (reqsign tools/reqsign.c) -add_executable (tlcp_client tools/tlcp_client.c) -add_executable (tlcp_server tools/tlcp_server.c) -add_executable (tls12_client tools/tls12_client.c) -add_executable (tls12_server tools/tls12_server.c) -add_executable (tls13_client tools/tls13_client.c) -add_executable (tls13_server tools/tls13_server.c) +add_executable( + gmssl-bin + tools/gmssl.c + tools/rand.c + tools/sm2keygen.c + tools/sm2sign.c + tools/sm2verify.c + tools/sm2encrypt.c + tools/sm2decrypt.c + tools/sm3.c + tools/sm3hmac.c + tools/sm4.c + tools/certgen.c + tools/certparse.c + tools/certverify.c + tools/crlparse.c + tools/pbkdf2.c + tools/reqgen.c + tools/reqparse.c + tools/reqsign.c + tools/tlcp_client.c + tools/tlcp_server.c + tools/tls12_client.c + tools/tls12_server.c + tools/tls13_client.c + tools/tls13_server.c +) +target_link_libraries (gmssl-bin LINK_PUBLIC gmssl) +set_target_properties (gmssl-bin PROPERTIES RUNTIME_OUTPUT_NAME gmssl) -target_link_libraries (sm2keygen LINK_PUBLIC gmssl) -target_link_libraries (sm2sign LINK_PUBLIC gmssl) -target_link_libraries (sm2verify LINK_PUBLIC gmssl) -target_link_libraries (sm2encrypt LINK_PUBLIC gmssl) -target_link_libraries (sm2decrypt LINK_PUBLIC gmssl) -target_link_libraries (sm3 LINK_PUBLIC gmssl) -target_link_libraries (sm3hmac LINK_PUBLIC gmssl) -target_link_libraries (sm4 LINK_PUBLIC gmssl) -target_link_libraries (reqgen LINK_PUBLIC gmssl) -target_link_libraries (reqparse LINK_PUBLIC gmssl) -target_link_libraries (reqsign LINK_PUBLIC gmssl) -target_link_libraries (certgen LINK_PUBLIC gmssl) -target_link_libraries (certparse LINK_PUBLIC gmssl) -target_link_libraries (certverify LINK_PUBLIC gmssl) -target_link_libraries (crlparse LINK_PUBLIC gmssl) -target_link_libraries (tlcp_client LINK_PUBLIC gmssl) -target_link_libraries (tlcp_server LINK_PUBLIC gmssl) -target_link_libraries (tls12_client LINK_PUBLIC gmssl) -target_link_libraries (tls12_server LINK_PUBLIC gmssl) -target_link_libraries (tls13_client LINK_PUBLIC gmssl) -target_link_libraries (tls13_server LINK_PUBLIC gmssl) # tests enable_testing() @@ -231,7 +216,6 @@ add_executable(tlstest tests/tlstest.c) target_link_libraries (tlstest LINK_PUBLIC gmssl) - enable_testing() add_test(NAME aes COMMAND aestest) add_test(NAME asn1 COMMAND asn1test) @@ -272,9 +256,7 @@ add_test(NAME x509_ext COMMAND x509_exttest) add_test(NAME zuc COMMAND zuctest) -INSTALL(TARGETS sm3 sm3hmac sm4 sm2keygen sm2sign sm2verify sm2encrypt sm2decrypt RUNTIME DESTINATION bin) -INSTALL(TARGETS certparse certgen certverify reqgen reqparse reqsign RUNTIME DESTINATION bin) -INSTALL(TARGETS tlcp_client tlcp_server tls12_client tls12_server RUNTIME DESTINATION bin) INSTALL(TARGETS gmssl LIBRARY DESTINATION lib) INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/include/gmssl DESTINATION include) +INSTALL(TARGETS gmssl RUNTIME DESTINATION bin) diff --git a/include/gmssl/gf128.h b/include/gmssl/gf128.h index a795619e..5762e1ed 100644 --- a/include/gmssl/gf128.h +++ b/include/gmssl/gf128.h @@ -55,6 +55,9 @@ #define GMSSL_GF128_H +#include +#include +#include #include @@ -62,28 +65,24 @@ extern "C" { #endif -#define GMSSL_HAVE_UINT128 -#ifdef GMSSL_HAVE_UINT128 -typedef unsigned __int128 gf128_t; -#else +//typedef unsigned __int128 gf128_t; + typedef struct { uint64_t hi; uint64_t lo; } gf128_t; -#endif + +// Note: send by value is comptabile with uint128_t and sse2 gf128_t gf128_from_hex(const char *s); int gf128_equ_hex(gf128_t a, const char *s); - gf128_t gf128_zero(void); - gf128_t gf128_add(gf128_t a, gf128_t b); gf128_t gf128_mul(gf128_t a, gf128_t b); gf128_t gf128_mul2(gf128_t a); gf128_t gf128_from_bytes(const uint8_t p[16]); void gf128_to_bytes(gf128_t a, uint8_t p[16]); - -void gf128_print(const char *s, gf128_t a); +int gf128_print(FILE *fp, int fmt ,int ind, const char *label, gf128_t a); #ifdef __cplusplus diff --git a/include/gmssl/pbkdf2.h b/include/gmssl/pbkdf2.h index a4e63ab0..3ba25574 100644 --- a/include/gmssl/pbkdf2.h +++ b/include/gmssl/pbkdf2.h @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2014 - 2021 The GmSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -53,6 +53,7 @@ #include #include #include +#include #include #ifdef __cplusplus @@ -61,7 +62,8 @@ extern "C" { #define PBKDF2_MIN_ITER 10000 -#define PBKDF2_MIN_SALT_SIZE 64 +#define PBKDF2_MAX_ITER (INT_MAX) +#define PBKDF2_MAX_SALT_SIZE 64 #define PBKDF2_DEFAULT_SALT_SIZE 8 diff --git a/include/gmssl/sm4.h b/include/gmssl/sm4.h index 6d4e0f82..1ffdd35e 100644 --- a/include/gmssl/sm4.h +++ b/include/gmssl/sm4.h @@ -124,6 +124,22 @@ int sm4_cbc_decrypt_update(SM4_CBC_CTX *ctx, const uint8_t *in, size_t inlen, ui int sm4_cbc_decrypt_finish(SM4_CBC_CTX *ctx, uint8_t *out, size_t *outlen); +typedef struct { + SM4_KEY sm4_key; + uint8_t ctr[SM4_BLOCK_SIZE]; + uint8_t block[SM4_BLOCK_SIZE]; + size_t block_nbytes; +} SM4_CTR_CTX; + +int sm4_ctr_encrypt_init(SM4_CTR_CTX *ctx, const uint8_t key[SM4_BLOCK_SIZE], const uint8_t ctr[SM4_BLOCK_SIZE]); +int sm4_ctr_encrypt_update(SM4_CTR_CTX *ctx, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen); +int sm4_ctr_encrypt_finish(SM4_CTR_CTX *ctx, uint8_t *out, size_t *outlen); + +#define sm4_ctr_decrypt_init(ctx,key,ctr) sm4_ctr_encrypt_init(ctx,key,ctr) +#define sm4_ctr_decrypt_update(ctx,in,inlen,out,outlen) sm4_ctr_encrypt_update(ctx,in,inlen,out,outlen) +#define sm4_ctr_decrypt_finish(ctx,out,outlen) sm4_ctr_encrypt_finish(ctx,out,outlen) + + #ifdef __cplusplus } #endif diff --git a/src/gf128.c b/src/gf128.c index f5d57779..109ac71b 100644 --- a/src/gf128.c +++ b/src/gf128.c @@ -59,6 +59,7 @@ #include #include "endian.h" + gf128_t gf128_zero(void) { uint8_t zero[16] = {0}; @@ -87,92 +88,31 @@ int gf128_equ_hex(gf128_t a, const char *s) void gf128_print_bits(gf128_t a) { int i; - for (i = 0; i < 128; i++) { - printf("%d", (int)(a % 2)); //FIXME - a >>= 1; + for (i = 0; i < 64; i++) { + printf("%d", (int)(a.hi % 2)); + a.hi >>= 1; + } + for (i = 0; i < 64; i++) { + printf("%d", (int)(a.lo % 2)); + a.lo >>= 1; } printf("\n"); } -void gf128_print(const char *s, gf128_t a) +int gf128_print(FILE *fp, int fmt, int ind, const char *label, gf128_t a) { uint8_t be[16]; int i; - printf("%s", s); + printf("%s", label); gf128_to_bytes(a, be); for (i = 0; i < 16; i++) { printf("%02X", be[i]); } printf("\n"); + return 1; } -#ifdef GMSSL_HAVE_UINT128 -gf128_t gf128_mul(gf128_t a, gf128_t b) -{ - const gf128_t mask = (gf128_t)1 << 127; - - gf128_t r = 0; - int i; - - for (i = 0; i < 128; i++) { - // r = r * 2 - if (r & mask) - r = (r << 1) ^ 0x87; - else r <<= 1; - - // if b[127-i] == 1, r = r + a - if (b & mask) - r ^= a; - b <<= 1; - } - return r; -} - -gf128_t gf128_add(gf128_t a, gf128_t b) -{ - return a ^ b; -} - -gf128_t gf128_mul2(gf128_t a) -{ - if (a & ((gf128_t)1 << 127)) - return (a << 1) ^ 0x87; - else return (a << 1); -} - -gf128_t gf128_reverse(gf128_t a) -{ - gf128_t r = 0; - int i; - - for (i = 0; i < 128; i++) { - r = (r << 1) | (a & 1); - a >>= 1; - } - return r; -} - -gf128_t gf128_from_bytes(const uint8_t p[16]) -{ - uint64_t hi = GETU64(p); - uint64_t lo = GETU64(p + 8); - gf128_t r = (gf128_t)hi << 64 | lo; - r = gf128_reverse(r); - return r; -} - -void gf128_to_bytes(gf128_t a, uint8_t p[16]) -{ - a = gf128_reverse(a); - uint64_t hi = a >> 64; - uint64_t lo = a; - PUTU64(p, hi); - PUTU64(p + 8, lo); -} - - -#else gf128_t gf128_from_bytes(const uint8_t p[16]) { gf128_t r; @@ -253,4 +193,68 @@ gf128_t gf128_mul2(gf128_t a) return r; } -#endif + +/* +gf128_t gf128_mul(gf128_t a, gf128_t b) +{ + const gf128_t mask = (gf128_t)1 << 127; + + gf128_t r = 0; + int i; + + for (i = 0; i < 128; i++) { + // r = r * 2 + if (r & mask) + r = (r << 1) ^ 0x87; + else r <<= 1; + + // if b[127-i] == 1, r = r + a + if (b & mask) + r ^= a; + b <<= 1; + } + return r; +} + +gf128_t gf128_add(gf128_t a, gf128_t b) +{ + return a ^ b; +} + +gf128_t gf128_mul2(gf128_t a) +{ + if (a & ((gf128_t)1 << 127)) + return (a << 1) ^ 0x87; + else return (a << 1); +} + +gf128_t gf128_reverse(gf128_t a) +{ + gf128_t r = 0; + int i; + + for (i = 0; i < 128; i++) { + r = (r << 1) | (a & 1); + a >>= 1; + } + return r; +} + +gf128_t gf128_from_bytes(const uint8_t p[16]) +{ + uint64_t hi = GETU64(p); + uint64_t lo = GETU64(p + 8); + gf128_t r = (gf128_t)hi << 64 | lo; + r = gf128_reverse(r); + return r; +} + +void gf128_to_bytes(gf128_t a, uint8_t p[16]) +{ + a = gf128_reverse(a); + uint64_t hi = a >> 64; + uint64_t lo = a; + PUTU64(p, hi); + PUTU64(p + 8, lo); +} +*/ diff --git a/src/sm4_modes.c b/src/sm4_modes.c index 1da9bb8b..7b35ae81 100644 --- a/src/sm4_modes.c +++ b/src/sm4_modes.c @@ -239,7 +239,6 @@ int sm4_gcm_decrypt(const SM4_KEY *key, const uint8_t *iv, size_t ivlen, return 1; } - int sm4_cbc_encrypt_init(SM4_CBC_CTX *ctx, const uint8_t key[SM4_BLOCK_SIZE], const uint8_t iv[SM4_BLOCK_SIZE]) { @@ -303,9 +302,6 @@ int sm4_cbc_encrypt_finish(SM4_CBC_CTX *ctx, uint8_t *out, size_t *outlen) error_print(); return -1; } - - format_bytes(stderr, 0, 0, "encrypt_finish", ctx->block, ctx->block_nbytes); - if (sm4_cbc_padding_encrypt(&ctx->sm4_key, ctx->iv, ctx->block, ctx->block_nbytes, out, outlen) != 1) { error_print(); return -1; @@ -370,13 +366,74 @@ int sm4_cbc_decrypt_finish(SM4_CBC_CTX *ctx, uint8_t *out, size_t *outlen) error_print(); return -1; } - format_bytes(stderr, 0, 0, "block", ctx->block, ctx->block_nbytes); - format_bytes(stderr, 0, 0, "iv", ctx->iv, 16); - - if (sm4_cbc_padding_decrypt(&ctx->sm4_key, ctx->iv, ctx->block, SM4_BLOCK_SIZE, out, outlen) != 1) { error_print(); return -1; } return 1; } + +int sm4_ctr_encrypt_init(SM4_CTR_CTX *ctx, + const uint8_t key[SM4_BLOCK_SIZE], const uint8_t ctr[SM4_BLOCK_SIZE]) +{ + sm4_set_encrypt_key(&ctx->sm4_key, key); + memcpy(ctx->ctr, ctr, SM4_BLOCK_SIZE); + memset(ctx->block, 0, SM4_BLOCK_SIZE); + ctx->block_nbytes = 0; + return 1; +} + +int sm4_ctr_encrypt_update(SM4_CTR_CTX *ctx, + const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) +{ + size_t left; + size_t nblocks; + size_t len; + + if (ctx->block_nbytes >= SM4_BLOCK_SIZE) { + error_print(); + return -1; + } + *outlen = 0; + if (ctx->block_nbytes) { + left = SM4_BLOCK_SIZE - ctx->block_nbytes; + if (inlen < left) { + memcpy(ctx->block + ctx->block_nbytes, in, inlen); + ctx->block_nbytes += inlen; + return 1; + } + memcpy(ctx->block + ctx->block_nbytes, in, left); + sm4_ctr_encrypt(&ctx->sm4_key, ctx->ctr, ctx->block, SM4_BLOCK_SIZE, out); + in += left; + inlen -= left; + out += SM4_BLOCK_SIZE; + *outlen += SM4_BLOCK_SIZE; + } + if (inlen >= SM4_BLOCK_SIZE) { + nblocks = inlen / SM4_BLOCK_SIZE; + len = nblocks * SM4_BLOCK_SIZE; + sm4_ctr_encrypt(&ctx->sm4_key, ctx->ctr, in, len, out); + in += len; + inlen -= len; + out += len; + *outlen += len; + } + if (inlen) { + memcpy(ctx->block, in, inlen); + } + ctx->block_nbytes = inlen; + return 1; +} + +int sm4_ctr_encrypt_finish(SM4_CTR_CTX *ctx, uint8_t *out, size_t *outlen) +{ + size_t left; + size_t i; + + if (ctx->block_nbytes >= SM4_BLOCK_SIZE) { + error_print(); + return -1; + } + sm4_ctr_encrypt(&ctx->sm4_key, ctx->ctr, ctx->block, ctx->block_nbytes, out); + return 1; +} diff --git a/tests/gf128test.c b/tests/gf128test.c index cf0301b3..cf76eb98 100644 --- a/tests/gf128test.c +++ b/tests/gf128test.c @@ -87,9 +87,9 @@ int main(void) gf128_t T = gf128_mul(C, H); - gf128_print("C = ", C); - gf128_print("H = ", H); - gf128_print("C * H = ", T); + gf128_print(stderr, 0, 0, "C", C); + gf128_print(stderr, 0, 0, "H", H); + gf128_print(stderr, 0, 0, "C * H", T); return 0; } diff --git a/tests/sm4test.c b/tests/sm4test.c index 25a3f605..01fdfa3c 100644 --- a/tests/sm4test.c +++ b/tests/sm4test.c @@ -166,43 +166,6 @@ static int test_ctr32(int avx) return 0; } - -/* -static int test_ede(void) -{ - SM4_KEY key; - sm4_ede_key_t ede_key; - unsigned char user_key[48]; - unsigned char in[16]; - unsigned char out1[16]; - unsigned char out2[16]; - - RAND_bytes(in, sizeof(in)); - - RAND_bytes(user_key, 16); - memcpy(user_key + 16, user_key, 16); - memcpy(user_key + 32, user_key, 16); - sm4_set_encrypt_key(&key, user_key); - sm4_encrypt(in, out1, &key); - sm4_ede_set_encrypt_key(&ede_key, user_key); - sm4_ede_encrypt(in, out2, &ede_key); - if (memcmp(out1, out2, 16) != 0) { - return 0; - } - - RAND_bytes(user_key, sizeof(user_key)); - sm4_ede_set_encrypt_key(&ede_key, user_key); - sm4_ede_encrypt(in, out1, &ede_key); - sm4_ede_set_decrypt_key(&ede_key, user_key); - sm4_ede_decrypt(out1, out2, &ede_key); - if (memcmp(in, out2, 16) != 0) { - return 0; - } - - return 1; -} -*/ - int test_sm4(void) { int err = 0; @@ -281,16 +244,6 @@ int test_sm4(void) } else printf("sm4 ctr32 pass!\n"); - /* test ede */ -/* - if (!test_ede()) { - printf("sm4 ede not pass!\n"); - err++; - } else - printf("sm4 ede pass!\n"); -*/ - - # ifdef SM4_AVX2 /* test ecb in avx2 */ if (!test_ecb(2)) { diff --git a/tools/README.md b/tools/README.md index d887ceb7..4d4dd049 100644 --- a/tools/README.md +++ b/tools/README.md @@ -1,5 +1,10 @@ # 命令行工具 +注意: + +* 命令行工具接口在v3版本正式发布前还会有较大调整 +* SM2, SM3, SM4等算法的命令相对比较底层,是对C语言接口的简单封装,命令行的应用开发者需要组合使用这些指令 + 命令行工具: * `sm3` 计算SM3杂凑值,支持带公钥和ID的Z值计算 @@ -14,3 +19,23 @@ * `certparse` 解析打印证书 * `certverify` 验证证书链 +TLS功能 + +* `tlcp_client` +* `tlcp_server` +* `tls12_client` +* `tls12_server` +* `tls13_client` +* `tls13_server` + +私钥总是默认以口令加密的方式存储 +SM3/HMAC-SM3 以二进制的格式输出 +签名和SM2Ciphertext以DER编码输出 + + +应该提供一个口令导出密钥的算法,由口令导出密钥 + +SM4加密需要外部提供key, iv +HMAC-SM3可以用命令行的方式拼合 +因此没必要提供一个单独的SM4-CBC-HMAC-SM3 + diff --git a/tools/certgen.c b/tools/certgen.c index 00a1ceb8..5f1827e7 100644 --- a/tools/certgen.c +++ b/tools/certgen.c @@ -79,7 +79,7 @@ static const char *options = "[-key_usage str]*"; -int main(int argc, char **argv) +int certgen_main(int argc, char **argv) { int ret = 1; char *prog = argv[0]; diff --git a/tools/certparse.c b/tools/certparse.c index b77c56ef..d04a12ce 100644 --- a/tools/certparse.c +++ b/tools/certparse.c @@ -55,7 +55,7 @@ static const char *options = "[-in file]"; -int main(int argc, char **argv) +int certparse_main(int argc, char **argv) { char *prog = argv[0]; char *infile = NULL; diff --git a/tools/certverify.c b/tools/certverify.c index cb0bc64d..d6e9f914 100644 --- a/tools/certverify.c +++ b/tools/certverify.c @@ -59,7 +59,7 @@ // 比如最基本的是证书中的签名、有效期、各个扩展等 // 外部相关的:证书链、CRL等 -int main(int argc, char **argv) +int certverify_main(int argc, char **argv) { int ret = 0; char *prog = argv[0]; diff --git a/tools/crlparse.c b/tools/crlparse.c index a33802c7..1f284836 100644 --- a/tools/crlparse.c +++ b/tools/crlparse.c @@ -56,7 +56,7 @@ static const char *options = "[-in file]"; -int main(int argc, char **argv) +int crlparse_main(int argc, char **argv) { char *prog = argv[0]; char *infile = NULL; diff --git a/tools/gmssl.c b/tools/gmssl.c new file mode 100644 index 00000000..7dbee795 --- /dev/null +++ b/tools/gmssl.c @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2021 - 2021 The GmSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +extern int rand_main(int argc, char **argv); +extern int certgen_main(int argc, char **argv); +extern int certparse_main(int argc, char **argv); +extern int certverify_main(int argc, char **argv); +extern int crlparse_main(int argc, char **argv); +extern int pbkdf2_main(int argc, char **argv); +extern int reqgen_main(int argc, char **argv); +extern int reqparse_main(int argc, char **argv); +extern int reqsign_main(int argc, char **argv); +extern int sm2decrypt_main(int argc, char **argv); +extern int sm2encrypt_main(int argc, char **argv); +extern int sm2keygen_main(int argc, char **argv); +extern int sm2sign_main(int argc, char **argv); +extern int sm2verify_main(int argc, char **argv); +extern int sm3_main(int argc, char **argv); +extern int sm3hmac_main(int argc, char **argv); +extern int sm4_main(int argc, char **argv); +extern int tlcp_client_main(int argc, char **argv); +extern int tlcp_server_main(int argc, char **argv); +extern int tls12_client_main(int argc, char **argv); +extern int tls12_server_main(int argc, char **argv); +extern int tls13_client_main(int argc, char **argv); +extern int tls13_server_main(int argc, char **argv); + + +static const char *options = + " commands:\n" + " help\n" + " version\n" + " rand\n" + " sm2keygen\n" + " sm2sign\n" + " sm2verify\n" + " sm2encrypt\n" + " sm2decrypt\n" + " pbkdf2\n" + " reqgen\n" + " reqsign\n" + " reqparse\n" + " crlparse\n" + " certgen\n" + " certparse\n" + " certverify\n" + " tlcp_client\n" + " tlcp_server\n" + " tls12_client\n" + " tls12_server\n" + " tls13_client\n" + " tls13_server\n"; + + +int version_main(int argc, char **argv) +{ + printf("%s\n", gmssl_version_str()); + return 0; +} + + +int main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + + + if (argc < 2) { + printf("usage: %s\n %s\n", prog, options); + return 0; + } + + argc--; + argv++; + + while (argc > 0) { + if (!strcmp(*argv, "help")) { +help: + printf("usage: %s\n %s\n", prog, options); + return 0; + } else if (!strcmp(*argv, "version")) { + return version_main(argc, argv); + } else if (!strcmp(*argv, "rand")) { + return rand_main(argc, argv); + } else if (!strcmp(*argv, "certgen")) { + return certgen_main(argc, argv); + } else if (!strcmp(*argv, "certparse")) { + return certparse_main(argc, argv); + } else if (!strcmp(*argv, "certverify")) { + return certverify_main(argc, argv); + } else if (!strcmp(*argv, "reqgen")) { + return reqgen_main(argc, argv); + } else if (!strcmp(*argv, "reqparse")) { + return reqparse_main(argc, argv); + } else if (!strcmp(*argv, "reqsign")) { + return reqsign_main(argc, argv); + } else if (!strcmp(*argv, "pbkdf2")) { + return pbkdf2_main(argc, argv); + } else if (!strcmp(*argv, "sm2sign")) { + return sm2sign_main(argc, argv); + } else if (!strcmp(*argv, "sm2verify")) { + return sm2verify_main(argc, argv); + } else if (!strcmp(*argv, "sm2encrypt")) { + return sm2encrypt_main(argc, argv); + } else if (!strcmp(*argv, "sm2decrypt")) { + return sm2decrypt_main(argc, argv); + } else if (!strcmp(*argv, "sm2keygen")) { + return sm2keygen_main(argc, argv); + } else if (!strcmp(*argv, "tlcp_client")) { + return tlcp_client_main(argc, argv); + } else if (!strcmp(*argv, "tlcp_server")) { + return tlcp_server_main(argc, argv); + } else if (!strcmp(*argv, "tls12_client")) { + return tls12_client_main(argc, argv); + } else if (!strcmp(*argv, "tls12_server")) { + return tls12_server_main(argc, argv); + } else if (!strcmp(*argv, "tls13_client")) { + return tls13_client_main(argc, argv); + } else if (!strcmp(*argv, "tls13_server")) { + return tls13_server_main(argc, argv); + } else { +bad: + fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv); + fprintf(stderr, "usage: %s %s\n", prog, options); + return 1; + } + + argc--; + argv++; + } + + return ret; +} diff --git a/tools/pbkdf2.c b/tools/pbkdf2.c new file mode 100644 index 00000000..bdeadc2f --- /dev/null +++ b/tools/pbkdf2.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2020 - 2021 The GmSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include + + +static const char *options = "-salt hex -iter num [-pass str] -outlen num"; + +int pbkdf2_main(int argc, char **argv) +{ + int ret = -1; + char *prog = argv[0]; + char *salthex = NULL; + uint8_t salt[PBKDF2_MAX_SALT_SIZE]; + size_t saltlen; + int iter = 0; + char *pass = NULL; + int outlen = 0; + uint8_t outbuf[64]; + int i; + + argc--; + argv++; + + if (argc < 1) { + fprintf(stderr, "usage: %s %s\n", prog, options); + return 1; + } + + while (argc > 0) { + if (!strcmp(*argv, "-help")) { + fprintf(stderr, "usage: %s %s\n", prog, options); + return 1; + } else if (!strcmp(*argv, "-salt")) { + if (--argc < 1) goto bad; + salthex = *(++argv); + } else if (!strcmp(*argv, "-iter")) { + if (--argc < 1) goto bad; + iter = atoi(*(++argv)); + if (iter < PBKDF2_MIN_ITER || iter > INT_MAX) { + error_print(); + return 1; + } + } else if (!strcmp(*argv, "-pass")) { + if (--argc < 1) goto bad; + pass = *(++argv); + } else if (!strcmp(*argv, "-outlen")) { + if (--argc < 1) goto bad; + outlen = atoi(*(++argv)); + if (outlen < 1 || outlen > sizeof(outbuf)) { + error_print(); + return 1; + } + } else { + fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv); + return 1; +bad: + fprintf(stderr, "%s: invalid option argument\n", prog); + return 1; + } + + argc--; + argv++; + } + + if (!salthex) { + error_print(); + return 1; + } + if (strlen(salthex) > sizeof(salt) * 2) { + error_print(); + return 1; + } + if (hex_to_bytes(salthex, strlen(salthex), salt, &saltlen) != 1) { + error_print(); + return 1; + } + + if (!iter) { + error_print(); + return 1; + } + if (!outlen) { + error_print(); + return 1; + } + + + if (!pass) { + error_print(); + return -1; + } + + if (pbkdf2_hmac_sm3_genkey(pass, strlen(pass), salt, saltlen, iter, outlen, outbuf) != 1) { + error_print(); + return -1; + } + for (i = 0; i < outlen; i++) { + printf("%02X", outbuf[i]); + } + printf("\n"); + + + return 0; +} diff --git a/tools/rand.c b/tools/rand.c new file mode 100644 index 00000000..0332655a --- /dev/null +++ b/tools/rand.c @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2020 - 2021 The GmSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include + + +static const char *options = "[-hex] [-rdrand] -outlen num"; + +int rand_main(int argc, char **argv) +{ + int ret = -1; + char *prog = argv[0]; + int hex = 0; + int rdrand = 0; + int outlen = 0; + uint8_t buf[2048]; + int i; + + argc--; + argv++; + + if (argc < 1) { + fprintf(stderr, "usage: %s %s\n", prog, options); + return 1; + } + + while (argc > 0) { + if (!strcmp(*argv, "-help")) { + fprintf(stderr, "usage: %s %s\n", prog, options); + return 1; + } else if (!strcmp(*argv, "-hex")) { + hex = 1; + } else if (!strcmp(*argv, "-rdrand")) { + // rdrand = 1; // FIXME: CMakeList.txt should be updated to support this option + } else if (!strcmp(*argv, "-outlen")) { + if (--argc < 1) goto bad; + outlen = atoi(*(++argv)); + if (outlen < 1 || outlen > INT_MAX) { + error_print(); + return 1; + } + } else { + fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv); + return 1; +bad: + fprintf(stderr, "%s: invalid option argument\n", prog); + return 1; + } + + argc--; + argv++; + } + + if (!outlen) { + error_print(); + return 1; + } + + while (outlen) { + size_t len = outlen < sizeof(buf) ? outlen : sizeof(buf); + + if (rdrand) { +/* + if (rdrand_bytes(buf, len) != 1) { + error_print(); + return 1; + } +*/ + } else { + if (rand_bytes(buf, len) != 1) { + error_print(); + return -1; + } + } + + if (hex) { + int i; + for (i = 0; i < len; i++) { + fprintf(stdout, "%02X", buf[i]); + } + } else { + fwrite(buf, 1, len, stdout); + } + + outlen -= len; + } + + if (hex) { + fprintf(stdout, "\n"); + } + + return 0; +} diff --git a/tools/reqgen.c b/tools/reqgen.c index c0d7cdc1..388b33a8 100644 --- a/tools/reqgen.c +++ b/tools/reqgen.c @@ -66,7 +66,7 @@ static const char *options = "[-C str] [-ST str] [-L str] [-O str] [-OU str] -CN str -days num" " -key file [-pass pass] [-out file]"; -int main(int argc, char **argv) +int reqgen_main(int argc, char **argv) { int ret = -1; char *prog = argv[0]; diff --git a/tools/reqparse.c b/tools/reqparse.c index 884a748d..6363d0f3 100644 --- a/tools/reqparse.c +++ b/tools/reqparse.c @@ -55,7 +55,7 @@ #include -int main(int argc, char **argv) +int reqparse_main(int argc, char **argv) { char *prog = argv[0]; char *infile = NULL; diff --git a/tools/reqsign.c b/tools/reqsign.c index 0f859aaa..49dc3d08 100644 --- a/tools/reqsign.c +++ b/tools/reqsign.c @@ -75,7 +75,7 @@ static int ext_key_usage_set(int *usages, const char *usage_name) static const char *usage = "usage: %s [-in file] -days num -cacert file -key file [-pass str] [-out file]\n"; -int main(int argc, char **argv) +int reqsign_main(int argc, char **argv) { char *prog = argv[0]; char *file; diff --git a/tools/sm2decrypt.c b/tools/sm2decrypt.c index ba6947c6..92f38b84 100644 --- a/tools/sm2decrypt.c +++ b/tools/sm2decrypt.c @@ -62,7 +62,7 @@ #endif -int main(int argc, char **argv) +int sm2decrypt_main(int argc, char **argv) { char *prog = argv[0]; char *keyfile = NULL; diff --git a/tools/sm2encrypt.c b/tools/sm2encrypt.c index dfa5b777..45c4f069 100644 --- a/tools/sm2encrypt.c +++ b/tools/sm2encrypt.c @@ -58,7 +58,7 @@ #include -int main(int argc, char **argv) +int sm2encrypt_main(int argc, char **argv) { int ret; char *prog = argv[0]; diff --git a/tools/sm2keygen.c b/tools/sm2keygen.c index a2f383e1..a48a175f 100644 --- a/tools/sm2keygen.c +++ b/tools/sm2keygen.c @@ -59,7 +59,7 @@ #include #endif -int main(int argc, char **argv) +int sm2keygen_main(int argc, char **argv) { char *prog = argv[0]; char *pass = NULL; diff --git a/tools/sm2sign.c b/tools/sm2sign.c index 538258b5..c1d4a6fa 100644 --- a/tools/sm2sign.c +++ b/tools/sm2sign.c @@ -64,7 +64,7 @@ // echo data | sm2sign -id "Alice" -keyfile sm2.pem // echo data | sm2verify -id "Alice" -keyfile sm2pub.pem -certfile a -cacertfile b -int main(int argc, char **argv) +int sm2sign_main(int argc, char **argv) { char *prog = argv[0]; char *keyfile = NULL; diff --git a/tools/sm2verify.c b/tools/sm2verify.c index 96e03ce6..e75755e0 100644 --- a/tools/sm2verify.c +++ b/tools/sm2verify.c @@ -60,7 +60,7 @@ // sm2verify [-in file] {-pubkey pem | -cert pem} [-id str] -sig file -int main(int argc, char **argv) +int sm2verify_main(int argc, char **argv) { int ret; char *prog = argv[0]; diff --git a/tools/sm3.c b/tools/sm3.c index cec1298f..412d6d54 100644 --- a/tools/sm3.c +++ b/tools/sm3.c @@ -54,7 +54,7 @@ #include -int main(int argc, char **argv) +int sm3_main(int argc, char **argv) { char *prog = argv[0]; char *pubkeyfile = NULL; diff --git a/tools/sm3hmac.c b/tools/sm3hmac.c index fcf8478f..83037f57 100644 --- a/tools/sm3hmac.c +++ b/tools/sm3hmac.c @@ -54,7 +54,7 @@ #include -int main(int argc, char **argv) +int sm3hmac_main(int argc, char **argv) { int ret = -1; char *prog = argv[0]; diff --git a/tools/sm4.c b/tools/sm4.c index b3dd21f2..5189aecc 100644 --- a/tools/sm4.c +++ b/tools/sm4.c @@ -53,10 +53,14 @@ #include #include -static const char *options = "-key hex -iv hex [-in file] [-out file]"; + +#define SM4_MODE_CBC 1 +#define SM4_MODE_CTR 2 + +static const char *options = "{-cbc|-ctr} {-encrypt|-decrypt} -key hex -iv hex [-in file] [-out file]"; -int main(int argc, char **argv) +int sm4_main(int argc, char **argv) { char *prog = argv[0]; char *keystr = NULL; @@ -69,8 +73,10 @@ int main(int argc, char **argv) size_t ivlen = sizeof(iv); FILE *infp = stdin; FILE *outfp = stdout; + int mode = 0; int enc = -1; SM4_CBC_CTX cbc_ctx; + SM4_CTR_CTX ctr_ctx; uint8_t inbuf[4096]; size_t inlen; uint8_t outbuf[4196]; @@ -98,6 +104,12 @@ int main(int argc, char **argv) enc = 1; } else if (!strcmp(*argv, "-decrypt")) { enc = 0; + } else if (!strcmp(*argv, "-cbc")) { + if (mode) goto bad; + mode = SM4_MODE_CBC; + } else if (!strcmp(*argv, "-ctr")) { + if (mode) goto bad; + mode = SM4_MODE_CTR; } else if (!strcmp(*argv, "-in")) { if (--argc < 1) goto bad; infile = *(++argv); @@ -116,6 +128,10 @@ bad: argv++; } + if (!mode) { + fprintf(stderr, "%s: mode not assigned, -cbc or -ctr option required\n", prog); + return 1; + } if (!keystr) { error_print(); @@ -157,6 +173,36 @@ bad: } } + + if (mode == SM4_MODE_CTR) { + if (sm4_ctr_encrypt_init(&ctr_ctx, key, iv) != 1) { + error_print(); + return -1; + } + while ((inlen = fread(inbuf, 1, sizeof(inbuf), infp)) > 0) { + if (sm4_ctr_encrypt_update(&ctr_ctx, inbuf, inlen, outbuf, &outlen) != 1) { + error_print(); + return -1; + } + if (fwrite(outbuf, 1, outlen, outfp) != outlen) { + error_print(); + return -1; + } + } + if (sm4_ctr_encrypt_finish(&ctr_ctx, outbuf, &outlen) != 1) { + error_print(); + return -1; + } + if (fwrite(outbuf, 1, outlen, outfp) != outlen) { + error_print(); + return -1; + } + + + return 0; + } + + if (enc < 0) { error_print(); return -1; @@ -186,8 +232,6 @@ bad: return -1; } - - } else { if (sm4_cbc_decrypt_init(&cbc_ctx, key, iv) != 1) { error_print(); diff --git a/tools/tlcp_client.c b/tools/tlcp_client.c index af8def40..a116461c 100644 --- a/tools/tlcp_client.c +++ b/tools/tlcp_client.c @@ -54,7 +54,7 @@ #include -const char *http_get = +static const char *http_get = "GET / HTTP/1.1\r\n" "Hostname: aaa\r\n" "\r\n\r\n"; @@ -63,7 +63,7 @@ const char *http_get = // 虽然服务器可以用双证书,但是客户端只能使用一个证书,也就是签名证书 static const char *options = "-host str [-port num] [-cacert file] [-cert file -key file [-pass str]]"; -int main(int argc, char *argv[]) +int tlcp_client_main(int argc, char *argv[]) { int ret = -1; char *prog = argv[0]; diff --git a/tools/tlcp_server.c b/tools/tlcp_server.c index dcd6df00..a9cf60db 100644 --- a/tools/tlcp_server.c +++ b/tools/tlcp_server.c @@ -58,7 +58,7 @@ static const char *options = "[-port num] -cert file -key file [-pass str] -ex_key file [-ex_pass str] [-cacert file]"; -int main(int argc , char **argv) +int tlcp_server_main(int argc , char **argv) { int ret = -1; char *prog = argv[0]; diff --git a/tools/tls12_client.c b/tools/tls12_client.c index cef77afb..3bcb08a1 100644 --- a/tools/tls12_client.c +++ b/tools/tls12_client.c @@ -62,7 +62,7 @@ const char *http_get = static const char *options = "-host str [-port num] [-cacert file] [-cert file -key file [-pass str]]"; -int main(int argc , char *argv[]) +int tls12_client_main(int argc , char *argv[]) { char *prog = argv[0]; char *host = NULL; diff --git a/tools/tls12_server.c b/tools/tls12_server.c index f1bd7795..d5df670d 100644 --- a/tools/tls12_server.c +++ b/tools/tls12_server.c @@ -58,7 +58,7 @@ // 因此如果提供了CA证书,那么等同于要求客户端验证 static const char *options = " [-port num] -cert file -key file [-pass str] [-cacert file]"; -int main(int argc , char *argv[]) +int tls12_server_main(int argc , char *argv[]) { int ret = -1; char *prog = argv[0]; diff --git a/tools/tls13_client.c b/tools/tls13_client.c index 81473522..9b45d865 100644 --- a/tools/tls13_client.c +++ b/tools/tls13_client.c @@ -54,7 +54,7 @@ #include -const char *http_get = +static const char *http_get = "GET / HTTP/1.1\r\n" "Hostname: aaa\r\n" "\r\n\r\n"; @@ -69,7 +69,7 @@ void print_usage(const char *prog) printf(" -key \n"); } -int main(int argc , char *argv[]) +int tls13_client_main(int argc , char *argv[]) { int ret = -1; char *prog = argv[0]; diff --git a/tools/tls13_server.c b/tools/tls13_server.c index 586e46a4..5f05382d 100644 --- a/tools/tls13_server.c +++ b/tools/tls13_server.c @@ -55,7 +55,7 @@ #include -void print_usage(const char *prog) +static void print_usage(const char *prog) { printf("Usage: %s [options]\n", prog); printf(" -port \n"); @@ -63,7 +63,7 @@ void print_usage(const char *prog) printf(" -signkey \n"); } -int main(int argc , char *argv[]) +int tls13_server_main(int argc , char *argv[]) { int ret = -1; char *prog = argv[0];