From 58340393b14198af142f64f4be095a4b1b2fc651 Mon Sep 17 00:00:00 2001 From: Zhi Guan Date: Sat, 11 May 2024 18:10:24 +0800 Subject: [PATCH] Add SM4 commands in gmssl CLI --- CMakeLists.txt | 7 + include/gmssl/sm4.h | 5 +- include/gmssl/sm4_cbc_sm3_hmac.h | 4 +- include/gmssl/sm4_ctr_sm3_hmac.h | 4 +- src/sm4_cbc_sm3_hmac.c | 12 +- src/sm4_ctr_sm3_hmac.c | 12 +- tests/sm4_ccmtest.c | 4 +- tests/sm4_sm3_hmactest.c | 8 +- tools/gmssl.c | 118 +++++++----- tools/sm4.c | 12 +- tools/sm4_cbc.c | 203 +++++++++++++++++++++ tools/sm4_cbc_sm3_hmac.c | 231 ++++++++++++++++++++++++ tools/sm4_ccm.c | 300 +++++++++++++++++++++++++++++++ tools/sm4_cfb.c | 203 +++++++++++++++++++++ tools/sm4_ctr.c | 56 +++--- tools/sm4_ctr_sm3_hmac.c | 231 ++++++++++++++++++++++++ tools/sm4_ecb.c | 191 ++++++++++++++++++++ tools/sm4_gcm.c | 240 +++++++++++++++++++++++++ tools/sm4_ofb.c | 167 +++++++++++++++++ 19 files changed, 1895 insertions(+), 113 deletions(-) create mode 100755 tools/sm4_cbc.c create mode 100755 tools/sm4_cbc_sm3_hmac.c create mode 100755 tools/sm4_ccm.c create mode 100755 tools/sm4_cfb.c create mode 100755 tools/sm4_ctr_sm3_hmac.c create mode 100755 tools/sm4_ecb.c create mode 100755 tools/sm4_gcm.c create mode 100755 tools/sm4_ofb.c diff --git a/CMakeLists.txt b/CMakeLists.txt index b07e72a3..c088254c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -93,7 +93,14 @@ set(tools tools/gmssl.c tools/version.c tools/sm4.c + tools/sm4_ecb.c + tools/sm4_cbc.c tools/sm4_ctr.c + tools/sm4_cfb.c + tools/sm4_ofb.c + tools/sm4_gcm.c + tools/sm4_cbc_sm3_hmac.c + tools/sm4_ctr_sm3_hmac.c tools/sm3.c tools/sm3hmac.c tools/sm3xmss_keygen.c diff --git a/include/gmssl/sm4.h b/include/gmssl/sm4.h index 65d26512..18b17475 100644 --- a/include/gmssl/sm4.h +++ b/include/gmssl/sm4.h @@ -219,8 +219,9 @@ _gmssl_export int sm4_cfb_decrypt_finish(SM4_CFB_CTX *ctx, uint8_t *out, size_t #ifdef ENABLE_SM4_CCM #define SM4_CCM_MIN_IV_SIZE 7 #define SM4_CCM_MAX_IV_SIZE 13 -#define SM4_CCM_MIN_MAC_SIZE 4 -#define SM4_CCM_MAX_MAC_SIZE 16 +#define SM4_CCM_MIN_TAG_SIZE 4 +#define SM4_CCM_MAX_TAG_SIZE 16 +#define SM4_CCM_DEFAULT_TAG_SIZE 16 // make sure inlen < 2^((15 - ivlen) * 8) _gmssl_export int sm4_ccm_encrypt(const SM4_KEY *sm4_key, const uint8_t *iv, size_t ivlen, diff --git a/include/gmssl/sm4_cbc_sm3_hmac.h b/include/gmssl/sm4_cbc_sm3_hmac.h index 11ae6e93..fb1abf48 100644 --- a/include/gmssl/sm4_cbc_sm3_hmac.h +++ b/include/gmssl/sm4_cbc_sm3_hmac.h @@ -32,14 +32,14 @@ typedef struct { #define SM4_CBC_SM3_HMAC_IV_SIZE 16 _gmssl_export int sm4_cbc_sm3_hmac_encrypt_init(SM4_CBC_SM3_HMAC_CTX *ctx, - const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, + const uint8_t key[48], const uint8_t iv[16], const uint8_t *aad, size_t aadlen); _gmssl_export int sm4_cbc_sm3_hmac_encrypt_update(SM4_CBC_SM3_HMAC_CTX *ctx, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen); _gmssl_export int sm4_cbc_sm3_hmac_encrypt_finish(SM4_CBC_SM3_HMAC_CTX *ctx, uint8_t *out, size_t *outlen); _gmssl_export int sm4_cbc_sm3_hmac_decrypt_init(SM4_CBC_SM3_HMAC_CTX *ctx, - const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, + const uint8_t key[48], const uint8_t iv[16], const uint8_t *aad, size_t aadlen); _gmssl_export int sm4_cbc_sm3_hmac_decrypt_update(SM4_CBC_SM3_HMAC_CTX *ctx, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen); diff --git a/include/gmssl/sm4_ctr_sm3_hmac.h b/include/gmssl/sm4_ctr_sm3_hmac.h index 71ad6027..3d0825df 100644 --- a/include/gmssl/sm4_ctr_sm3_hmac.h +++ b/include/gmssl/sm4_ctr_sm3_hmac.h @@ -32,14 +32,14 @@ typedef struct { #define SM4_CTR_SM3_HMAC_IV_SIZE 16 _gmssl_export int sm4_ctr_sm3_hmac_encrypt_init(SM4_CTR_SM3_HMAC_CTX *ctx, - const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, + const uint8_t key[48], const uint8_t iv[16], const uint8_t *aad, size_t aadlen); _gmssl_export int sm4_ctr_sm3_hmac_encrypt_update(SM4_CTR_SM3_HMAC_CTX *ctx, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen); _gmssl_export int sm4_ctr_sm3_hmac_encrypt_finish(SM4_CTR_SM3_HMAC_CTX *ctx, uint8_t *out, size_t *outlen); _gmssl_export int sm4_ctr_sm3_hmac_decrypt_init(SM4_CTR_SM3_HMAC_CTX *ctx, - const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, + const uint8_t key[48], const uint8_t iv[16], const uint8_t *aad, size_t aadlen); _gmssl_export int sm4_ctr_sm3_hmac_decrypt_update(SM4_CTR_SM3_HMAC_CTX *ctx, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen); diff --git a/src/sm4_cbc_sm3_hmac.c b/src/sm4_cbc_sm3_hmac.c index 5feed84b..ad23a4f0 100644 --- a/src/sm4_cbc_sm3_hmac.c +++ b/src/sm4_cbc_sm3_hmac.c @@ -17,17 +17,13 @@ int sm4_cbc_sm3_hmac_encrypt_init(SM4_CBC_SM3_HMAC_CTX *ctx, - const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, + const uint8_t key[48], const uint8_t iv[16], const uint8_t *aad, size_t aadlen) { if (!ctx || !key || !iv || (!aad && aadlen)) { error_print(); return -1; } - if (keylen != 48 || ivlen != 16) { - error_print(); - return -1; - } memset(ctx, 0, sizeof(*ctx)); if (sm4_cbc_encrypt_init(&ctx->enc_ctx, key, iv) != 1) { error_print(); @@ -71,17 +67,13 @@ int sm4_cbc_sm3_hmac_encrypt_finish(SM4_CBC_SM3_HMAC_CTX *ctx, uint8_t *out, siz } int sm4_cbc_sm3_hmac_decrypt_init(SM4_CBC_SM3_HMAC_CTX *ctx, - const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, + const uint8_t key[48], const uint8_t iv[16], const uint8_t *aad, size_t aadlen) { if (!ctx || !key || !iv || (!aad && aadlen)) { error_print(); return -1; } - if (keylen != 48 || ivlen != 16) { - error_print(); - return -1; - } memset(ctx, 0, sizeof(*ctx)); if (sm4_cbc_decrypt_init(&ctx->enc_ctx, key, iv) != 1) { error_print(); diff --git a/src/sm4_ctr_sm3_hmac.c b/src/sm4_ctr_sm3_hmac.c index c785ca23..752d981d 100644 --- a/src/sm4_ctr_sm3_hmac.c +++ b/src/sm4_ctr_sm3_hmac.c @@ -17,17 +17,13 @@ int sm4_ctr_sm3_hmac_encrypt_init(SM4_CTR_SM3_HMAC_CTX *ctx, - const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, + const uint8_t key[48], const uint8_t iv[16], const uint8_t *aad, size_t aadlen) { if (!ctx || !key || !iv || (!aad && aadlen)) { error_print(); return -1; } - if (keylen != 48 || ivlen != 16) { - error_print(); - return -1; - } memset(ctx, 0, sizeof(*ctx)); if (sm4_ctr_encrypt_init(&ctx->enc_ctx, key, iv) != 1) { error_print(); @@ -71,17 +67,13 @@ int sm4_ctr_sm3_hmac_encrypt_finish(SM4_CTR_SM3_HMAC_CTX *ctx, uint8_t *out, siz } int sm4_ctr_sm3_hmac_decrypt_init(SM4_CTR_SM3_HMAC_CTX *ctx, - const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, + const uint8_t key[48], const uint8_t iv[16], const uint8_t *aad, size_t aadlen) { if (!ctx || !key || !iv || (!aad && aadlen)) { error_print(); return -1; } - if (keylen != 48 || ivlen != 16) { - error_print(); - return -1; - } memset(ctx, 0, sizeof(*ctx)); if (sm4_ctr_encrypt_init(&ctx->enc_ctx, key, iv) != 1) { error_print(); diff --git a/tests/sm4_ccmtest.c b/tests/sm4_ccmtest.c index f6a8ec89..d7bae5f6 100644 --- a/tests/sm4_ccmtest.c +++ b/tests/sm4_ccmtest.c @@ -31,8 +31,8 @@ static int test_sm4_ccm(void) size_t len[] = { 4, 16, 36, 64 }; uint8_t encrypted[sizeof(plaintext)]; uint8_t decrypted[sizeof(plaintext)]; - uint8_t mac[SM4_CCM_MAX_MAC_SIZE]; - size_t maclen[] = { SM4_CCM_MIN_MAC_SIZE, SM4_CCM_MAX_MAC_SIZE }; + uint8_t mac[SM4_CCM_MAX_TAG_SIZE]; + size_t maclen[] = { SM4_CCM_MIN_TAG_SIZE, SM4_CCM_MAX_TAG_SIZE }; size_t i; rand_bytes(key, sizeof(key)); diff --git a/tests/sm4_sm3_hmactest.c b/tests/sm4_sm3_hmactest.c index 8c5131a6..cfe4cd24 100644 --- a/tests/sm4_sm3_hmactest.c +++ b/tests/sm4_sm3_hmactest.c @@ -43,7 +43,7 @@ static int test_sm4_cbc_sm3_hmac(void) rand_bytes(aad, sizeof(aad)); rand_bytes(plain, plainlen); - if (sm4_cbc_sm3_hmac_encrypt_init(&aead_ctx, key, sizeof(key), iv, sizeof(iv), aad, sizeof(aad)) != 1) { + if (sm4_cbc_sm3_hmac_encrypt_init(&aead_ctx, key, iv, aad, sizeof(aad)) != 1) { error_print(); return -1; } @@ -100,7 +100,7 @@ static int test_sm4_cbc_sm3_hmac(void) in = cipher; out = buf; - if (sm4_cbc_sm3_hmac_decrypt_init(&aead_ctx, key, sizeof(key), iv, sizeof(iv), aad, sizeof(aad)) != 1) { + if (sm4_cbc_sm3_hmac_decrypt_init(&aead_ctx, key, iv, aad, sizeof(aad)) != 1) { error_print(); return -1; } @@ -162,7 +162,7 @@ static int test_sm4_ctr_sm3_hmac(void) rand_bytes(aad, sizeof(aad)); rand_bytes(plain, plainlen); - if (sm4_ctr_sm3_hmac_encrypt_init(&aead_ctx, key, sizeof(key), iv, sizeof(iv), aad, sizeof(aad)) != 1) { + if (sm4_ctr_sm3_hmac_encrypt_init(&aead_ctx, key, iv, aad, sizeof(aad)) != 1) { error_print(); return -1; } @@ -221,7 +221,7 @@ static int test_sm4_ctr_sm3_hmac(void) in = cipher; out = buf; - if (sm4_ctr_sm3_hmac_decrypt_init(&aead_ctx, key, sizeof(key), iv, sizeof(iv), aad, sizeof(aad)) != 1) { + if (sm4_ctr_sm3_hmac_decrypt_init(&aead_ctx, key, iv, aad, sizeof(aad)) != 1) { error_print(); return -1; } diff --git a/tools/gmssl.c b/tools/gmssl.c index 3405def3..720ed079 100644 --- a/tools/gmssl.c +++ b/tools/gmssl.c @@ -36,7 +36,14 @@ extern int sm3_main(int argc, char **argv); extern int sm3hmac_main(int argc, char **argv); extern int sm3xmss_keygen_main(int argc, char **argv); extern int sm4_main(int argc, char **argv); +extern int sm4_ecb_main(int argc, char **argv); +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_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 zuc_main(int argc, char **argv); extern int sm9setup_main(int argc, char **argv); extern int sm9keygen_main(int argc, char **argv); @@ -67,55 +74,62 @@ static const char *options = "command -help\n" "\n" "Commands:\n" - " help Print this help message\n" - " version Print version\n" - " rand Generate random bytes\n" - " sm2keygen Generate SM2 keypair\n" - " sm2sign Generate SM2 signature\n" - " sm2verify Verify SM2 signature\n" - " sm2encrypt Encrypt with SM2 public key\n" - " sm2decrypt Decrypt with SM2 private key\n" - " sm3 Generate SM3 hash\n" - " sm3hmac Generate SM3 HMAC tag\n" - " sm3xmss_keygen Generate SM3-XMSS keypair\n" - " sm4 Encrypt or decrypt with SM4\n" - " sm4_ctr Encrypt or decrypt with SM4 CTR\n" - " zuc Encrypt or decrypt with ZUC\n" - " sm9setup Generate SM9 master secret\n" - " sm9keygen Generate SM9 private key\n" - " sm9sign Generate SM9 signature\n" - " sm9verify Verify SM9 signature\n" - " sm9encrypt SM9 public key encryption\n" - " sm9decrypt SM9 decryption\n" - " pbkdf2 Generate key from password\n" - " reqgen Generate certificate signing request (CSR)\n" - " reqsign Generate certificate from CSR\n" - " reqparse Parse and print a CSR\n" - " crlget Download the CRL of given certificate\n" - " crlgen Sign a CRL with CA certificate and private key\n" - " crlverify Verify a CRL with issuer's certificate\n" - " crlparse Parse and print CRL\n" - " certgen Generate a self-signed certificate\n" - " certparse Parse and print certificates\n" - " certverify Verify certificate chain\n" - " certrevoke Revoke certificate and output RevokedCertificate record\n" - " cmsparse Parse CMS (cryptographic message syntax) file\n" - " cmsencrypt Generate CMS EnvelopedData\n" - " cmsdecrypt Decrypt CMS EnvelopedData\n" - " cmssign Generate CMS SignedData\n" - " cmsverify Verify CMS SignedData\n" + " help Print this help message\n" + " version Print version\n" + " rand Generate random bytes\n" + " sm2keygen Generate SM2 keypair\n" + " sm2sign Generate SM2 signature\n" + " sm2verify Verify SM2 signature\n" + " sm2encrypt Encrypt with SM2 public key\n" + " sm2decrypt Decrypt with SM2 private key\n" + " sm3 Generate SM3 hash\n" + " sm3hmac Generate SM3 HMAC tag\n" + " sm3xmss_keygen Generate SM3-XMSS keypair\n" + " sm4 Encrypt or decrypt with SM4\n" + " sm4_ecb Encrypt or decrypt with SM4 ECB\n" + " sm4_cbc Encrypt or decrypt with SM4 CBC\n" + " 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_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" + " zuc Encrypt or decrypt with ZUC\n" + " sm9setup Generate SM9 master secret\n" + " sm9keygen Generate SM9 private key\n" + " sm9sign Generate SM9 signature\n" + " sm9verify Verify SM9 signature\n" + " sm9encrypt SM9 public key encryption\n" + " sm9decrypt SM9 decryption\n" + " pbkdf2 Generate key from password\n" + " reqgen Generate certificate signing request (CSR)\n" + " reqsign Generate certificate from CSR\n" + " reqparse Parse and print a CSR\n" + " crlget Download the CRL of given certificate\n" + " crlgen Sign a CRL with CA certificate and private key\n" + " crlverify Verify a CRL with issuer's certificate\n" + " crlparse Parse and print CRL\n" + " certgen Generate a self-signed certificate\n" + " certparse Parse and print certificates\n" + " certverify Verify certificate chain\n" + " certrevoke Revoke certificate and output RevokedCertificate record\n" + " cmsparse Parse CMS (cryptographic message syntax) file\n" + " cmsencrypt Generate CMS EnvelopedData\n" + " cmsdecrypt Decrypt CMS EnvelopedData\n" + " cmssign Generate CMS SignedData\n" + " cmsverify Verify CMS SignedData\n" #ifdef ENABLE_SDF - " sdfutil SDF crypto device utility\n" + " sdfutil SDF crypto device utility\n" #endif #ifdef ENABLE_SKF - " skfutil SKF crypto device utility\n" + " skfutil SKF crypto device utility\n" #endif - " tlcp_client TLCP client\n" - " tlcp_server TLCP server\n" - " tls12_client TLS 1.2 client\n" - " tls12_server TLS 1.2 server\n" - " tls13_client TLS 1.3 client\n" - " tls13_server TLS 1.3 server\n" + " tlcp_client TLCP client\n" + " tlcp_server TLCP server\n" + " tls12_client TLS 1.2 client\n" + " tls12_server TLS 1.2 server\n" + " tls13_client TLS 1.3 client\n" + " tls13_server TLS 1.3 server\n" "\n" "run `gmssl -help` to print help of the given command\n" "\n"; @@ -184,8 +198,22 @@ int main(int argc, char **argv) return sm3xmss_keygen_main(argc, argv); } else if (!strcmp(*argv, "sm4")) { return sm4_main(argc, argv); + } else if (!strcmp(*argv, "sm4_ecb")) { + return sm4_ecb_main(argc, argv); + } else if (!strcmp(*argv, "sm4_cbc")) { + return sm4_cbc_main(argc, argv); } else if (!strcmp(*argv, "sm4_ctr")) { return sm4_ctr_main(argc, argv); + } else if (!strcmp(*argv, "sm4_cfb")) { + return sm4_cfb_main(argc, argv); + } else if (!strcmp(*argv, "sm4_ofb")) { + return sm4_ofb_main(argc, argv); + } else if (!strcmp(*argv, "sm4_gcm")) { + return sm4_gcm_main(argc, argv); + } else if (!strcmp(*argv, "sm4_cbc_sm3_hmac")) { + 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, "zuc")) { return zuc_main(argc, argv); } else if (!strcmp(*argv, "sm9setup")) { diff --git a/tools/sm4.c b/tools/sm4.c index a7116159..46daf11e 100755 --- a/tools/sm4.c +++ b/tools/sm4.c @@ -111,9 +111,9 @@ static int sm4_ccm_crypt(const uint8_t *key, size_t keylen, const uint8_t *iv, s prog, SM4_CCM_MIN_IV_SIZE, SM4_CCM_MAX_IV_SIZE); return -1; } - 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: invalid SM4-CCM MAC tag length, should be in [%d, %d]\n", - prog, SM4_CCM_MIN_MAC_SIZE, SM4_CCM_MAX_MAC_SIZE); + prog, SM4_CCM_MIN_TAG_SIZE, SM4_CCM_MAX_TAG_SIZE); return -1; } if (enc < 0) { @@ -585,8 +585,8 @@ bad: case SM4_MODE_XTS: rv = sm4_xts_encrypt_init(&sm4_ctx.xts, key, iv, xts_data_unit_size); break; #endif case SM4_MODE_GCM: rv = sm4_gcm_encrypt_init(&sm4_ctx.gcm, key, keylen, iv, ivlen, aad, aadlen, GHASH_SIZE); break; - case SM4_MODE_CBC_SM3_HMAC: rv = sm4_cbc_sm3_hmac_encrypt_init(&sm4_ctx.cbc_sm3_hmac, key, keylen, iv, ivlen, aad, aadlen); break; - case SM4_MODE_CTR_SM3_HMAC: rv = sm4_ctr_sm3_hmac_encrypt_init(&sm4_ctx.ctr_sm3_hmac, key, keylen, iv, ivlen, aad, aadlen); break; + case SM4_MODE_CBC_SM3_HMAC: rv = sm4_cbc_sm3_hmac_encrypt_init(&sm4_ctx.cbc_sm3_hmac, key, iv, aad, aadlen); break; + case SM4_MODE_CTR_SM3_HMAC: rv = sm4_ctr_sm3_hmac_encrypt_init(&sm4_ctx.ctr_sm3_hmac, key, iv, aad, aadlen); break; } if (rv != 1) { error_print(); @@ -665,8 +665,8 @@ bad: case SM4_MODE_XTS: rv = sm4_xts_decrypt_init(&sm4_ctx.xts, key, iv, xts_data_unit_size); break; #endif case SM4_MODE_GCM: rv = sm4_gcm_decrypt_init(&sm4_ctx.gcm, key, keylen, iv, ivlen, aad, aadlen, GHASH_SIZE); break; - case SM4_MODE_CBC_SM3_HMAC: rv = sm4_cbc_sm3_hmac_decrypt_init(&sm4_ctx.cbc_sm3_hmac, key, keylen, iv, ivlen, aad, aadlen); break; - case SM4_MODE_CTR_SM3_HMAC: rv = sm4_ctr_sm3_hmac_decrypt_init(&sm4_ctx.ctr_sm3_hmac, key, keylen, iv, ivlen, aad, aadlen); break; + case SM4_MODE_CBC_SM3_HMAC: rv = sm4_cbc_sm3_hmac_decrypt_init(&sm4_ctx.cbc_sm3_hmac, key, iv, aad, aadlen); break; + case SM4_MODE_CTR_SM3_HMAC: rv = sm4_ctr_sm3_hmac_decrypt_init(&sm4_ctx.ctr_sm3_hmac, key, iv, aad, aadlen); break; } if (rv != 1) { error_print(); diff --git a/tools/sm4_cbc.c b/tools/sm4_cbc.c new file mode 100755 index 00000000..3919a11b --- /dev/null +++ b/tools/sm4_cbc.c @@ -0,0 +1,203 @@ +/* + * Copyright 2014-2024 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 +#include + + +static const char *usage = "{-encrypt|-decrypt} -key hex -iv hex [-in file] [-out file]"; + +static const char *options = +"Options\n" +"\n" +" -encrypt Encrypt\n" +" -decrypt Decrypt\n" +" -key hex Symmetric key in HEX format\n" +" -iv hex IV in HEX format\n" +" -in file | stdin Input data\n" +" -out file | stdout Output data\n" +"\n" +"Examples" +"\n" +" echo \"hello\" | gmssl sm4_cbc -encrypt -key 11223344556677881122334455667788 -iv 112233445566778811223344 -out ciphertext.bin\n" +"\n"; + +int sm4_cbc_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + int enc = -1; + char *keyhex = NULL; + char *ivhex = NULL; + char *infile = NULL; + char *outfile = NULL; + uint8_t key[16]; + size_t keylen; + uint8_t iv[16]; + size_t ivlen; + FILE *infp = stdin; + FILE *outfp = stdout; + SM4_CBC_CTX ctx; + uint8_t buf[4096]; + size_t inlen; + size_t outlen; + + 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", options); + ret = 0; + goto end; + } else if (!strcmp(*argv, "-encrypt")) { + if (enc == 0) { + fprintf(stderr, "gmssl %s: `-encrypt` `-decrypt` should not be used together\n", prog); + goto end; + } + enc = 1; + } else if (!strcmp(*argv, "-decrypt")) { + if (enc == 1) { + fprintf(stderr, "gmssl %s: `-encrypt` `-decrypt` should not be used together\n", prog); + goto end; + } + enc = 0; + } else if (!strcmp(*argv, "-key")) { + if (--argc < 1) goto bad; + keyhex = *(++argv); + if (strlen(keyhex) != sizeof(key) * 2) { + fprintf(stderr, "gmssl %s: invalid key length\n", prog); + goto end; + } + if (hex_to_bytes(keyhex, strlen(keyhex), key, &keylen) != 1) { + fprintf(stderr, "gmssl %s: invalid key hex digits\n", prog); + goto end; + } + } else if (!strcmp(*argv, "-iv")) { + if (--argc < 1) goto bad; + ivhex = *(++argv); + if (strlen(ivhex) != sizeof(iv) * 2) { + fprintf(stderr, "gmssl %s: invalid IV length\n", prog); + goto end; + } + if (hex_to_bytes(ivhex, strlen(ivhex), iv, &ivlen) != 1) { + fprintf(stderr, "gmssl %s: invalid IV hex digits\n", prog); + goto end; + } + } 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 (enc < 0) { + fprintf(stderr, "gmssl %s: option -encrypt or -decrypt should be set\n", prog); + goto end; + } + if (!keyhex) { + fprintf(stderr, "gmssl %s: option `-key` missing\n", prog); + goto end; + } + if (!ivhex) { + fprintf(stderr, "gmssl %s: option `-iv` missing\n", prog); + goto end; + } + + if (enc) { + if (sm4_cbc_encrypt_init(&ctx, key, iv) != 1) { + error_print(); + goto end; + } + } else { + if (sm4_cbc_decrypt_init(&ctx, key, iv) != 1) { + error_print(); + goto end; + } + } + + while ((inlen = fread(buf, 1, sizeof(buf), infp)) > 0) { + + if (enc) { + if (sm4_cbc_encrypt_update(&ctx, buf, inlen, buf, &outlen) != 1) { + error_print(); + goto end; + } + } else { + if (sm4_cbc_decrypt_update(&ctx, buf, inlen, buf, &outlen) != 1) { + error_print(); + goto end; + } + } + + if (fwrite(buf, 1, outlen, outfp) != outlen) { + fprintf(stderr, "gmssl %s: output failure : %s\n", prog, strerror(errno)); + goto end; + } + } + + if (enc) { + if (sm4_cbc_encrypt_finish(&ctx, buf, &outlen) != 1) { + error_print(); + goto end; + } + } else { + if (sm4_cbc_decrypt_finish(&ctx, buf, &outlen) != 1) { + error_print(); + goto end; + } + } + if (fwrite(buf, 1, outlen, outfp) != outlen) { + fprintf(stderr, "gmssl %s: output failure : %s\n", prog, strerror(errno)); + goto end; + } + + ret = 0; + +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)); + if (infile && infp) fclose(infp); + if (outfile && outfp) fclose(outfp); + return ret; +} diff --git a/tools/sm4_cbc_sm3_hmac.c b/tools/sm4_cbc_sm3_hmac.c new file mode 100755 index 00000000..2b85a78c --- /dev/null +++ b/tools/sm4_cbc_sm3_hmac.c @@ -0,0 +1,231 @@ +/* + * Copyright 2014-2024 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 +#include + + +static const char *usage = "{-encrypt|-decrypt} -key hex -iv hex [-aad str| -aad_hex hex] [-in file] [-out file]"; + +static const char *options = +"Options\n" +"\n" +" -encrypt Encrypt\n" +" -decrypt Decrypt\n" +" -key hex Symmetric key in HEX format, 48 bytes\n" +" -iv hex IV in HEX format, 16 bytes\n" +" -aad str Authenticated-only message\n" +" -aad_hex hex Authenticated-only data in HEX format\n" +" -in file | stdin Input data\n" +" -out file | stdout Output data\n" +"\n" +"Examples" +"\n" +" echo \"hello\" | gmssl sm4_cbc_sm3_hmac -encrypt -key 11223344556677881122334455667788 -iv 112233445566778811223344 -out ciphertext.bin\n" +" gmssl sm4_cbc_sm3_hmac -decrypt -key 11223344556677881122334455667788 -iv 112233445566778811223344 -in ciphertext.bin\n" +"\n"; + +int sm4_cbc_sm3_hmac_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + int enc = -1; + char *keyhex = NULL; + char *ivhex = NULL; + uint8_t *aad = NULL; + uint8_t *aad_buf = NULL; + size_t aadlen = 0; + char *infile = NULL; + char *outfile = NULL; + uint8_t key[48]; + size_t keylen; + uint8_t iv[16]; + size_t ivlen; + FILE *infp = stdin; + FILE *outfp = stdout; + SM4_CBC_SM3_HMAC_CTX ctx; + uint8_t buf[4096]; + size_t inlen; + size_t outlen; + + 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", options); + ret = 0; + goto end; + } else if (!strcmp(*argv, "-encrypt")) { + if (enc == 0) { + fprintf(stderr, "gmssl %s: `-encrypt` `-decrypt` should not be used together\n", prog); + goto end; + } + enc = 1; + } else if (!strcmp(*argv, "-decrypt")) { + if (enc == 1) { + fprintf(stderr, "gmssl %s: `-encrypt` `-decrypt` should not be used together\n", prog); + goto end; + } + enc = 0; + } else if (!strcmp(*argv, "-key")) { + if (--argc < 1) goto bad; + keyhex = *(++argv); + if (strlen(keyhex) != sizeof(key) * 2) { + fprintf(stderr, "gmssl %s: invalid key length, should be %d bytes\n", prog, SM4_CBC_SM3_HMAC_KEY_SIZE); + goto end; + } + if (hex_to_bytes(keyhex, strlen(keyhex), key, &keylen) != 1) { + fprintf(stderr, "gmssl %s: invalid key hex digits, should be %d bytes\n", prog, SM4_CBC_SM3_HMAC_IV_SIZE); + goto end; + } + } else if (!strcmp(*argv, "-iv")) { + if (--argc < 1) goto bad; + ivhex = *(++argv); + if (strlen(ivhex) != sizeof(iv) * 2) { + fprintf(stderr, "gmssl %s: invalid IV length\n", prog); + goto end; + } + if (hex_to_bytes(ivhex, strlen(ivhex), iv, &ivlen) != 1) { + fprintf(stderr, "gmssl %s: invalid IV hex digits\n", prog); + goto end; + } + } else if (!strcmp(*argv, "-aad")) { + if (--argc < 1) goto bad; + if (aad) { + fprintf(stderr, "gmssl %s: `-aad` or `aad_hex` has been specified\n", prog); + goto bad; + } + aad = (uint8_t *)(*(++argv)); + aadlen = strlen((char *)aad); + } else if (!strcmp(*argv, "-aad_hex")) { + if (--argc < 1) goto bad; + if (aad) { + fprintf(stderr, "gmssl %s: `-aad` or `aad_hex` has been specified\n", prog); + goto bad; + } + aad = (uint8_t *)(*(++argv)); + if (!(aad_buf = malloc(strlen((char *)aad)/2 + 1))) { + fprintf(stderr, "gmssl %s: malloc failure\n", prog); + goto end; + } + if (hex_to_bytes((char *)aad, strlen((char *)aad), aad_buf, &aadlen) != 1) { + fprintf(stderr, "gmssl %s: `-aad_hex` invalid HEX format argument\n", prog); + goto end; + } + aad = aad_buf; + } 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 (enc < 0) { + fprintf(stderr, "gmssl %s: option -encrypt or -decrypt should be set\n", prog); + goto end; + } + if (!keyhex) { + fprintf(stderr, "gmssl %s: option `-key` missing\n", prog); + goto end; + } + if (!ivhex) { + fprintf(stderr, "gmssl %s: option `-iv` missing\n", prog); + goto end; + } + + if (enc) { + if (sm4_cbc_sm3_hmac_encrypt_init(&ctx, key, iv, aad, aadlen) != 1) { + error_print(); + goto end; + } + } else { + if (sm4_cbc_sm3_hmac_decrypt_init(&ctx, key, iv, aad, aadlen) != 1) { + error_print(); + goto end; + } + } + + while ((inlen = fread(buf, 1, sizeof(buf), infp)) > 0) { + if (enc) { + if (sm4_cbc_sm3_hmac_encrypt_update(&ctx, buf, inlen, buf, &outlen) != 1) { + error_print(); + goto end; + } + } else { + if (sm4_cbc_sm3_hmac_decrypt_update(&ctx, buf, inlen, buf, &outlen) != 1) { + error_print(); + goto end; + } + } + if (fwrite(buf, 1, outlen, outfp) != outlen) { + fprintf(stderr, "gmssl %s: output failure : %s\n", prog, strerror(errno)); + goto end; + } + } + + if (enc) { + if (sm4_cbc_sm3_hmac_encrypt_finish(&ctx, buf, &outlen) != 1) { + error_print(); + goto end; + } + } else { + if (sm4_cbc_sm3_hmac_decrypt_finish(&ctx, buf, &outlen) != 1) { + error_print(); + goto end; + } + } + if (fwrite(buf, 1, outlen, outfp) != outlen) { + fprintf(stderr, "gmssl %s: output failure : %s\n", prog, strerror(errno)); + goto end; + } + + ret = 0; + +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)); + if (infile && infp) fclose(infp); + if (outfile && outfp) fclose(outfp); + return ret; +} diff --git a/tools/sm4_ccm.c b/tools/sm4_ccm.c new file mode 100755 index 00000000..97a7c515 --- /dev/null +++ b/tools/sm4_ccm.c @@ -0,0 +1,300 @@ +/* + * Copyright 2014-2024 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 +#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 = +"Options\n" +"\n" +" -encrypt Encrypt\n" +" -decrypt Decrypt\n" +" -key hex Symmetric key in HEX format\n" +" -iv hex IV in HEX format, 7 to 13 bytes\n" +" -aad str Authenticated-only message\n" +" -aad_hex hex Authenticated-only data in HEX format\n" +" -taglen num MAC tag length, 4 to 16 bytes\n" +" -in file | stdin Input data\n" +" -out file | stdout Output data\n" +"\n" +"Examples" +"\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" +"\n"; + + +static uint8_t *read_content(FILE *infp, size_t *outlen, const char *prog) +{ + const size_t INITIAL_BUFFER_SIZE = 4096; + const size_t MAX_BUFFER_SIZE = 512 * 1024 * 1024; + uint8_t *buffer = NULL; + size_t buffer_size = INITIAL_BUFFER_SIZE; + size_t total_read = 0; + + if (!(buffer = (uint8_t *)malloc(INITIAL_BUFFER_SIZE))) { + fprintf(stderr, "%s: malloc failure\n", prog); + return NULL; + } + + while (1) { + size_t bytes_read; + + if (total_read == buffer_size) { + 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); + free(buffer); + return NULL; + } + buffer_size = buffer_size * 2; + if (buffer_size > MAX_BUFFER_SIZE) { + buffer_size = MAX_BUFFER_SIZE; + } + + if (!(new_buffer = (uint8_t *)realloc(buffer, buffer_size))) { + fprintf(stderr, "%s: realloc failure\n", prog); + free(buffer); + return NULL; + } + buffer = new_buffer; + } + + bytes_read = fread(buffer + total_read, 1, buffer_size - total_read, infp); + total_read += bytes_read; + + if (feof(infp)) { + break; + } + + if (ferror(infp)) { + fprintf(stderr, "%s: fread error\n", prog); + perror("error reading input"); + free(buffer); + return NULL; + } + } + + *outlen = total_read; + + return buffer; +} + +int sm4_ccm_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + int enc = -1; + char *keyhex = NULL; + char *ivhex = NULL; + uint8_t *aad = NULL; + uint8_t *aad_buf = NULL; + size_t aadlen = 0; + int taglen = SM4_CCM_DEFAULT_MAC_SIZE; + char *infile = NULL; + char *outfile = NULL; + uint8_t key[16]; + size_t keylen; + uint8_t iv[SM4_CCM_MAX_IV_SIZE]; + size_t ivlen; + FILE *infp = stdin; + FILE *outfp = stdout; + SM4_KEY sm4_key; + uint8_t buf[4096]; // CCM不是update 模式的,因此输出可能比输入长 + size_t inlen; + size_t outlen; + + 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", options); + ret = 0; + goto end; + } else if (!strcmp(*argv, "-encrypt")) { + if (enc == 0) { + fprintf(stderr, "gmssl %s: `-encrypt` `-decrypt` should not be used together\n", prog); + goto end; + } + enc = 1; + } else if (!strcmp(*argv, "-decrypt")) { + if (enc == 1) { + fprintf(stderr, "gmssl %s: `-encrypt` `-decrypt` should not be used together\n", prog); + goto end; + } + enc = 0; + } else if (!strcmp(*argv, "-key")) { + if (--argc < 1) goto bad; + keyhex = *(++argv); + if (strlen(keyhex) != sizeof(key) * 2) { + fprintf(stderr, "gmssl %s: invalid key length\n", prog); + goto end; + } + if (hex_to_bytes(keyhex, strlen(keyhex), key, &keylen) != 1) { + fprintf(stderr, "gmssl %s: invalid key hex digits\n", prog); + goto end; + } + } else if (!strcmp(*argv, "-iv")) { + if (--argc < 1) goto bad; + ivhex = *(++argv); + if (strlen(ivhex) > sizeof(iv) * 2) { + fprintf(stderr, "gmssl %s: invalid IV length\n", prog); + goto end; + } + if (hex_to_bytes(ivhex, strlen(ivhex), iv, &ivlen) != 1) { + fprintf(stderr, "gmssl %s: invalid IV hex digits\n", prog); + goto end; + } + if (ivlen < SM4_CCM_MIN_IV_SIZE || ivlen > SM4_CCM_MAX_IV_SIZE) { + fprintf(stderr, "gmssl %s invalid IV length\n", prog); + goto end; + } + } else if (!strcmp(*argv, "-aad")) { + if (--argc < 1) goto bad; + if (aad) { + fprintf(stderr, "gmssl %s: `-aad` or `aad_hex` has been specified\n", prog); + goto bad; + } + aad = (uint8_t *)(*(++argv)); + aadlen = strlen((char *)aad); + } else if (!strcmp(*argv, "-aad_hex")) { + if (--argc < 1) goto bad; + if (aad) { + fprintf(stderr, "gmssl %s: `-aad` or `aad_hex` has been specified\n", prog); + goto bad; + } + aad = (uint8_t *)(*(++argv)); + if (!(aad_buf = malloc(strlen((char *)aad)/2 + 1))) { + fprintf(stderr, "gmssl %s: malloc failure\n", prog); + goto end; + } + if (hex_to_bytes((char *)aad, strlen((char *)aad), aad_buf, &aadlen) != 1) { + fprintf(stderr, "gmssl %s: `-aad_hex` invalid HEX format argument\n", prog); + goto end; + } + aad = aad_buf; + } 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) { + fprintf(stderr, "%s: `-taglen` invalid integer argument\n", prog); + goto end; + } + } 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 (enc < 0) { + fprintf(stderr, "gmssl %s: option -encrypt or -decrypt should be set\n", prog); + goto end; + } + if (!keyhex) { + fprintf(stderr, "gmssl %s: option `-key` missing\n", prog); + goto end; + } + if (!ivhex) { + fprintf(stderr, "gmssl %s: option `-iv` missing\n", prog); + goto end; + } + + sm4_set_encrypt_key(&sm4_key, key); + + if (!(inbuf = read_content(infp, &inlen, prog))) { + goto end; + } + + if (enc) { + outlen = inlen + taglen; + if (!(outbuf = (uint8_t *)malloc(outlen))) { + fprintf(stderr, "%s: malloc failure\n", prog); + goto end; + } + tag = outbuf + inlen; + if (sm4_ccm_encrypt(&sm4_key, iv, ivlen, aad, aadlen, inbuf, inlen, outbuf, taglen, tag) != 1) { + error_print(); + goto end; + } + } else { + if (inlen < taglen) { + fprintf(stderr, "%s: input length (%zu bytes) shorter than tag length (%zu bytes)\n", + prog, inlen, taglen); + goto end; + } + outlen = inlen - taglen; + tag = inbuf + inlen - taglen; + if (!(outbuf = (uint8_t *)malloc(outlen))) { + fprintf(stderr, "%s: malloc failure\n", prog); + goto end; + } + if (sm4_ccm_decrypt(&sm4_key, iv, ivlen, aad, aadlen, inbuf, inlen - taglen, + tag, taglen, outbuf) != 1) { + error_print(); + goto end; + } + } + + if (fwrite(outbuf, 1, outlen, outfp) != outlen) { + fprintf(stderr, "%s: fwrite error\n", prog); + goto end; + } + + ret = 0; + +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)); + if (infile && infp) fclose(infp); + if (outfile && outfp) fclose(outfp); + return ret; +} diff --git a/tools/sm4_cfb.c b/tools/sm4_cfb.c new file mode 100755 index 00000000..463a6fff --- /dev/null +++ b/tools/sm4_cfb.c @@ -0,0 +1,203 @@ +/* + * Copyright 2014-2024 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 +#include + + +static const char *usage = "{-encrypt|-decrypt} -key hex -iv hex [-in file] [-out file]"; + +static const char *options = +"Options\n" +"\n" +" -encrypt Encrypt\n" +" -decrypt Decrypt\n" +" -key hex Symmetric key in HEX format\n" +" -iv hex IV in HEX format\n" +" -in file | stdin Input data\n" +" -out file | stdout Output data\n" +"\n" +"Examples" +"\n" +" echo \"hello\" | gmssl sm4_cfb -encrypt -key 11223344556677881122334455667788 -iv 112233445566778811223344 -out ciphertext.bin\n" +"\n"; + +int sm4_cfb_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + int enc = -1; + char *keyhex = NULL; + char *ivhex = NULL; + char *infile = NULL; + char *outfile = NULL; + uint8_t key[16]; + size_t keylen; + uint8_t iv[16]; + size_t ivlen; + FILE *infp = stdin; + FILE *outfp = stdout; + SM4_CFB_CTX ctx; + uint8_t buf[4096]; + size_t inlen; + size_t outlen; + + 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", options); + ret = 0; + goto end; + } else if (!strcmp(*argv, "-encrypt")) { + if (enc == 0) { + fprintf(stderr, "gmssl %s: `-encrypt` `-decrypt` should not be used together\n", prog); + goto end; + } + enc = 1; + } else if (!strcmp(*argv, "-decrypt")) { + if (enc == 1) { + fprintf(stderr, "gmssl %s: `-encrypt` `-decrypt` should not be used together\n", prog); + goto end; + } + enc = 0; + } else if (!strcmp(*argv, "-key")) { + if (--argc < 1) goto bad; + keyhex = *(++argv); + if (strlen(keyhex) != sizeof(key) * 2) { + fprintf(stderr, "gmssl %s: invalid key length\n", prog); + goto end; + } + if (hex_to_bytes(keyhex, strlen(keyhex), key, &keylen) != 1) { + fprintf(stderr, "gmssl %s: invalid key hex digits\n", prog); + goto end; + } + } else if (!strcmp(*argv, "-iv")) { + if (--argc < 1) goto bad; + ivhex = *(++argv); + if (strlen(ivhex) != sizeof(iv) * 2) { + fprintf(stderr, "gmssl %s: invalid IV length\n", prog); + goto end; + } + if (hex_to_bytes(ivhex, strlen(ivhex), iv, &ivlen) != 1) { + fprintf(stderr, "gmssl %s: invalid IV hex digits\n", prog); + goto end; + } + } 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 (enc < 0) { + fprintf(stderr, "gmssl %s: option -encrypt or -decrypt should be set\n", prog); + goto end; + } + if (!keyhex) { + fprintf(stderr, "gmssl %s: option `-key` missing\n", prog); + goto end; + } + if (!ivhex) { + fprintf(stderr, "gmssl %s: option `-iv` missing\n", prog); + goto end; + } + + if (enc) { + if (sm4_cfb_encrypt_init(&ctx, 16, key, iv) != 1) { + error_print(); + goto end; + } + } else { + if (sm4_cfb_decrypt_init(&ctx, 16, key, iv) != 1) { + error_print(); + goto end; + } + } + + while ((inlen = fread(buf, 1, sizeof(buf), infp)) > 0) { + + if (enc) { + if (sm4_cfb_encrypt_update(&ctx, buf, inlen, buf, &outlen) != 1) { + error_print(); + goto end; + } + } else { + if (sm4_cfb_decrypt_update(&ctx, buf, inlen, buf, &outlen) != 1) { + error_print(); + goto end; + } + } + + if (fwrite(buf, 1, outlen, outfp) != outlen) { + fprintf(stderr, "gmssl %s: output failure : %s\n", prog, strerror(errno)); + goto end; + } + } + + if (enc) { + if (sm4_cfb_encrypt_finish(&ctx, buf, &outlen) != 1) { + error_print(); + goto end; + } + } else { + if (sm4_cfb_decrypt_finish(&ctx, buf, &outlen) != 1) { + error_print(); + goto end; + } + } + if (fwrite(buf, 1, outlen, outfp) != outlen) { + fprintf(stderr, "gmssl %s: output failure : %s\n", prog, strerror(errno)); + goto end; + } + + ret = 0; + +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)); + if (infile && infp) fclose(infp); + if (outfile && outfp) fclose(outfp); + return ret; +} diff --git a/tools/sm4_ctr.c b/tools/sm4_ctr.c index 9027bd3b..9684e747 100755 --- a/tools/sm4_ctr.c +++ b/tools/sm4_ctr.c @@ -18,7 +18,7 @@ #include -static const char *usage = "-key hex -iv hex [-in file] [-out file]"; +static const char *usage = "[-encrypt|-decrypt] -key hex -iv hex [-in file] [-out file]"; static const char *options = "Options\n" @@ -43,25 +43,22 @@ int sm4_ctr_main(int argc, char **argv) char *ivhex = NULL; char *infile = NULL; char *outfile = NULL; - uint8_t key[16]; size_t keylen; uint8_t iv[16]; size_t ivlen; FILE *infp = stdin; FILE *outfp = stdout; - SM4_CTR_CTX ctx; - uint8_t inbuf[4096]; + uint8_t buf[4096]; size_t inlen; - uint8_t outbuf[4096]; // should sizeof(outbuf) > sizeof(inbuf) ? size_t outlen; argc--; argv++; if (argc < 1) { - fprintf(stderr, "usage: %s %s\n", prog, usage); + fprintf(stderr, "usage: gmssl %s %s\n", prog, usage); return 1; } @@ -71,51 +68,51 @@ int sm4_ctr_main(int argc, char **argv) printf("%s\n", options); ret = 0; goto end; + } else if (!strcmp(*argv, "-encrypt")) { + // ignore this option + } else if (!strcmp(*argv, "-decrypt")) { + // ignore this option } else if (!strcmp(*argv, "-key")) { if (--argc < 1) goto bad; keyhex = *(++argv); if (strlen(keyhex) != sizeof(key) * 2) { - fprintf(stderr, "%s: invalid key length\n", prog); + fprintf(stderr, "gmssl %s: invalid key length\n", prog); goto end; } if (hex_to_bytes(keyhex, strlen(keyhex), key, &keylen) != 1) { - fprintf(stderr, "%s: invalid key hex digits\n", prog); + fprintf(stderr, "gmssl %s: invalid key hex digits\n", prog); goto end; } } else if (!strcmp(*argv, "-iv")) { if (--argc < 1) goto bad; ivhex = *(++argv); if (strlen(ivhex) != sizeof(iv) * 2) { - fprintf(stderr, "%s: invalid IV length\n", prog); + fprintf(stderr, "gmssl %s: invalid IV length\n", prog); goto end; } if (hex_to_bytes(ivhex, strlen(ivhex), iv, &ivlen) != 1) { - fprintf(stderr, "%s: invalid IV hex digits\n", prog); + fprintf(stderr, "gmssl %s: invalid IV hex digits\n", prog); goto end; } - } else if (!strcmp(*argv, "-encrypt")) { - // ignore this option - } else if (!strcmp(*argv, "-decrypt")) { - // ignore this option } else if (!strcmp(*argv, "-in")) { if (--argc < 1) goto bad; infile = *(++argv); if (!(infp = fopen(infile, "rb"))) { - fprintf(stderr, "%s: open '%s' failure : %s\n", prog, infile, strerror(errno)); + 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, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno)); + fprintf(stderr, "gmssl %s: open '%s' failure : %s\n", prog, outfile, strerror(errno)); goto end; } } else { - fprintf(stderr, "%s: illegal option `%s`\n", prog, *argv); + fprintf(stderr, "gmssl %s: illegal option `%s`\n", prog, *argv); goto end; bad: - fprintf(stderr, "%s: `%s` option value missing\n", prog, *argv); + fprintf(stderr, "gmssl %s: `%s` option value missing\n", prog, *argv); goto end; } @@ -124,11 +121,11 @@ bad: } if (!keyhex) { - fprintf(stderr, "%s: option `-key` missing\n", prog); + fprintf(stderr, "gmssl %s: option `-key` missing\n", prog); goto end; } if (!ivhex) { - fprintf(stderr, "%s: option `-iv` missing\n", prog); + fprintf(stderr, "gmssl %s: option `-iv` missing\n", prog); goto end; } @@ -137,23 +134,23 @@ bad: goto end; } - while ((inlen = fread(inbuf, 1, sizeof(inbuf), infp)) > 0) { - if (sm4_ctr_encrypt_update(&ctx, inbuf, inlen, outbuf, &outlen) != 1) { + while ((inlen = fread(buf, 1, sizeof(buf), infp)) > 0) { + if (sm4_ctr_encrypt_update(&ctx, buf, inlen, buf, &outlen) != 1) { error_print(); goto end; } - if (fwrite(outbuf, 1, outlen, outfp) != outlen) { - fprintf(stderr, "%s: output failure : %s\n", prog, strerror(errno)); + if (fwrite(buf, 1, outlen, outfp) != outlen) { + fprintf(stderr, "gmssl %s: output failure : %s\n", prog, strerror(errno)); goto end; } } - if (sm4_ctr_encrypt_finish(&ctx, outbuf, &outlen) != 1) { + if (sm4_ctr_encrypt_finish(&ctx, buf, &outlen) != 1) { error_print(); goto end; } - if (fwrite(outbuf, 1, outlen, outfp) != outlen) { - fprintf(stderr, "%s: output failure : %s\n", prog, strerror(errno)); + if (fwrite(buf, 1, outlen, outfp) != outlen) { + fprintf(stderr, "gmssl %s: output failure : %s\n", prog, strerror(errno)); goto end; } @@ -162,10 +159,9 @@ 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)); if (infile && infp) fclose(infp); if (outfile && outfp) fclose(outfp); - gmssl_secure_clear(&ctx, sizeof(ctx)); - gmssl_secure_clear(inbuf, sizeof(inbuf)); - gmssl_secure_clear(outbuf, sizeof(outbuf)); return ret; } diff --git a/tools/sm4_ctr_sm3_hmac.c b/tools/sm4_ctr_sm3_hmac.c new file mode 100755 index 00000000..25f85557 --- /dev/null +++ b/tools/sm4_ctr_sm3_hmac.c @@ -0,0 +1,231 @@ +/* + * Copyright 2014-2024 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 +#include + + +static const char *usage = "{-encrypt|-decrypt} -key hex -iv hex [-aad str| -aad_hex hex] [-in file] [-out file]"; + +static const char *options = +"Options\n" +"\n" +" -encrypt Encrypt\n" +" -decrypt Decrypt\n" +" -key hex Symmetric key in HEX format, 48 bytes\n" +" -iv hex IV in HEX format, 16 bytes\n" +" -aad str Authenticated-only message\n" +" -aad_hex hex Authenticated-only data in HEX format\n" +" -in file | stdin Input data\n" +" -out file | stdout Output data\n" +"\n" +"Examples" +"\n" +" echo \"hello\" | gmssl sm4_ctr_sm3_hmac -encrypt -key 11223344556677881122334455667788 -iv 112233445566778811223344 -out ciphertext.bin\n" +" gmssl sm4_ctr_sm3_hmac -decrypt -key 11223344556677881122334455667788 -iv 112233445566778811223344 -in ciphertext.bin\n" +"\n"; + +int sm4_ctr_sm3_hmac_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + int enc = -1; + char *keyhex = NULL; + char *ivhex = NULL; + uint8_t *aad = NULL; + uint8_t *aad_buf = NULL; + size_t aadlen = 0; + char *infile = NULL; + char *outfile = NULL; + uint8_t key[48]; + size_t keylen; + uint8_t iv[16]; + size_t ivlen; + FILE *infp = stdin; + FILE *outfp = stdout; + SM4_CTR_SM3_HMAC_CTX ctx; + uint8_t buf[4096]; + size_t inlen; + size_t outlen; + + 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", options); + ret = 0; + goto end; + } else if (!strcmp(*argv, "-encrypt")) { + if (enc == 0) { + fprintf(stderr, "gmssl %s: `-encrypt` `-decrypt` should not be used together\n", prog); + goto end; + } + enc = 1; + } else if (!strcmp(*argv, "-decrypt")) { + if (enc == 1) { + fprintf(stderr, "gmssl %s: `-encrypt` `-decrypt` should not be used together\n", prog); + goto end; + } + enc = 0; + } else if (!strcmp(*argv, "-key")) { + if (--argc < 1) goto bad; + keyhex = *(++argv); + if (strlen(keyhex) != sizeof(key) * 2) { + fprintf(stderr, "gmssl %s: invalid key length, should be %d bytes\n", prog, SM4_CTR_SM3_HMAC_KEY_SIZE); + goto end; + } + if (hex_to_bytes(keyhex, strlen(keyhex), key, &keylen) != 1) { + fprintf(stderr, "gmssl %s: invalid key hex digits, should be %d bytes\n", prog, SM4_CTR_SM3_HMAC_IV_SIZE); + goto end; + } + } else if (!strcmp(*argv, "-iv")) { + if (--argc < 1) goto bad; + ivhex = *(++argv); + if (strlen(ivhex) != sizeof(iv) * 2) { + fprintf(stderr, "gmssl %s: invalid IV length\n", prog); + goto end; + } + if (hex_to_bytes(ivhex, strlen(ivhex), iv, &ivlen) != 1) { + fprintf(stderr, "gmssl %s: invalid IV hex digits\n", prog); + goto end; + } + } else if (!strcmp(*argv, "-aad")) { + if (--argc < 1) goto bad; + if (aad) { + fprintf(stderr, "gmssl %s: `-aad` or `aad_hex` has been specified\n", prog); + goto bad; + } + aad = (uint8_t *)(*(++argv)); + aadlen = strlen((char *)aad); + } else if (!strcmp(*argv, "-aad_hex")) { + if (--argc < 1) goto bad; + if (aad) { + fprintf(stderr, "gmssl %s: `-aad` or `aad_hex` has been specified\n", prog); + goto bad; + } + aad = (uint8_t *)(*(++argv)); + if (!(aad_buf = malloc(strlen((char *)aad)/2 + 1))) { + fprintf(stderr, "gmssl %s: malloc failure\n", prog); + goto end; + } + if (hex_to_bytes((char *)aad, strlen((char *)aad), aad_buf, &aadlen) != 1) { + fprintf(stderr, "gmssl %s: `-aad_hex` invalid HEX format argument\n", prog); + goto end; + } + aad = aad_buf; + } 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 (enc < 0) { + fprintf(stderr, "gmssl %s: option -encrypt or -decrypt should be set\n", prog); + goto end; + } + if (!keyhex) { + fprintf(stderr, "gmssl %s: option `-key` missing\n", prog); + goto end; + } + if (!ivhex) { + fprintf(stderr, "gmssl %s: option `-iv` missing\n", prog); + goto end; + } + + if (enc) { + if (sm4_ctr_sm3_hmac_encrypt_init(&ctx, key, iv, aad, aadlen) != 1) { + error_print(); + goto end; + } + } else { + if (sm4_ctr_sm3_hmac_decrypt_init(&ctx, key, iv, aad, aadlen) != 1) { + error_print(); + goto end; + } + } + + while ((inlen = fread(buf, 1, sizeof(buf), infp)) > 0) { + if (enc) { + if (sm4_ctr_sm3_hmac_encrypt_update(&ctx, buf, inlen, buf, &outlen) != 1) { + error_print(); + goto end; + } + } else { + if (sm4_ctr_sm3_hmac_decrypt_update(&ctx, buf, inlen, buf, &outlen) != 1) { + error_print(); + goto end; + } + } + if (fwrite(buf, 1, outlen, outfp) != outlen) { + fprintf(stderr, "gmssl %s: output failure : %s\n", prog, strerror(errno)); + goto end; + } + } + + if (enc) { + if (sm4_ctr_sm3_hmac_encrypt_finish(&ctx, buf, &outlen) != 1) { + error_print(); + goto end; + } + } else { + if (sm4_ctr_sm3_hmac_decrypt_finish(&ctx, buf, &outlen) != 1) { + error_print(); + goto end; + } + } + if (fwrite(buf, 1, outlen, outfp) != outlen) { + fprintf(stderr, "gmssl %s: output failure : %s\n", prog, strerror(errno)); + goto end; + } + + ret = 0; + +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)); + if (infile && infp) fclose(infp); + if (outfile && outfp) fclose(outfp); + return ret; +} diff --git a/tools/sm4_ecb.c b/tools/sm4_ecb.c new file mode 100755 index 00000000..8fa11221 --- /dev/null +++ b/tools/sm4_ecb.c @@ -0,0 +1,191 @@ +/* + * Copyright 2014-2024 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 +#include + + +static const char *usage = "{-encrypt|-decrypt} -key hex [-in file] [-out file]"; + +static const char *options = +"Options\n" +"\n" +" -encrypt Encrypt\n" +" -decrypt Decrypt\n" +" -key hex Symmetric key in HEX format\n" +" -in file | stdin Input data\n" +" -out file | stdout Output data\n" +"\n" +"Examples" +"\n" +" echo \"hello\" | gmssl sm4_ecb -encrypt -key 11223344556677881122334455667788 -iv 112233445566778811223344 -out ciphertext.bin\n" +"\n"; + +int sm4_ecb_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + int enc = -1; + char *keyhex = NULL; + char *ivhex = NULL; + char *infile = NULL; + char *outfile = NULL; + uint8_t key[16]; + size_t keylen; + uint8_t iv[16]; + size_t ivlen; + FILE *infp = stdin; + FILE *outfp = stdout; + SM4_ECB_CTX ctx; + uint8_t buf[4096]; + size_t inlen; + size_t outlen; + + 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", options); + ret = 0; + goto end; + } else if (!strcmp(*argv, "-encrypt")) { + if (enc == 0) { + fprintf(stderr, "gmssl %s: `-encrypt` `-decrypt` should not be used together\n", prog); + goto end; + } + enc = 1; + } else if (!strcmp(*argv, "-decrypt")) { + if (enc == 1) { + fprintf(stderr, "gmssl %s: `-encrypt` `-decrypt` should not be used together\n", prog); + goto end; + } + enc = 0; + } else if (!strcmp(*argv, "-key")) { + if (--argc < 1) goto bad; + keyhex = *(++argv); + if (strlen(keyhex) != sizeof(key) * 2) { + fprintf(stderr, "gmssl %s: invalid key length\n", prog); + goto end; + } + if (hex_to_bytes(keyhex, strlen(keyhex), key, &keylen) != 1) { + fprintf(stderr, "gmssl %s: invalid key hex digits\n", prog); + goto end; + } + } 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 (enc < 0) { + fprintf(stderr, "gmssl %s: option -encrypt or -decrypt should be set\n", prog); + goto end; + } + if (!keyhex) { + fprintf(stderr, "gmssl %s: option `-key` missing\n", prog); + goto end; + } + if (!ivhex) { + fprintf(stderr, "gmssl %s: option `-iv` missing\n", prog); + goto end; + } + + if (enc) { + if (sm4_ecb_encrypt_init(&ctx, key) != 1) { + error_print(); + goto end; + } + } else { + if (sm4_ecb_decrypt_init(&ctx, key) != 1) { + error_print(); + goto end; + } + } + + while ((inlen = fread(buf, 1, sizeof(buf), infp)) > 0) { + + if (enc) { + if (sm4_ecb_encrypt_update(&ctx, buf, inlen, buf, &outlen) != 1) { + error_print(); + goto end; + } + } else { + if (sm4_ecb_decrypt_update(&ctx, buf, inlen, buf, &outlen) != 1) { + error_print(); + goto end; + } + } + + if (fwrite(buf, 1, outlen, outfp) != outlen) { + fprintf(stderr, "gmssl %s: output failure : %s\n", prog, strerror(errno)); + goto end; + } + } + + if (enc) { + if (sm4_ecb_encrypt_finish(&ctx, buf, &outlen) != 1) { + error_print(); + goto end; + } + } else { + if (sm4_ecb_decrypt_finish(&ctx, buf, &outlen) != 1) { + error_print(); + goto end; + } + } + if (fwrite(buf, 1, outlen, outfp) != outlen) { + fprintf(stderr, "gmssl %s: output failure : %s\n", prog, strerror(errno)); + goto end; + } + + ret = 0; + +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)); + if (infile && infp) fclose(infp); + if (outfile && outfp) fclose(outfp); + return ret; +} diff --git a/tools/sm4_gcm.c b/tools/sm4_gcm.c new file mode 100755 index 00000000..6756e968 --- /dev/null +++ b/tools/sm4_gcm.c @@ -0,0 +1,240 @@ +/* + * Copyright 2014-2024 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 +#include + + +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 = +"Options\n" +"\n" +" -encrypt Encrypt\n" +" -decrypt Decrypt\n" +" -key hex Symmetric key in HEX format\n" +" -iv hex IV in HEX format, 12 bytes (24 hex digits) is recommended\n" +" -aad str Authenticated-only message\n" +" -aad_hex hex Authenticated-only data in HEX format\n" +" -taglen num MAC tag length, default 16 bytes\n" +" -in file | stdin Input data\n" +" -out file | stdout Output data\n" +"\n" +"Examples" +"\n" +" echo \"hello\" | gmssl sm4_gcm -encrypt -key 11223344556677881122334455667788 -iv 112233445566778811223344 -out ciphertext.bin\n" +" gmssl sm4_gcm -decrypt -key 11223344556677881122334455667788 -iv 112233445566778811223344 -in ciphertext.bin\n" +"\n"; + +int sm4_gcm_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + int enc = -1; + char *keyhex = NULL; + char *ivhex = NULL; + uint8_t *aad = NULL; + uint8_t *aad_buf = NULL; + size_t aadlen = 0; + int taglen = SM4_GCM_DEFAULT_TAG_SIZE; + char *infile = NULL; + char *outfile = NULL; + uint8_t key[16]; + size_t keylen; + uint8_t iv[SM4_GCM_MAX_IV_SIZE]; + size_t ivlen; + FILE *infp = stdin; + FILE *outfp = stdout; + SM4_GCM_CTX ctx; + uint8_t buf[4096]; + size_t inlen; + size_t outlen; + + 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", options); + ret = 0; + goto end; + } else if (!strcmp(*argv, "-encrypt")) { + if (enc == 0) { + fprintf(stderr, "gmssl %s: `-encrypt` `-decrypt` should not be used together\n", prog); + goto end; + } + enc = 1; + } else if (!strcmp(*argv, "-decrypt")) { + if (enc == 1) { + fprintf(stderr, "gmssl %s: `-encrypt` `-decrypt` should not be used together\n", prog); + goto end; + } + enc = 0; + } else if (!strcmp(*argv, "-key")) { + if (--argc < 1) goto bad; + keyhex = *(++argv); + if (strlen(keyhex) != sizeof(key) * 2) { + fprintf(stderr, "gmssl %s: invalid key length\n", prog); + goto end; + } + if (hex_to_bytes(keyhex, strlen(keyhex), key, &keylen) != 1) { + fprintf(stderr, "gmssl %s: invalid key hex digits\n", prog); + goto end; + } + } else if (!strcmp(*argv, "-iv")) { + if (--argc < 1) goto bad; + ivhex = *(++argv); + if (strlen(ivhex) > sizeof(iv) * 2) { + fprintf(stderr, "gmssl %s: invalid IV length\n", prog); + goto end; + } + if (hex_to_bytes(ivhex, strlen(ivhex), iv, &ivlen) != 1) { + fprintf(stderr, "gmssl %s: invalid IV hex digits\n", prog); + goto end; + } + } else if (!strcmp(*argv, "-aad")) { + if (--argc < 1) goto bad; + if (aad) { + fprintf(stderr, "gmssl %s: `-aad` or `aad_hex` has been specified\n", prog); + goto bad; + } + aad = (uint8_t *)(*(++argv)); + aadlen = strlen((char *)aad); + } else if (!strcmp(*argv, "-aad_hex")) { + if (--argc < 1) goto bad; + if (aad) { + fprintf(stderr, "gmssl %s: `-aad` or `aad_hex` has been specified\n", prog); + goto bad; + } + aad = (uint8_t *)(*(++argv)); + if (!(aad_buf = malloc(strlen((char *)aad)/2 + 1))) { + fprintf(stderr, "gmssl %s: malloc failure\n", prog); + goto end; + } + if (hex_to_bytes((char *)aad, strlen((char *)aad), aad_buf, &aadlen) != 1) { + fprintf(stderr, "gmssl %s: `-aad_hex` invalid HEX format argument\n", prog); + goto end; + } + aad = aad_buf; + } else if (!strcmp(*argv, "-taglen")) { + if (--argc < 1) goto bad; + taglen = atoi(*(++argv)); + if (taglen < SM4_GCM_MIN_TAG_SIZE || taglen > SM4_GCM_MAX_TAG_SIZE) { + fprintf(stderr, "%s: `-taglen` invalid integer argument\n", prog); + goto end; + } + } 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 (enc < 0) { + fprintf(stderr, "gmssl %s: option -encrypt or -decrypt should be set\n", prog); + goto end; + } + if (!keyhex) { + fprintf(stderr, "gmssl %s: option `-key` missing\n", prog); + goto end; + } + if (!ivhex) { + fprintf(stderr, "gmssl %s: option `-iv` missing\n", prog); + goto end; + } + + if (enc) { + if (sm4_gcm_encrypt_init(&ctx, key, keylen, iv, ivlen, aad, aadlen, taglen) != 1) { + error_print(); + goto end; + } + } else { + if (sm4_gcm_decrypt_init(&ctx, key, keylen, iv, ivlen, aad, aadlen, taglen) != 1) { + error_print(); + goto end; + } + } + + while ((inlen = fread(buf, 1, sizeof(buf), infp)) > 0) { + if (enc) { + if (sm4_gcm_encrypt_update(&ctx, buf, inlen, buf, &outlen) != 1) { + error_print(); + goto end; + } + } else { + if (sm4_gcm_decrypt_update(&ctx, buf, inlen, buf, &outlen) != 1) { + error_print(); + goto end; + } + } + if (fwrite(buf, 1, outlen, outfp) != outlen) { + fprintf(stderr, "gmssl %s: output failure : %s\n", prog, strerror(errno)); + goto end; + } + } + + if (enc) { + if (sm4_gcm_encrypt_finish(&ctx, buf, &outlen) != 1) { + error_print(); + goto end; + } + } else { + if (sm4_gcm_decrypt_finish(&ctx, buf, &outlen) != 1) { + error_print(); + goto end; + } + } + if (fwrite(buf, 1, outlen, outfp) != outlen) { + fprintf(stderr, "gmssl %s: output failure : %s\n", prog, strerror(errno)); + goto end; + } + + ret = 0; + +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)); + if (infile && infp) fclose(infp); + if (outfile && outfp) fclose(outfp); + return ret; +} diff --git a/tools/sm4_ofb.c b/tools/sm4_ofb.c new file mode 100755 index 00000000..210d5fa2 --- /dev/null +++ b/tools/sm4_ofb.c @@ -0,0 +1,167 @@ +/* + * Copyright 2014-2024 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 +#include + + +static const char *usage = "[-encrypt|-decrypt] -key hex -iv hex [-in file] [-out file]"; + +static const char *options = +"Options\n" +"\n" +" -encrypt Encrypt\n" +" -decrypt Decrypt\n" +" -key hex Symmetric key in HEX format\n" +" -iv hex IV in HEX format\n" +" -in file | stdin Input data\n" +" -out file | stdout Output data\n" +"\n" +"Examples" +"\n" +" echo \"hello\" | gmssl sm4_ofb -key 11223344556677881122334455667788 -iv 112233445566778811223344 -out ciphertext.bin\n" +"\n"; + +int sm4_ofb_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + char *keyhex = NULL; + char *ivhex = NULL; + char *infile = NULL; + char *outfile = NULL; + uint8_t key[16]; + size_t keylen; + uint8_t iv[16]; + size_t ivlen; + FILE *infp = stdin; + FILE *outfp = stdout; + SM4_OFB_CTX ctx; + uint8_t buf[4096]; + size_t inlen; + size_t outlen; + + 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", options); + ret = 0; + goto end; + } else if (!strcmp(*argv, "-encrypt")) { + // ignore this option + } else if (!strcmp(*argv, "-decrypt")) { + // ignore this option + } else if (!strcmp(*argv, "-key")) { + if (--argc < 1) goto bad; + keyhex = *(++argv); + if (strlen(keyhex) != sizeof(key) * 2) { + fprintf(stderr, "gmssl %s: invalid key length\n", prog); + goto end; + } + if (hex_to_bytes(keyhex, strlen(keyhex), key, &keylen) != 1) { + fprintf(stderr, "gmssl %s: invalid key hex digits\n", prog); + goto end; + } + } else if (!strcmp(*argv, "-iv")) { + if (--argc < 1) goto bad; + ivhex = *(++argv); + if (strlen(ivhex) != sizeof(iv) * 2) { + fprintf(stderr, "gmssl %s: invalid IV length\n", prog); + goto end; + } + if (hex_to_bytes(ivhex, strlen(ivhex), iv, &ivlen) != 1) { + fprintf(stderr, "gmssl %s: invalid IV hex digits\n", prog); + goto end; + } + } 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` missing\n", prog); + goto end; + } + if (!ivhex) { + fprintf(stderr, "gmssl %s: option `-iv` missing\n", prog); + goto end; + } + + if (sm4_ofb_encrypt_init(&ctx, key, iv) != 1) { + error_print(); + goto end; + } + + while ((inlen = fread(buf, 1, sizeof(buf), infp)) > 0) { + if (sm4_ofb_encrypt_update(&ctx, buf, inlen, buf, &outlen) != 1) { + error_print(); + goto end; + } + if (fwrite(buf, 1, outlen, outfp) != outlen) { + fprintf(stderr, "gmssl %s: output failure : %s\n", prog, strerror(errno)); + goto end; + } + } + + if (sm4_ofb_encrypt_finish(&ctx, buf, &outlen) != 1) { + error_print(); + goto end; + } + if (fwrite(buf, 1, outlen, outfp) != outlen) { + fprintf(stderr, "gmssl %s: output failure : %s\n", prog, strerror(errno)); + goto end; + } + + ret = 0; + +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)); + if (infile && infp) fclose(infp); + if (outfile && outfp) fclose(outfp); + return ret; +}