diff --git a/CMakeLists.txt b/CMakeLists.txt index c50e8fd0..4cf9f50b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -345,6 +345,7 @@ if (ENABLE_SM4_CCM) set(ENABLE_SM4_CBC_MAC ON) add_definitions(-DENABLE_SM4_CCM) list(APPEND src src/sm4_ccm.c) + list(APPEND tools tools/sm4_ccm.c) list(APPEND tests sm4_ccm) endif() @@ -441,6 +442,7 @@ endif() if (ENABLE_SM4_CBC_MAC) message(STATUS "ENABLE_SM4_CBC_MAC is ON") list(APPEND src src/sm4_cbc_mac.c) + list(APPEND tools tools/sm4_cbc_mac.c) list(APPEND tests sm4_cbc_mac) endif() diff --git a/tools/gmssl.c b/tools/gmssl.c index fb82fb81..998900ab 100644 --- a/tools/gmssl.c +++ b/tools/gmssl.c @@ -41,9 +41,11 @@ extern int sm4_cbc_main(int argc, char **argv); extern int sm4_ctr_main(int argc, char **argv); extern int sm4_cfb_main(int argc, char **argv); extern int sm4_ofb_main(int argc, char **argv); +extern int sm4_ccm_main(int argc, char **argv); extern int sm4_gcm_main(int argc, char **argv); extern int sm4_cbc_sm3_hmac_main(int argc, char **argv); extern int sm4_ctr_sm3_hmac_main(int argc, char **argv); +extern int sm4_cbc_mac_main(int argc, char **argv); extern int zuc_main(int argc, char **argv); extern int sm9setup_main(int argc, char **argv); extern int sm9keygen_main(int argc, char **argv); @@ -91,9 +93,11 @@ static const char *options = " sm4_ctr Encrypt or decrypt with SM4 CTR\n" " sm4_cfb Encrypt or decrypt with SM4 CFB\n" " sm4_ofb Encrypt or decrypt with SM4 OFB\n" + " sm4_ccm Encrypt or decrypt with SM4 CCM\n" " sm4_gcm Encrypt or decrypt with SM4 GCM\n" " sm4_cbc_sm3_hmac Encrypt or decrypt with SM4 CBC with SM3-HMAC\n" " sm4_ctr_sm3_hmac Encrypt or decrypt with SM4 CTR with SM3-HMAC\n" + " sm4_cbc_mac Generate SM4 CBC-MAC\n" " zuc Encrypt or decrypt with ZUC\n" " sm9setup Generate SM9 master secret\n" " sm9keygen Generate SM9 private key\n" @@ -213,6 +217,10 @@ int main(int argc, char **argv) #if ENABLE_SM4_OFB } else if (!strcmp(*argv, "sm4_ofb")) { return sm4_ofb_main(argc, argv); +#endif +#if ENABLE_SM4_CCM + } else if (!strcmp(*argv, "sm4_ccm")) { + return sm4_ccm_main(argc, argv); #endif } else if (!strcmp(*argv, "sm4_gcm")) { return sm4_gcm_main(argc, argv); @@ -220,6 +228,8 @@ int main(int argc, char **argv) return sm4_cbc_sm3_hmac_main(argc, argv); } else if (!strcmp(*argv, "sm4_ctr_sm3_hmac")) { return sm4_ctr_sm3_hmac_main(argc, argv); + } else if (!strcmp(*argv, "sm4_cbc_mac")) { + return sm4_cbc_mac_main(argc, argv); } else if (!strcmp(*argv, "zuc")) { return zuc_main(argc, argv); } else if (!strcmp(*argv, "sm9setup")) { diff --git a/tools/sm4_cbc_mac.c b/tools/sm4_cbc_mac.c new file mode 100644 index 00000000..b1c350d2 --- /dev/null +++ b/tools/sm4_cbc_mac.c @@ -0,0 +1,201 @@ +/* + * Copyright 2014-2023 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 +#include + + +static const char *usage = "-key hex [-in file | -in_str str] [-bin|-hex] [-out file]"; + +static const char *help = +"Options\n" +"\n" +" -key hex Hex string of the MAC key, 16 bytes\n" +" -in_str str Input as text string\n" +" -in file | stdin Input file path\n" +" `-in_str` and `-in` should not be used together\n" +" If neither `-in` nor `-in_str` specified, read from stdin\n" +" -hex Output MAC-tag as hex string (by default)\n" +" -bin Output MAC-tag as binary\n" +" `-hex` and `-bin` should not be used together\n" +" -out file | stdout Output file path. If not specified, output to stdout\n" +"\n" +"Examples\n" +"\n" +" KEY_HEX=`gmssl rand -outlen 16 -hex`\n" +" gmssl sm4_cbc_mac -key $KEY_HEX -in_str abc\n" +"\n" +" gmssl sm4_cbc_mac -key $KEY_HEX -in_str abc -bin\n" +"\n" +" gmssl sm4_cbc_mac -key $KEY_HEX -in /path/to/file\n" +"\n" +" When reading from stdin, make sure the trailing newline character is removed\n" +"\n" +" Linux/Mac:\n" +" echo -n abc | gmssl sm4_cbc_mac -key $KEY_HEX\n" +"\n" +" Windows:\n" +" C:\\> echo |set/p=\"abc\" | gmssl sm4_cbc_mac -key 11223344556677881122334455667788\n" +"\n"; + +int sm4_cbc_mac_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + char *keyhex = NULL; + int outformat = 0; + char *in_str = NULL; + char *infile = NULL; + char *outfile = NULL; + uint8_t key[16]; + size_t keylen; + FILE *infp = stdin; + FILE *outfp = stdout; + SM4_CBC_MAC_CTX ctx; + uint8_t mac[16]; + size_t i; + + argc--; + argv++; + + if (argc < 1) { + fprintf(stderr, "usage: gmssl %s %s\n", prog, usage); + return 1; + } + + while (argc > 0) { + if (!strcmp(*argv, "-help")) { + printf("usage: gmssl %s %s\n", prog, usage); + printf("%s\n", help); + ret = 0; + goto end; + } else if (!strcmp(*argv, "-key")) { + if (--argc < 1) goto bad; + keyhex = *(++argv); + if (strlen(keyhex) > sizeof(key) * 2) { + fprintf(stderr, "gmssl %s: key should be 16 bytes\n", prog); + goto end; + } + if (hex_to_bytes(keyhex, strlen(keyhex), key, &keylen) != 1) { + fprintf(stderr, "gmssl %s: invalid HEX digits\n", prog); + goto end; + } + } else if (!strcmp(*argv, "-hex")) { + if (outformat == 2) { + fprintf(stderr, "gmssl %s: `-hex` and `-bin` should not be used together\n", prog); + goto end; + } + outformat = 1; + } else if (!strcmp(*argv, "-bin")) { + if (outformat == 1) { + fprintf(stderr, "gmssl %s: `-hex` and `-bin` should not be used together\n", prog); + goto end; + } + outformat = 2; + } else if (!strcmp(*argv, "-in_str")) { + if (infile) { + fprintf(stderr, "gmssl %s: `-in` and `-in_str` should not be used together\n", prog); + goto end; + } + if (--argc < 1) goto bad; + in_str = *(++argv); + } else if (!strcmp(*argv, "-in")) { + if (--argc < 1) goto bad; + infile = *(++argv); + if (!(infp = fopen(infile, "rb"))) { + fprintf(stderr, "gmssl %s: open '%s' failure : %s\n", prog, infile, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-out")) { + if (--argc < 1) goto bad; + outfile = *(++argv); + if (!(outfp = fopen(outfile, "wb"))) { + fprintf(stderr, "gmssl %s: open '%s' failure : %s\n", prog, outfile, strerror(errno)); + goto end; + } + } else { + fprintf(stderr, "gmssl %s: illegal option '%s'\n", prog, *argv); + goto end; +bad: + fprintf(stderr, "gmssl %s: '%s' option value missing\n", prog, *argv); + goto end; + } + + argc--; + argv++; + } + + if (!keyhex) { + fprintf(stderr, "gmssl %s: option '-key' required\n", prog); + goto end; + } + + sm4_cbc_mac_init(&ctx, key); + /* + if (sm4_cbc_mac_init(&ctx, key) != 1) { + fprintf(stderr, "gmssl %s: inner error\n", prog); + goto end; + } + */ + + if (in_str) { + sm4_cbc_mac_update(&ctx, (uint8_t *)in_str, strlen(in_str)); + /* + if (sm4_cbc_mac_update(&ctx, (uint8_t *)in_str, strlen(in_str)) != 1) { + fprintf(stderr, "gmssl %s: inner error\n", prog); + goto end; + } + */ + } else { + uint8_t buf[4096]; + size_t len; + while ((len = fread(buf, 1, sizeof(buf), infp)) > 0) { + sm4_cbc_mac_update(&ctx, buf, len); + /* + if (sm4_cbc_mac_update(&ctx, buf, len) != 1) { + fprintf(stderr, "gmssl %s: inner error\n", prog); + goto end; + } + */ + } + memset(buf, 0, sizeof(buf)); + } + sm4_cbc_mac_finish(&ctx, mac); + /* + if (sm4_cbc_mac_finish(&ctx, mac) != 1) { + fprintf(stderr, "gmssl %s: inner error\n", prog); + goto end; + } + */ + + if (outformat > 1) { + if (fwrite(mac, 1, sizeof(mac), outfp) != sizeof(mac)) { + fprintf(stderr, "gmssl %s: output failure : %s\n", prog, strerror(errno)); + goto end; + } + } else { + for (i = 0; i < sizeof(mac); i++) { + fprintf(outfp, "%02x", mac[i]); + } + fprintf(outfp, "\n"); + } + ret = 0; +end: + gmssl_secure_clear(key, sizeof(key)); + gmssl_secure_clear(&ctx, sizeof(ctx)); + if (infile && infp) fclose(infp); + if (outfile && outfp) fclose(outfp); + return ret; +} diff --git a/tools/sm4_ccm.c b/tools/sm4_ccm.c index 97a7c515..6e4b2f3c 100755 --- a/tools/sm4_ccm.c +++ b/tools/sm4_ccm.c @@ -18,9 +18,6 @@ #include -// 这个要对照sm4.c中的再修改一下 - - static const char *usage = "{-encrypt|-decrypt} -key hex -iv hex [-aad str| -aad_hex hex] [-taglen num] [-in file] [-out file]"; static const char *options = @@ -36,13 +33,16 @@ static const char *options = " -in file | stdin Input data\n" " -out file | stdout Output data\n" "\n" -"Examples" +"Examples\n" "\n" -" echo \"hello\" | gmssl sm4_ccm -encrypt -key 11223344556677881122334455667788 -iv 112233445566778811223344 -out ciphertext.bin\n" -" gmssl sm4_ccm -decrypt -key 11223344556677881122334455667788 -iv 112233445566778811223344 -in ciphertext.bin\n" +" $ TEXT=`gmssl rand -outlen 20 -hex`\n" +" $ KEY=`gmssl rand -outlen 16 -hex`\n" +" $ IV=`gmssl rand -outlen 12 -hex`\n" +" $ AAD=\"The AAD Data\"\n" +" $ echo -n $TEXT | gmssl sm4_ccm -encrypt -key $KEY -iv $IV -aad $AAD -out sm4_ccm_ciphertext.bin\n" +" $ gmssl sm4_ccm -decrypt -key $KEY -iv $IV -aad $AAD -in sm4_ccm_ciphertext.bin\n" "\n"; - static uint8_t *read_content(FILE *infp, size_t *outlen, const char *prog) { const size_t INITIAL_BUFFER_SIZE = 4096; @@ -52,7 +52,7 @@ static uint8_t *read_content(FILE *infp, size_t *outlen, const char *prog) size_t total_read = 0; if (!(buffer = (uint8_t *)malloc(INITIAL_BUFFER_SIZE))) { - fprintf(stderr, "%s: malloc failure\n", prog); + fprintf(stderr, "gmssl %s: malloc failure\n", prog); return NULL; } @@ -63,7 +63,7 @@ static uint8_t *read_content(FILE *infp, size_t *outlen, const char *prog) uint8_t *new_buffer; if (buffer_size >= MAX_BUFFER_SIZE) { - fprintf(stderr, "%s: input too long, should be less than %zu\n", prog, MAX_BUFFER_SIZE); + fprintf(stderr, "gmssl %s: input too long, should be less than %zu\n", prog, MAX_BUFFER_SIZE); free(buffer); return NULL; } @@ -73,7 +73,7 @@ static uint8_t *read_content(FILE *infp, size_t *outlen, const char *prog) } if (!(new_buffer = (uint8_t *)realloc(buffer, buffer_size))) { - fprintf(stderr, "%s: realloc failure\n", prog); + fprintf(stderr, "gmssl %s: realloc failure\n", prog); free(buffer); return NULL; } @@ -88,7 +88,7 @@ static uint8_t *read_content(FILE *infp, size_t *outlen, const char *prog) } if (ferror(infp)) { - fprintf(stderr, "%s: fread error\n", prog); + fprintf(stderr, "gmssl %s: fread error\n", prog); perror("error reading input"); free(buffer); return NULL; @@ -110,7 +110,7 @@ int sm4_ccm_main(int argc, char **argv) uint8_t *aad = NULL; uint8_t *aad_buf = NULL; size_t aadlen = 0; - int taglen = SM4_CCM_DEFAULT_MAC_SIZE; + int taglen = SM4_CCM_DEFAULT_TAG_SIZE; char *infile = NULL; char *outfile = NULL; uint8_t key[16]; @@ -120,9 +120,11 @@ int sm4_ccm_main(int argc, char **argv) FILE *infp = stdin; FILE *outfp = stdout; SM4_KEY sm4_key; - uint8_t buf[4096]; // CCM不是update 模式的,因此输出可能比输入长 + uint8_t *inbuf = NULL; size_t inlen; + uint8_t *outbuf = NULL; size_t outlen; + uint8_t *tag; argc--; argv++; @@ -203,7 +205,7 @@ int sm4_ccm_main(int argc, char **argv) } else if (!strcmp(*argv, "-taglen")) { if (--argc < 1) goto bad; taglen = atoi(*(++argv)); - if (taglen < SM4_CCM_MIN_MAC_SIZE || taglen > SM4_CCM_MAX_MAC_SIZE) { + if (taglen < SM4_CCM_MIN_TAG_SIZE || taglen > SM4_CCM_MAX_TAG_SIZE) { fprintf(stderr, "%s: `-taglen` invalid integer argument\n", prog); goto end; } @@ -263,9 +265,10 @@ bad: error_print(); goto end; } + } else { if (inlen < taglen) { - fprintf(stderr, "%s: input length (%zu bytes) shorter than tag length (%zu bytes)\n", + fprintf(stderr, "%s: input length (%zu bytes) shorter than tag length (%d bytes)\n", prog, inlen, taglen); goto end; } @@ -282,6 +285,7 @@ bad: } } + if (fwrite(outbuf, 1, outlen, outfp) != outlen) { fprintf(stderr, "%s: fwrite error\n", prog); goto end; @@ -292,9 +296,10 @@ bad: end: gmssl_secure_clear(key, sizeof(key)); gmssl_secure_clear(iv, sizeof(iv)); - gmssl_secure_clear(&ctx, sizeof(ctx)); - gmssl_secure_clear(buf, sizeof(buf)); + gmssl_secure_clear(&sm4_key, sizeof(sm4_key)); if (infile && infp) fclose(infp); if (outfile && outfp) fclose(outfp); + if (inbuf) free(inbuf); + if (outbuf) free(outbuf); return ret; } diff --git a/tools/sm4_gcm.c b/tools/sm4_gcm.c index 0de436bc..f9054f52 100755 --- a/tools/sm4_gcm.c +++ b/tools/sm4_gcm.c @@ -40,7 +40,7 @@ static const char *options = " $ IV=`gmssl rand -outlen 12 -hex`\n" " $ AAD=\"The AAD Data\"\n" " $ echo -n $TEXT | gmssl sm4_gcm -encrypt -key $KEY -iv $IV -aad $AAD -out sm4_gcm_ciphertext.bin\n" -" $ gmssl sm4_gcm -decrypt -key $KEY -iv $IV -in sm4_gcm_ciphertext.bin\n" +" $ gmssl sm4_gcm -decrypt -key $KEY -iv $IV -aad $AAD -in sm4_gcm_ciphertext.bin\n" "\n"; int sm4_gcm_main(int argc, char **argv)