diff --git a/src/sm4_cfb.c b/src/sm4_cfb.c index e086b3b2..a169eaea 100644 --- a/src/sm4_cfb.c +++ b/src/sm4_cfb.c @@ -13,24 +13,25 @@ #include +// sm4_cfb_encrypt iv type is not compatible with sm4_cbc_encrypt, carefull if inlen % sbytes != 0 void sm4_cfb_encrypt(const SM4_KEY *key, size_t sbytes, uint8_t iv[16], const uint8_t *in, size_t inlen, uint8_t *out) { uint8_t block[16]; size_t len, i; - // assert(1 <= sbytes && sbytes <= 16); - while (inlen) { len = inlen < sbytes ? inlen : sbytes; + sm4_encrypt(key, iv, block); + gmssl_memxor(out, in, block, len); // iv = (iv << sbytes) | out for (i = 0; i < 16 - sbytes; i++) { iv[i] = iv[sbytes + i]; } - memcpy(iv + i, out, len); + memcpy(iv + 16 - sbytes, out, len); in += len; out += len; @@ -44,18 +45,19 @@ void sm4_cfb_decrypt(const SM4_KEY *key, size_t sbytes, uint8_t iv[16], uint8_t block[16]; size_t len, i; - // assert(1 <= sbytes && sbytes <= 16); - while (inlen) { len = inlen < sbytes ? inlen : sbytes; + sm4_encrypt(key, iv, block); - gmssl_memxor(out, in, block, len); // iv = (iv << sbytes) | in for (i = 0; i < 16 - sbytes; i++) { iv[i] = iv[sbytes + i]; } - memcpy(iv + i, in, len); + memcpy(iv + 16 - sbytes, in, len); + + // NOTE: must update before output, in might be changed if in == out + gmssl_memxor(out, in, block, len); in += len; out += len; @@ -191,6 +193,8 @@ int sm4_cfb_decrypt_update(SM4_CFB_CTX *ctx, } *outlen = 0; if (ctx->block_nbytes) { + error_print(); + left = ctx->sbytes - ctx->block_nbytes; if (inlen < left) { memcpy(ctx->block + ctx->block_nbytes, in, inlen); diff --git a/src/sm4_ofb.c b/src/sm4_ofb.c index cf82e236..2dc03f37 100644 --- a/src/sm4_ofb.c +++ b/src/sm4_ofb.c @@ -13,6 +13,7 @@ #include +// sm4_ofb_encrypt iv type is not compatible with sm4_cbc_encrypt, careful if inlen % 16 != 0 void sm4_ofb_encrypt(const SM4_KEY *key, uint8_t iv[16], const uint8_t *in, size_t inlen, uint8_t *out) { size_t len; diff --git a/tools/sm4_cfb.c b/tools/sm4_cfb.c index a8e18212..b1077ec3 100755 --- a/tools/sm4_cfb.c +++ b/tools/sm4_cfb.c @@ -18,12 +18,13 @@ #include -static const char *usage = "{-encrypt|-decrypt} -key hex -iv hex [-in file] [-out file]"; +static const char *usage = "{-encrypt|-decrypt} -sbytes num -key hex -iv hex [-in file] [-out file]"; static const char *options = "\n" "Options\n" "\n" +" -sbytes num Parameter sbytes of CFB mode, should be 1, 8 or 16, 16 by default\n" " -encrypt Encrypt\n" " -decrypt Decrypt\n" " -key hex Symmetric key in HEX format\n" @@ -36,8 +37,14 @@ static const char *options = " $ TEXT=`gmssl rand -outlen 20 -hex`\n" " $ KEY=`gmssl rand -outlen 16 -hex`\n" " $ IV=`gmssl rand -outlen 16 -hex`\n" -" $ echo -n $TEXT | gmssl sm4_cfb -encrypt -key $KEY -iv $IV -out sm4_cfb_ciphertext.bin\n" -" $ gmssl sm4_cfb -decrypt -key $KEY -iv $IV -in sm4_cfb_ciphertext.bin\n" +" $ echo -n $TEXT | gmssl sm4_cfb -encrypt -key $KEY -iv $IV -out sm4_cfb128_ciphertext.bin\n" +" $ gmssl sm4_cfb -decrypt -key $KEY -iv $IV -in sm4_cfb128_ciphertext.bin\n" +"\n" +" $ echo -n $TEXT | gmssl sm4_cfb -sbytes 1 -encrypt -key $KEY -iv $IV -out sm4_cfb8_ciphertext.bin\n" +" $ gmssl sm4_cfb -sbytes 1 -decrypt -key $KEY -iv $IV -in sm4_cfb8_ciphertext.bin\n" +"\n" +" $ echo -n $TEXT | gmssl sm4_cfb -sbytes 8 -encrypt -key $KEY -iv $IV -out sm4_cfb64_ciphertext.bin\n" +" $ gmssl sm4_cfb -sbytes 8 -decrypt -key $KEY -iv $IV -in sm4_cfb64_ciphertext.bin\n" "\n"; int sm4_cfb_main(int argc, char **argv) @@ -45,6 +52,7 @@ int sm4_cfb_main(int argc, char **argv) int ret = 1; char *prog = argv[0]; int enc = -1; + int sbytes = SM4_CFB_128; char *keyhex = NULL; char *ivhex = NULL; char *infile = NULL; @@ -86,6 +94,14 @@ int sm4_cfb_main(int argc, char **argv) goto end; } enc = 0; + } else if (!strcmp(*argv, "-sbytes")) { + if (--argc < 1) goto bad; + sbytes = atoi(*(++argv)); + if (sbytes != SM4_CFB_8 && sbytes != SM4_CFB_64 && sbytes != SM4_CFB_128) { + fprintf(stderr, "%s: value of `-sbytes` should be %d, %d or %d\n", prog, + SM4_CFB_8, SM4_CFB_64, SM4_CFB_128); + goto end; + } } else if (!strcmp(*argv, "-key")) { if (--argc < 1) goto bad; keyhex = *(++argv); @@ -148,12 +164,12 @@ bad: } if (enc) { - if (sm4_cfb_encrypt_init(&ctx, 16, key, iv) != 1) { + if (sm4_cfb_encrypt_init(&ctx, sbytes, key, iv) != 1) { error_print(); goto end; } } else { - if (sm4_cfb_decrypt_init(&ctx, 16, key, iv) != 1) { + if (sm4_cfb_decrypt_init(&ctx, sbytes, key, iv) != 1) { error_print(); goto end; }