From 2d0378f3c7dce6895ee95001ff21494c6b60db0f Mon Sep 17 00:00:00 2001 From: Zhi Guan Date: Wed, 10 Apr 2024 16:07:44 +0800 Subject: [PATCH] Adjust SM4 source files --- CMakeLists.txt | 8 +- include/gmssl/aead.h | 25 -- include/gmssl/gcm.h | 25 +- include/gmssl/ghash.h | 49 +++ include/gmssl/sm4.h | 33 ++ src/aead.c | 534 --------------------------------- src/gcm.c | 149 --------- src/ghash.c | 169 +++++++++++ src/{sm4_modes.c => sm4_cbc.c} | 179 +---------- src/sm4_cbc_sm3_hmac.c | 180 +++++++++++ src/sm4_ctr.c | 104 +++++++ src/sm4_ctr_sm3_hmac.c | 191 ++++++++++++ src/sm4_gcm.c | 294 ++++++++++++++++++ 13 files changed, 1029 insertions(+), 911 deletions(-) create mode 100644 include/gmssl/ghash.h delete mode 100644 src/aead.c create mode 100644 src/ghash.c rename src/{sm4_modes.c => sm4_cbc.c} (57%) create mode 100644 src/sm4_cbc_sm3_hmac.c create mode 100644 src/sm4_ctr.c create mode 100644 src/sm4_ctr_sm3_hmac.c create mode 100644 src/sm4_gcm.c diff --git a/CMakeLists.txt b/CMakeLists.txt index d4c4c21b..771b61d8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,9 @@ set(src src/version.c src/debug.c src/sm4.c - src/sm4_modes.c + src/sm4_cbc.c + src/sm4_ctr.c + src/sm4_gcm.c src/sm3.c src/sm3_hmac.c src/sm3_kdf.c @@ -40,8 +42,10 @@ set(src src/hkdf.c src/pbkdf2.c src/gf128.c + src/ghash.c src/gcm.c - src/aead.c + src/sm4_cbc_sm3_hmac.c + src/sm4_ctr_sm3_hmac.c src/pkcs8.c src/ec.c src/rsa.c diff --git a/include/gmssl/aead.h b/include/gmssl/aead.h index 1bc13b57..2b76e663 100644 --- a/include/gmssl/aead.h +++ b/include/gmssl/aead.h @@ -74,32 +74,7 @@ _gmssl_export int sm4_ctr_sm3_hmac_decrypt_finish(SM4_CTR_SM3_HMAC_CTX *ctx, uint8_t *out, size_t *outlen); -typedef struct { - SM4_CTR_CTX enc_ctx; - GHASH_CTX mac_ctx; - uint8_t Y[16]; // E(K, Y_0) - size_t taglen; - uint8_t mac[16]; - size_t maclen; -} SM4_GCM_CTX; -#define SM4_GCM_KEY_SIZE 16 -#define SM4_GCM_DEFAULT_TAG_SIZE 16 - -_gmssl_export int sm4_gcm_encrypt_init(SM4_GCM_CTX *ctx, - const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, - const uint8_t *aad, size_t aadlen, size_t taglen); -_gmssl_export int sm4_gcm_encrypt_update(SM4_GCM_CTX *ctx, - const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen); -_gmssl_export int sm4_gcm_encrypt_finish(SM4_GCM_CTX *ctx, - uint8_t *out, size_t *outlen); -_gmssl_export int sm4_gcm_decrypt_init(SM4_GCM_CTX *ctx, - const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, - const uint8_t *aad, size_t aadlen, size_t taglen); -_gmssl_export int sm4_gcm_decrypt_update(SM4_GCM_CTX *ctx, - const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen); -_gmssl_export int sm4_gcm_decrypt_finish(SM4_GCM_CTX *ctx, - uint8_t *out, size_t *outlen); #ifdef __cplusplus diff --git a/include/gmssl/gcm.h b/include/gmssl/gcm.h index 97c62fcc..c2aae9f0 100644 --- a/include/gmssl/gcm.h +++ b/include/gmssl/gcm.h @@ -1,5 +1,5 @@ /* - * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * 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. @@ -7,7 +7,6 @@ * http://www.apache.org/licenses/LICENSE-2.0 */ - #ifndef GMSSL_GCM_H #define GMSSL_GCM_H @@ -15,7 +14,7 @@ #include #include #include -#include +#include #include @@ -35,29 +34,9 @@ extern "C" { #define GCM_MAX_PLAINTEXT_SIZE ((((uint64_t)1 << 39) - 256) >> 3) -#define GHASH_SIZE (16) - - #define GCM_IS_LITTLE_ENDIAN 1 -void ghash(const uint8_t h[16], const uint8_t *aad, size_t aadlen, - const uint8_t *c, size_t clen, uint8_t out[16]); - -typedef struct { - gf128_t H; - gf128_t X; - size_t aadlen; - size_t clen; - uint8_t block[16]; - size_t num; -} GHASH_CTX; - -void ghash_init(GHASH_CTX *ctx, const uint8_t h[16], const uint8_t *aad, size_t aadlen); -void ghash_update(GHASH_CTX *ctx, const uint8_t *c, size_t clen); -void ghash_finish(GHASH_CTX *ctx, uint8_t out[16]); - - int gcm_encrypt(const BLOCK_CIPHER_KEY *key, const uint8_t *iv, size_t ivlen, const uint8_t *aad, size_t aadlen, const uint8_t *in, size_t inlen, uint8_t *out, size_t taglen, uint8_t *tag); diff --git a/include/gmssl/ghash.h b/include/gmssl/ghash.h new file mode 100644 index 00000000..27445f30 --- /dev/null +++ b/include/gmssl/ghash.h @@ -0,0 +1,49 @@ +/* + * 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 + */ + +#ifndef GMSSL_GHASH_H +#define GMSSL_GHASH_H + + +#include +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +#define GHASH_SIZE (16) + + + +void ghash(const uint8_t h[16], const uint8_t *aad, size_t aadlen, + const uint8_t *c, size_t clen, uint8_t out[16]); + +typedef struct { + gf128_t H; + gf128_t X; + size_t aadlen; + size_t clen; + uint8_t block[16]; + size_t num; +} GHASH_CTX; + +void ghash_init(GHASH_CTX *ctx, const uint8_t h[16], const uint8_t *aad, size_t aadlen); +void ghash_update(GHASH_CTX *ctx, const uint8_t *c, size_t clen); +void ghash_finish(GHASH_CTX *ctx, uint8_t out[16]); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/gmssl/sm4.h b/include/gmssl/sm4.h index 63476df3..eefe5160 100644 --- a/include/gmssl/sm4.h +++ b/include/gmssl/sm4.h @@ -119,6 +119,39 @@ int sm4_ctr_encrypt_finish(SM4_CTR_CTX *ctx, uint8_t *out, size_t *outlen); #define sm4_ctr_decrypt_finish(ctx,out,outlen) sm4_ctr_encrypt_finish(ctx,out,outlen) +#include +#include + +typedef struct { + SM4_CTR_CTX enc_ctx; + GHASH_CTX mac_ctx; + uint8_t Y[16]; // E(K, Y_0) + size_t taglen; + uint8_t mac[16]; + size_t maclen; +} SM4_GCM_CTX; + +#define SM4_GCM_KEY_SIZE 16 +#define SM4_GCM_DEFAULT_TAG_SIZE 16 + +_gmssl_export int sm4_gcm_encrypt_init(SM4_GCM_CTX *ctx, + const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, + const uint8_t *aad, size_t aadlen, size_t taglen); +_gmssl_export int sm4_gcm_encrypt_update(SM4_GCM_CTX *ctx, + const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen); +_gmssl_export int sm4_gcm_encrypt_finish(SM4_GCM_CTX *ctx, + uint8_t *out, size_t *outlen); +_gmssl_export int sm4_gcm_decrypt_init(SM4_GCM_CTX *ctx, + const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, + const uint8_t *aad, size_t aadlen, size_t taglen); +_gmssl_export int sm4_gcm_decrypt_update(SM4_GCM_CTX *ctx, + const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen); +_gmssl_export int sm4_gcm_decrypt_finish(SM4_GCM_CTX *ctx, + uint8_t *out, size_t *outlen); + + + + #ifdef ENABLE_SM4_ECB // call `sm4_set_decrypt_key` before decrypt void sm4_ecb_encrypt(const SM4_KEY *key, const uint8_t *in, size_t nblocks, uint8_t *out); diff --git a/src/aead.c b/src/aead.c deleted file mode 100644 index 7dcbe73c..00000000 --- a/src/aead.c +++ /dev/null @@ -1,534 +0,0 @@ -/* - * 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 - - -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 *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(); - return -1; - } - sm3_hmac_init(&ctx->mac_ctx, key + SM4_KEY_SIZE, SM3_HMAC_SIZE); - if (aad && aadlen) { - sm3_hmac_update(&ctx->mac_ctx, aad, aadlen); - } - return 1; -} - -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) -{ - if (!ctx || !in || !out || !outlen) { - error_print(); - return -1; - } - if (sm4_cbc_encrypt_update(&ctx->enc_ctx, in, inlen, out, outlen) != 1) { - error_print(); - return -1; - } - sm3_hmac_update(&ctx->mac_ctx, out, *outlen); - return 1; -} - -int sm4_cbc_sm3_hmac_encrypt_finish(SM4_CBC_SM3_HMAC_CTX *ctx, uint8_t *out, size_t *outlen) -{ - if (!ctx || !out || !outlen) { - error_print(); - return -1; - } - if (sm4_cbc_encrypt_finish(&ctx->enc_ctx, out, outlen) != 1) { - error_print(); - return -1; - } - sm3_hmac_update(&ctx->mac_ctx, out, *outlen); - sm3_hmac_finish(&ctx->mac_ctx, out + *outlen); - *outlen += SM3_HMAC_SIZE; - return 1; -} - -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 *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(); - return -1; - } - sm3_hmac_init(&ctx->mac_ctx, key + SM4_KEY_SIZE, SM3_HMAC_SIZE); - if (aad && aadlen) { - sm3_hmac_update(&ctx->mac_ctx, aad, aadlen); - } - return 1; -} - -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) -{ - size_t len; - - if (!ctx || !in || !out || !outlen) { - error_print(); - return -1; - } - if (ctx->maclen > SM3_HMAC_SIZE) { - error_print(); - return -1; - } - - if (ctx->maclen < SM3_HMAC_SIZE) { - len = SM3_HMAC_SIZE - ctx->maclen; - if (inlen <= len) { - memcpy(ctx->mac + ctx->maclen, in, inlen); - ctx->maclen += inlen; - return 1; - } else { - memcpy(ctx->mac + ctx->maclen, in, len); - ctx->maclen += len; - in += len; - inlen -= len; - } - } - - if (inlen <= SM3_HMAC_SIZE) { - uint8_t tmp[SM3_HMAC_SIZE]; - sm3_hmac_update(&ctx->mac_ctx, ctx->mac, inlen); - if (sm4_cbc_decrypt_update(&ctx->enc_ctx, ctx->mac, inlen, out, outlen) != 1) { - error_print(); - return -1; - } - len = SM3_HMAC_SIZE - inlen; - memcpy(tmp, ctx->mac + inlen, len); - memcpy(tmp + len, in, inlen); - memcpy(ctx->mac, tmp, SM3_HMAC_SIZE); - } else { - sm3_hmac_update(&ctx->mac_ctx, ctx->mac, SM3_HMAC_SIZE); - if (sm4_cbc_decrypt_update(&ctx->enc_ctx, ctx->mac, SM3_HMAC_SIZE, out, outlen) != 1) { - error_print(); - return -1; - } - out += *outlen; - - inlen -= SM3_HMAC_SIZE; - sm3_hmac_update(&ctx->mac_ctx, in, inlen); - if (sm4_cbc_decrypt_update(&ctx->enc_ctx, in, inlen, out, &len) != 1) { - error_print(); - return -1; - } - *outlen += len; - memcpy(ctx->mac, in + inlen, SM3_HMAC_SIZE); - } - return 1; -} - -int sm4_cbc_sm3_hmac_decrypt_finish(SM4_CBC_SM3_HMAC_CTX *ctx, uint8_t *out, size_t *outlen) -{ - uint8_t mac[SM3_HMAC_SIZE]; - - if (!ctx || !out || !outlen) { - error_print(); - return -1; - } - if (ctx->maclen != SM3_HMAC_SIZE) { - error_print(); - return -1; - } - sm3_hmac_finish(&ctx->mac_ctx, mac); - if (sm4_cbc_decrypt_finish(&ctx->enc_ctx, out, outlen) != 1) { - error_print(); - return -1; - } - if (memcmp(mac, ctx->mac, SM3_HMAC_SIZE) != 0) { - error_print(); - return -1; - } - memset(ctx->mac, 0, SM3_HMAC_SIZE); - ctx->maclen = 0; - return 1; -} - -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 *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(); - return -1; - } - sm3_hmac_init(&ctx->mac_ctx, key + SM4_KEY_SIZE, SM3_HMAC_SIZE); - if (aad && aadlen) { - sm3_hmac_update(&ctx->mac_ctx, aad, aadlen); - } - return 1; -} - -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) -{ - if (!ctx || !in || !out || !outlen) { - error_print(); - return -1; - } - if (sm4_ctr_encrypt_update(&ctx->enc_ctx, in, inlen, out, outlen) != 1) { - error_print(); - return -1; - } - sm3_hmac_update(&ctx->mac_ctx, out, *outlen); - return 1; -} - -int sm4_ctr_sm3_hmac_encrypt_finish(SM4_CTR_SM3_HMAC_CTX *ctx, uint8_t *out, size_t *outlen) -{ - if (!ctx || !out || !outlen) { - error_print(); - return -1; - } - if (sm4_ctr_encrypt_finish(&ctx->enc_ctx, out, outlen) != 1) { - error_print(); - return -1; - } - sm3_hmac_update(&ctx->mac_ctx, out, *outlen); - sm3_hmac_finish(&ctx->mac_ctx, out + *outlen); - *outlen += SM3_HMAC_SIZE; - return 1; -} - -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 *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_decrypt_init(&ctx->enc_ctx, key, iv) != 1) { - error_print(); - return -1; - } - sm3_hmac_init(&ctx->mac_ctx, key + SM4_KEY_SIZE, SM3_HMAC_SIZE); - if (aad && aadlen) { - sm3_hmac_update(&ctx->mac_ctx, aad, aadlen); - } - return 1; -} - -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) -{ - size_t len; - - if (!ctx || !in || !out || !outlen) { - error_print(); - return -1; - } - if (ctx->maclen > SM3_HMAC_SIZE) { - error_print(); - return -1; - } - - if (ctx->maclen < SM3_HMAC_SIZE) { - len = SM3_HMAC_SIZE - ctx->maclen; - if (inlen <= len) { - memcpy(ctx->mac + ctx->maclen, in, inlen); - ctx->maclen += inlen; - return 1; - } else { - memcpy(ctx->mac + ctx->maclen, in, len); - ctx->maclen += len; - in += len; - inlen -= len; - } - } - - if (inlen <= SM3_HMAC_SIZE) { - uint8_t tmp[SM3_HMAC_SIZE]; - sm3_hmac_update(&ctx->mac_ctx, ctx->mac, inlen); - if (sm4_ctr_decrypt_update(&ctx->enc_ctx, ctx->mac, inlen, out, outlen) != 1) { - error_print(); - return -1; - } - len = SM3_HMAC_SIZE - inlen; - memcpy(tmp, ctx->mac + inlen, len); - memcpy(tmp + len, in, inlen); - memcpy(ctx->mac, tmp, SM3_HMAC_SIZE); - } else { - sm3_hmac_update(&ctx->mac_ctx, ctx->mac, SM3_HMAC_SIZE); - if (sm4_ctr_decrypt_update(&ctx->enc_ctx, ctx->mac, SM3_HMAC_SIZE, out, outlen) != 1) { - error_print(); - return -1; - } - out += *outlen; - - inlen -= SM3_HMAC_SIZE; - sm3_hmac_update(&ctx->mac_ctx, in, inlen); - if (sm4_ctr_decrypt_update(&ctx->enc_ctx, in, inlen, out, &len) != 1) { - error_print(); - return -1; - } - *outlen += len; - memcpy(ctx->mac, in + inlen, SM3_HMAC_SIZE); - } - return 1; -} - -int sm4_ctr_sm3_hmac_decrypt_finish(SM4_CTR_SM3_HMAC_CTX *ctx, uint8_t *out, size_t *outlen) -{ - uint8_t mac[SM3_HMAC_SIZE]; - - if (!ctx || !out || !outlen) { - error_print(); - return -1; - } - if (ctx->maclen != SM3_HMAC_SIZE) { - error_print(); - return -1; - } - sm3_hmac_finish(&ctx->mac_ctx, mac); - if (sm4_ctr_decrypt_finish(&ctx->enc_ctx, out, outlen) != 1) { - error_print(); - return -1; - } - if (memcmp(mac, ctx->mac, SM3_HMAC_SIZE) != 0) { - error_print(); - return -1; - } - memset(ctx->mac, 0, SM3_HMAC_SIZE); - ctx->maclen = 0; - return 1; -} - -static void ctr_incr(uint8_t a[16]) -{ - int i; - for (i = 15; i >= 0; i--) { - a[i]++; - if (a[i]) break; - } -} - -int sm4_gcm_encrypt_init(SM4_GCM_CTX *ctx, - const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, - const uint8_t *aad, size_t aadlen, size_t taglen) -{ - uint8_t H[16] = {0}; - uint8_t Y[16]; - - if (!ctx || !key || !iv || (!aad && aadlen)) { - error_print(); - return -1; - } - if (keylen != 16) { - error_print(); - return -1; - } - if (ivlen < SM4_GCM_MIN_IV_SIZE || ivlen > SM4_GCM_MAX_IV_SIZE) { - error_print(); - return -1; - } - if (taglen < 8 || taglen > 16) { - error_print(); - return -1; - } - - memset(ctx, 0, sizeof(*ctx)); - ctx->taglen = taglen; - - if (sm4_ctr_encrypt_init(&ctx->enc_ctx, key, H) != 1) { - error_print(); - return -1; - } - - sm4_encrypt(&ctx->enc_ctx.sm4_key, H, H); - - ghash_init(&ctx->mac_ctx, H, aad, aadlen); - - if (ivlen == 12) { - memcpy(Y, iv, 12); - Y[12] = Y[13] = Y[14] = 0; - Y[15] = 1; - } else { - ghash(H, NULL, 0, iv, ivlen, Y); - } - - sm4_encrypt(&ctx->enc_ctx.sm4_key, Y, ctx->Y); - - ctr_incr(Y); - memcpy(ctx->enc_ctx.ctr, Y, 16); - - gmssl_secure_clear(H, sizeof(H)); - gmssl_secure_clear(Y, sizeof(Y)); - return 1; -} - -int sm4_gcm_encrypt_update(SM4_GCM_CTX *ctx, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) -{ - if (!ctx || !in || !out || !outlen) { - error_print(); - return -1; - } - if (sm4_ctr_encrypt_update(&ctx->enc_ctx, in, inlen, out, outlen) != 1) { - error_print(); - return -1; - } - ghash_update(&ctx->mac_ctx, out, *outlen); - return 1; -} - -int sm4_gcm_encrypt_finish(SM4_GCM_CTX *ctx, uint8_t *out, size_t *outlen) -{ - uint8_t mac[16]; - - if (!ctx || !out || !outlen) { - error_print(); - return -1; - } - if (sm4_ctr_encrypt_finish(&ctx->enc_ctx, out, outlen) != 1) { - error_print(); - return -1; - } - ghash_update(&ctx->mac_ctx, out, *outlen); - ghash_finish(&ctx->mac_ctx, mac); - - gmssl_memxor(mac, mac, ctx->Y, ctx->taglen); - memcpy(out + *outlen, mac, ctx->taglen); - *outlen += ctx->taglen; - - return 1; -} - -int sm4_gcm_decrypt_init(SM4_GCM_CTX *ctx, - const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, - const uint8_t *aad, size_t aadlen, size_t taglen) -{ - return sm4_gcm_encrypt_init(ctx, key, keylen, iv, ivlen, aad, aadlen, taglen); -} - -int sm4_gcm_decrypt_update(SM4_GCM_CTX *ctx, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) -{ - size_t len; - - if (!ctx || !in || !out || !outlen) { - error_print(); - return -1; - } - if (ctx->maclen > ctx->taglen) { - error_print(); - return -1; - } - - if (ctx->maclen < ctx->taglen) { - len = ctx->taglen - ctx->maclen; - if (inlen <= len) { - memcpy(ctx->mac + ctx->maclen, in, inlen); - ctx->maclen += inlen; - return 1; - } else { - memcpy(ctx->mac + ctx->maclen, in, len); - ctx->maclen += len; - in += len; - inlen -= len; - } - } - - if (inlen <= ctx->taglen) { - uint8_t tmp[GHASH_SIZE]; - ghash_update(&ctx->mac_ctx, ctx->mac, inlen); - if (sm4_ctr_decrypt_update(&ctx->enc_ctx, ctx->mac, inlen, out, outlen) != 1) { - error_print(); - return -1; - } - len = ctx->taglen - inlen; - memcpy(tmp, ctx->mac + inlen, len); - memcpy(tmp + len, in, inlen); - memcpy(ctx->mac, tmp, GHASH_SIZE); - } else { - ghash_update(&ctx->mac_ctx, ctx->mac, ctx->taglen); - if (sm4_ctr_decrypt_update(&ctx->enc_ctx, ctx->mac, ctx->taglen, out, outlen) != 1) { - error_print(); - return -1; - } - out += *outlen; - - inlen -= ctx->taglen; - ghash_update(&ctx->mac_ctx, in, inlen); - if (sm4_ctr_decrypt_update(&ctx->enc_ctx, in, inlen, out, &len) != 1) { - error_print(); - return -1; - } - *outlen += len; - memcpy(ctx->mac, in + inlen, GHASH_SIZE); - } - return 1; -} - -int sm4_gcm_decrypt_finish(SM4_GCM_CTX *ctx, uint8_t *out, size_t *outlen) -{ - uint8_t mac[GHASH_SIZE]; - - if (!ctx || !out || !outlen) { - error_print(); - return -1; - } - if (ctx->maclen != ctx->taglen) { - error_print(); - return -1; - } - ghash_finish(&ctx->mac_ctx, mac); - if (sm4_ctr_decrypt_finish(&ctx->enc_ctx, out, outlen) != 1) { - error_print(); - return -1; - } - - gmssl_memxor(mac, mac, ctx->Y, ctx->taglen); - if (memcmp(mac, ctx->mac, ctx->taglen) != 0) { - error_print(); - return -1; - } - memset(ctx->mac, 0, GHASH_SIZE); - ctx->maclen = 0; - return 1; -} diff --git a/src/gcm.c b/src/gcm.c index 2425f9e3..b8fbe1e9 100644 --- a/src/gcm.c +++ b/src/gcm.c @@ -13,161 +13,12 @@ #include #include #include -#include #include #include #include #include -/* - * GHASH(H, A, C) = X_{m + n + 1} - * A additional authenticated data, A = A_1, ..., A_{m-1}, A_{m^*}, nbits(A_{m^*}) = v - * C ciphertext, C = C_1, ..., C_{n-1}, C_{n^*}, nbits(C_{n^*}) = u - * H = E_K(0^128) - * - * X_i = 0 for i = 0 - * = (X_{i-1} xor A_i ) * H for i = 1, ..., m-1 - * = (X_{m-1} xor (A_m^* || 0^{128-v})) * H for i = m - * = (X_{i-1} xor C_i ) * H for i = m+1, ..., m + n − 1 - * = (X_{m+n-1} xor (C_m^* || 0^{128-u})) * H for i = m + n - * = (X_{m+n} xor (nbits(A)||nbits(C))) * H for i = m + n + 1 - */ -void ghash(const uint8_t h[16], const uint8_t *aad, size_t aadlen, const uint8_t *c, size_t clen, uint8_t out[16]) -{ - gf128_t H = gf128_from_bytes(h); - gf128_t X = gf128_zero(); - gf128_t L; - - PUTU64(out, (uint64_t)aadlen << 3); - PUTU64(out + 8, (uint64_t)clen << 3); - L = gf128_from_bytes(out); - - while (aadlen) { - gf128_t A; - if (aadlen >= 16) { - A = gf128_from_bytes(aad); - aad += 16; - aadlen -= 16; - } else { - memset(out, 0, 16); - memcpy(out, aad, aadlen); - A = gf128_from_bytes(out); - aadlen = 0; - } - X = gf128_add(X, A); - X = gf128_mul(X, H); - } - - while (clen) { - gf128_t C; - if (clen >= 16) { - C = gf128_from_bytes(c); - c += 16; - clen -= 16; - } else { - memset(out, 0, 16); - memcpy(out, c, clen); - C = gf128_from_bytes(out); - clen = 0; - } - X = gf128_add(X, C); - X = gf128_mul(X, H); - } - - X = gf128_add(X, L); - H = gf128_mul(X, H); - gf128_to_bytes(H, out); -} - - -void ghash_init(GHASH_CTX *ctx, const uint8_t h[16], const uint8_t *aad, size_t aadlen) -{ - gf128_t A; - - memset(ctx, 0, sizeof(*ctx)); - ctx->H = gf128_from_bytes(h); - ctx->X = gf128_zero(); - ctx->aadlen = aadlen; - ctx->clen = 0; - - while (aadlen) { - if (aadlen >= 16) { - A = gf128_from_bytes(aad); - aad += 16; - aadlen -= 16; - } else { - memset(ctx->block, 0, 16); - memcpy(ctx->block, aad, aadlen); - A = gf128_from_bytes(ctx->block); - aadlen = 0; - } - ctx->X = gf128_add(ctx->X, A); - ctx->X = gf128_mul(ctx->X, ctx->H); - } -} - -void ghash_update(GHASH_CTX *ctx, const uint8_t *c, size_t clen) -{ - gf128_t C; - - assert(ctx->num < 16); - - ctx->clen += clen; - - if (ctx->num) { - size_t left = 16 - ctx->num; - if (clen < left) { - memcpy(ctx->block + ctx->num, c, clen); - ctx->num += clen; - return; - } else { - memcpy(ctx->block + ctx->num, c, left); - C = gf128_from_bytes(ctx->block); - ctx->X = gf128_add(ctx->X, C); - ctx->X = gf128_mul(ctx->X, ctx->H); - c += left; - clen -= left; - } - } - - while (clen >= 16) { - C = gf128_from_bytes(c); - ctx->X = gf128_add(ctx->X, C); - ctx->X = gf128_mul(ctx->X, ctx->H); - c += 16; - clen -= 16; - } - - ctx->num = clen; - if (clen) { - memcpy(ctx->block, c, clen); - } -} - -void ghash_finish(GHASH_CTX *ctx, uint8_t out[16]) -{ - gf128_t C; - gf128_t L; - - if (ctx->num) { - memset(ctx->block + ctx->num, 0, 16 - ctx->num); - C = gf128_from_bytes(ctx->block); - ctx->X = gf128_add(ctx->X, C); - ctx->X = gf128_mul(ctx->X, ctx->H); - } - - PUTU64(ctx->block, (uint64_t)ctx->aadlen << 3); - PUTU64(ctx->block + 8, (uint64_t)ctx->clen << 3); - L = gf128_from_bytes(ctx->block); - - ctx->X = gf128_add(ctx->X, L); - ctx->H = gf128_mul(ctx->X, ctx->H); - gf128_to_bytes(ctx->H, out); - - gmssl_secure_clear(ctx, sizeof(*ctx)); -} - int gcm_encrypt(const BLOCK_CIPHER_KEY *key, const uint8_t *iv, size_t ivlen, const uint8_t *aad, size_t aadlen, const uint8_t *in, size_t inlen, uint8_t *out, size_t taglen, uint8_t *tag) diff --git a/src/ghash.c b/src/ghash.c new file mode 100644 index 00000000..e6767157 --- /dev/null +++ b/src/ghash.c @@ -0,0 +1,169 @@ +/* + * 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 +#include +#include + + +/* + * GHASH(H, A, C) = X_{m + n + 1} + * A additional authenticated data, A = A_1, ..., A_{m-1}, A_{m^*}, nbits(A_{m^*}) = v + * C ciphertext, C = C_1, ..., C_{n-1}, C_{n^*}, nbits(C_{n^*}) = u + * H = E_K(0^128) + * + * X_i = 0 for i = 0 + * = (X_{i-1} xor A_i ) * H for i = 1, ..., m-1 + * = (X_{m-1} xor (A_m^* || 0^{128-v})) * H for i = m + * = (X_{i-1} xor C_i ) * H for i = m+1, ..., m + n − 1 + * = (X_{m+n-1} xor (C_m^* || 0^{128-u})) * H for i = m + n + * = (X_{m+n} xor (nbits(A)||nbits(C))) * H for i = m + n + 1 + */ +void ghash(const uint8_t h[16], const uint8_t *aad, size_t aadlen, const uint8_t *c, size_t clen, uint8_t out[16]) +{ + gf128_t H = gf128_from_bytes(h); + gf128_t X = gf128_zero(); + gf128_t L; + + PUTU64(out, (uint64_t)aadlen << 3); + PUTU64(out + 8, (uint64_t)clen << 3); + L = gf128_from_bytes(out); + + while (aadlen) { + gf128_t A; + if (aadlen >= 16) { + A = gf128_from_bytes(aad); + aad += 16; + aadlen -= 16; + } else { + memset(out, 0, 16); + memcpy(out, aad, aadlen); + A = gf128_from_bytes(out); + aadlen = 0; + } + X = gf128_add(X, A); + X = gf128_mul(X, H); + } + + while (clen) { + gf128_t C; + if (clen >= 16) { + C = gf128_from_bytes(c); + c += 16; + clen -= 16; + } else { + memset(out, 0, 16); + memcpy(out, c, clen); + C = gf128_from_bytes(out); + clen = 0; + } + X = gf128_add(X, C); + X = gf128_mul(X, H); + } + + X = gf128_add(X, L); + H = gf128_mul(X, H); + gf128_to_bytes(H, out); +} + + +void ghash_init(GHASH_CTX *ctx, const uint8_t h[16], const uint8_t *aad, size_t aadlen) +{ + gf128_t A; + + memset(ctx, 0, sizeof(*ctx)); + ctx->H = gf128_from_bytes(h); + ctx->X = gf128_zero(); + ctx->aadlen = aadlen; + ctx->clen = 0; + + while (aadlen) { + if (aadlen >= 16) { + A = gf128_from_bytes(aad); + aad += 16; + aadlen -= 16; + } else { + memset(ctx->block, 0, 16); + memcpy(ctx->block, aad, aadlen); + A = gf128_from_bytes(ctx->block); + aadlen = 0; + } + ctx->X = gf128_add(ctx->X, A); + ctx->X = gf128_mul(ctx->X, ctx->H); + } +} + +void ghash_update(GHASH_CTX *ctx, const uint8_t *c, size_t clen) +{ + gf128_t C; + + assert(ctx->num < 16); + + ctx->clen += clen; + + if (ctx->num) { + size_t left = 16 - ctx->num; + if (clen < left) { + memcpy(ctx->block + ctx->num, c, clen); + ctx->num += clen; + return; + } else { + memcpy(ctx->block + ctx->num, c, left); + C = gf128_from_bytes(ctx->block); + ctx->X = gf128_add(ctx->X, C); + ctx->X = gf128_mul(ctx->X, ctx->H); + c += left; + clen -= left; + } + } + + while (clen >= 16) { + C = gf128_from_bytes(c); + ctx->X = gf128_add(ctx->X, C); + ctx->X = gf128_mul(ctx->X, ctx->H); + c += 16; + clen -= 16; + } + + ctx->num = clen; + if (clen) { + memcpy(ctx->block, c, clen); + } +} + +void ghash_finish(GHASH_CTX *ctx, uint8_t out[16]) +{ + gf128_t C; + gf128_t L; + + if (ctx->num) { + memset(ctx->block + ctx->num, 0, 16 - ctx->num); + C = gf128_from_bytes(ctx->block); + ctx->X = gf128_add(ctx->X, C); + ctx->X = gf128_mul(ctx->X, ctx->H); + } + + PUTU64(ctx->block, (uint64_t)ctx->aadlen << 3); + PUTU64(ctx->block + 8, (uint64_t)ctx->clen << 3); + L = gf128_from_bytes(ctx->block); + + ctx->X = gf128_add(ctx->X, L); + ctx->H = gf128_mul(ctx->X, ctx->H); + gf128_to_bytes(ctx->H, out); + + gmssl_secure_clear(ctx, sizeof(*ctx)); +} diff --git a/src/sm4_modes.c b/src/sm4_cbc.c similarity index 57% rename from src/sm4_modes.c rename to src/sm4_cbc.c index f54925ed..151f096b 100644 --- a/src/sm4_modes.c +++ b/src/sm4_cbc.c @@ -1,5 +1,5 @@ /* - * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * 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. @@ -10,7 +10,6 @@ #include #include -#include #include void sm4_cbc_encrypt(const SM4_KEY *key, const uint8_t iv[16], @@ -92,119 +91,6 @@ int sm4_cbc_padding_decrypt(const SM4_KEY *key, const uint8_t iv[16], return 1; } -static void ctr_incr(uint8_t a[16]) -{ - int i; - for (i = 15; i >= 0; i--) { - a[i]++; - if (a[i]) break; - } -} - -#ifndef ENABLE_SM4_AESNI_AVX -void sm4_ctr_encrypt(const SM4_KEY *key, uint8_t ctr[16], const uint8_t *in, size_t inlen, uint8_t *out) -{ - uint8_t block[16]; - size_t len; - - while (inlen) { - len = inlen < 16 ? inlen : 16; - sm4_encrypt(key, ctr, block); - gmssl_memxor(out, in, block, len); - ctr_incr(ctr); - in += len; - out += len; - inlen -= len; - } -} -#endif - -int sm4_gcm_encrypt(const SM4_KEY *key, const uint8_t *iv, size_t ivlen, - const uint8_t *aad, size_t aadlen, const uint8_t *in, size_t inlen, - uint8_t *out, size_t taglen, uint8_t *tag) -{ - const uint8_t *pin = in; - uint8_t *pout = out; - size_t left = inlen; - uint8_t H[16] = {0}; - uint8_t Y[16]; - uint8_t T[16]; - - if (taglen > SM4_GCM_MAX_TAG_SIZE) { - error_print(); - return -1; - } - - sm4_encrypt(key, H, H); - - if (ivlen == 12) { - memcpy(Y, iv, 12); - Y[12] = Y[13] = Y[14] = 0; - Y[15] = 1; - } else { - ghash(H, NULL, 0, iv, ivlen, Y); - } - - sm4_encrypt(key, Y, T); - - while (left) { - uint8_t block[16]; - size_t len = left < 16 ? left : 16; - ctr_incr(Y); - sm4_encrypt(key, Y, block); - gmssl_memxor(pout, pin, block, len); - pin += len; - pout += len; - left -= len; - } - - ghash(H, aad, aadlen, out, inlen, H); - gmssl_memxor(tag, T, H, taglen); - return 1; -} - -int sm4_gcm_decrypt(const SM4_KEY *key, const uint8_t *iv, size_t ivlen, - const uint8_t *aad, size_t aadlen, const uint8_t *in, size_t inlen, - const uint8_t *tag, size_t taglen, uint8_t *out) -{ - const uint8_t *pin = in; - uint8_t *pout = out; - size_t left = inlen; - uint8_t H[16] = {0}; - uint8_t Y[16]; - uint8_t T[16]; - - sm4_encrypt(key, H, H); - - if (ivlen == 12) { - memcpy(Y, iv, 12); - Y[12] = Y[13] = Y[14] = 0; - Y[15] = 1; - } else { - ghash(H, NULL, 0, iv, ivlen, Y); - } - - ghash(H, aad, aadlen, in, inlen, H); - sm4_encrypt(key, Y, T); - gmssl_memxor(T, T, H, taglen); - if (memcmp(T, tag, taglen) != 0) { - error_print(); - return -1; - } - - while (left) { - uint8_t block[16]; - size_t len = left < 16 ? left : 16; - ctr_incr(Y); - sm4_encrypt(key, Y, block); - gmssl_memxor(pout, pin, block, len); - pin += len; - pout += len; - left -= len; - } - 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]) { @@ -335,66 +221,3 @@ int sm4_cbc_decrypt_finish(SM4_CBC_CTX *ctx, uint8_t *out, size_t *outlen) } 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) -{ - 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); - *outlen = ctx->block_nbytes; - return 1; -} diff --git a/src/sm4_cbc_sm3_hmac.c b/src/sm4_cbc_sm3_hmac.c new file mode 100644 index 00000000..554e6ef0 --- /dev/null +++ b/src/sm4_cbc_sm3_hmac.c @@ -0,0 +1,180 @@ +/* + * 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 + + +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 *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(); + return -1; + } + sm3_hmac_init(&ctx->mac_ctx, key + SM4_KEY_SIZE, SM3_HMAC_SIZE); + if (aad && aadlen) { + sm3_hmac_update(&ctx->mac_ctx, aad, aadlen); + } + return 1; +} + +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) +{ + if (!ctx || !in || !out || !outlen) { + error_print(); + return -1; + } + if (sm4_cbc_encrypt_update(&ctx->enc_ctx, in, inlen, out, outlen) != 1) { + error_print(); + return -1; + } + sm3_hmac_update(&ctx->mac_ctx, out, *outlen); + return 1; +} + +int sm4_cbc_sm3_hmac_encrypt_finish(SM4_CBC_SM3_HMAC_CTX *ctx, uint8_t *out, size_t *outlen) +{ + if (!ctx || !out || !outlen) { + error_print(); + return -1; + } + if (sm4_cbc_encrypt_finish(&ctx->enc_ctx, out, outlen) != 1) { + error_print(); + return -1; + } + sm3_hmac_update(&ctx->mac_ctx, out, *outlen); + sm3_hmac_finish(&ctx->mac_ctx, out + *outlen); + *outlen += SM3_HMAC_SIZE; + return 1; +} + +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 *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(); + return -1; + } + sm3_hmac_init(&ctx->mac_ctx, key + SM4_KEY_SIZE, SM3_HMAC_SIZE); + if (aad && aadlen) { + sm3_hmac_update(&ctx->mac_ctx, aad, aadlen); + } + return 1; +} + +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) +{ + size_t len; + + if (!ctx || !in || !out || !outlen) { + error_print(); + return -1; + } + if (ctx->maclen > SM3_HMAC_SIZE) { + error_print(); + return -1; + } + + if (ctx->maclen < SM3_HMAC_SIZE) { + len = SM3_HMAC_SIZE - ctx->maclen; + if (inlen <= len) { + memcpy(ctx->mac + ctx->maclen, in, inlen); + ctx->maclen += inlen; + return 1; + } else { + memcpy(ctx->mac + ctx->maclen, in, len); + ctx->maclen += len; + in += len; + inlen -= len; + } + } + + if (inlen <= SM3_HMAC_SIZE) { + uint8_t tmp[SM3_HMAC_SIZE]; + sm3_hmac_update(&ctx->mac_ctx, ctx->mac, inlen); + if (sm4_cbc_decrypt_update(&ctx->enc_ctx, ctx->mac, inlen, out, outlen) != 1) { + error_print(); + return -1; + } + len = SM3_HMAC_SIZE - inlen; + memcpy(tmp, ctx->mac + inlen, len); + memcpy(tmp + len, in, inlen); + memcpy(ctx->mac, tmp, SM3_HMAC_SIZE); + } else { + sm3_hmac_update(&ctx->mac_ctx, ctx->mac, SM3_HMAC_SIZE); + if (sm4_cbc_decrypt_update(&ctx->enc_ctx, ctx->mac, SM3_HMAC_SIZE, out, outlen) != 1) { + error_print(); + return -1; + } + out += *outlen; + + inlen -= SM3_HMAC_SIZE; + sm3_hmac_update(&ctx->mac_ctx, in, inlen); + if (sm4_cbc_decrypt_update(&ctx->enc_ctx, in, inlen, out, &len) != 1) { + error_print(); + return -1; + } + *outlen += len; + memcpy(ctx->mac, in + inlen, SM3_HMAC_SIZE); + } + return 1; +} + +int sm4_cbc_sm3_hmac_decrypt_finish(SM4_CBC_SM3_HMAC_CTX *ctx, uint8_t *out, size_t *outlen) +{ + uint8_t mac[SM3_HMAC_SIZE]; + + if (!ctx || !out || !outlen) { + error_print(); + return -1; + } + if (ctx->maclen != SM3_HMAC_SIZE) { + error_print(); + return -1; + } + sm3_hmac_finish(&ctx->mac_ctx, mac); + if (sm4_cbc_decrypt_finish(&ctx->enc_ctx, out, outlen) != 1) { + error_print(); + return -1; + } + if (memcmp(mac, ctx->mac, SM3_HMAC_SIZE) != 0) { + error_print(); + return -1; + } + memset(ctx->mac, 0, SM3_HMAC_SIZE); + ctx->maclen = 0; + return 1; +} diff --git a/src/sm4_ctr.c b/src/sm4_ctr.c new file mode 100644 index 00000000..1679481e --- /dev/null +++ b/src/sm4_ctr.c @@ -0,0 +1,104 @@ +/* + * 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 + + +static void ctr_incr(uint8_t a[16]) +{ + int i; + for (i = 15; i >= 0; i--) { + a[i]++; + if (a[i]) break; + } +} + +#ifndef ENABLE_SM4_AESNI_AVX +void sm4_ctr_encrypt(const SM4_KEY *key, uint8_t ctr[16], const uint8_t *in, size_t inlen, uint8_t *out) +{ + uint8_t block[16]; + size_t len; + + while (inlen) { + len = inlen < 16 ? inlen : 16; + sm4_encrypt(key, ctr, block); + gmssl_memxor(out, in, block, len); + ctr_incr(ctr); + in += len; + out += len; + inlen -= len; + } +} +#endif + +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) +{ + 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); + *outlen = ctx->block_nbytes; + return 1; +} diff --git a/src/sm4_ctr_sm3_hmac.c b/src/sm4_ctr_sm3_hmac.c new file mode 100644 index 00000000..f5211baf --- /dev/null +++ b/src/sm4_ctr_sm3_hmac.c @@ -0,0 +1,191 @@ +/* + * 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 + + + +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 *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(); + return -1; + } + sm3_hmac_init(&ctx->mac_ctx, key + SM4_KEY_SIZE, SM3_HMAC_SIZE); + if (aad && aadlen) { + sm3_hmac_update(&ctx->mac_ctx, aad, aadlen); + } + return 1; +} + +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) +{ + if (!ctx || !in || !out || !outlen) { + error_print(); + return -1; + } + if (sm4_ctr_encrypt_update(&ctx->enc_ctx, in, inlen, out, outlen) != 1) { + error_print(); + return -1; + } + sm3_hmac_update(&ctx->mac_ctx, out, *outlen); + return 1; +} + +int sm4_ctr_sm3_hmac_encrypt_finish(SM4_CTR_SM3_HMAC_CTX *ctx, uint8_t *out, size_t *outlen) +{ + if (!ctx || !out || !outlen) { + error_print(); + return -1; + } + if (sm4_ctr_encrypt_finish(&ctx->enc_ctx, out, outlen) != 1) { + error_print(); + return -1; + } + sm3_hmac_update(&ctx->mac_ctx, out, *outlen); + sm3_hmac_finish(&ctx->mac_ctx, out + *outlen); + *outlen += SM3_HMAC_SIZE; + return 1; +} + +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 *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_decrypt_init(&ctx->enc_ctx, key, iv) != 1) { + error_print(); + return -1; + } + sm3_hmac_init(&ctx->mac_ctx, key + SM4_KEY_SIZE, SM3_HMAC_SIZE); + if (aad && aadlen) { + sm3_hmac_update(&ctx->mac_ctx, aad, aadlen); + } + return 1; +} + +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) +{ + size_t len; + + if (!ctx || !in || !out || !outlen) { + error_print(); + return -1; + } + if (ctx->maclen > SM3_HMAC_SIZE) { + error_print(); + return -1; + } + + if (ctx->maclen < SM3_HMAC_SIZE) { + len = SM3_HMAC_SIZE - ctx->maclen; + if (inlen <= len) { + memcpy(ctx->mac + ctx->maclen, in, inlen); + ctx->maclen += inlen; + return 1; + } else { + memcpy(ctx->mac + ctx->maclen, in, len); + ctx->maclen += len; + in += len; + inlen -= len; + } + } + + if (inlen <= SM3_HMAC_SIZE) { + uint8_t tmp[SM3_HMAC_SIZE]; + sm3_hmac_update(&ctx->mac_ctx, ctx->mac, inlen); + if (sm4_ctr_decrypt_update(&ctx->enc_ctx, ctx->mac, inlen, out, outlen) != 1) { + error_print(); + return -1; + } + len = SM3_HMAC_SIZE - inlen; + memcpy(tmp, ctx->mac + inlen, len); + memcpy(tmp + len, in, inlen); + memcpy(ctx->mac, tmp, SM3_HMAC_SIZE); + } else { + sm3_hmac_update(&ctx->mac_ctx, ctx->mac, SM3_HMAC_SIZE); + if (sm4_ctr_decrypt_update(&ctx->enc_ctx, ctx->mac, SM3_HMAC_SIZE, out, outlen) != 1) { + error_print(); + return -1; + } + out += *outlen; + + inlen -= SM3_HMAC_SIZE; + sm3_hmac_update(&ctx->mac_ctx, in, inlen); + if (sm4_ctr_decrypt_update(&ctx->enc_ctx, in, inlen, out, &len) != 1) { + error_print(); + return -1; + } + *outlen += len; + memcpy(ctx->mac, in + inlen, SM3_HMAC_SIZE); + } + return 1; +} + +int sm4_ctr_sm3_hmac_decrypt_finish(SM4_CTR_SM3_HMAC_CTX *ctx, uint8_t *out, size_t *outlen) +{ + uint8_t mac[SM3_HMAC_SIZE]; + + if (!ctx || !out || !outlen) { + error_print(); + return -1; + } + if (ctx->maclen != SM3_HMAC_SIZE) { + error_print(); + return -1; + } + sm3_hmac_finish(&ctx->mac_ctx, mac); + if (sm4_ctr_decrypt_finish(&ctx->enc_ctx, out, outlen) != 1) { + error_print(); + return -1; + } + if (memcmp(mac, ctx->mac, SM3_HMAC_SIZE) != 0) { + error_print(); + return -1; + } + memset(ctx->mac, 0, SM3_HMAC_SIZE); + ctx->maclen = 0; + return 1; +} + +static void ctr_incr(uint8_t a[16]) +{ + int i; + for (i = 15; i >= 0; i--) { + a[i]++; + if (a[i]) break; + } +} + diff --git a/src/sm4_gcm.c b/src/sm4_gcm.c new file mode 100644 index 00000000..780794a7 --- /dev/null +++ b/src/sm4_gcm.c @@ -0,0 +1,294 @@ +/* + * 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 + + +static void ctr_incr(uint8_t a[16]) +{ + int i; + for (i = 15; i >= 0; i--) { + a[i]++; + if (a[i]) break; + } +} + +int sm4_gcm_encrypt(const SM4_KEY *key, const uint8_t *iv, size_t ivlen, + const uint8_t *aad, size_t aadlen, const uint8_t *in, size_t inlen, + uint8_t *out, size_t taglen, uint8_t *tag) +{ + const uint8_t *pin = in; + uint8_t *pout = out; + size_t left = inlen; + uint8_t H[16] = {0}; + uint8_t Y[16]; + uint8_t T[16]; + + if (taglen > SM4_GCM_MAX_TAG_SIZE) { + error_print(); + return -1; + } + + sm4_encrypt(key, H, H); + + if (ivlen == 12) { + memcpy(Y, iv, 12); + Y[12] = Y[13] = Y[14] = 0; + Y[15] = 1; + } else { + ghash(H, NULL, 0, iv, ivlen, Y); + } + + sm4_encrypt(key, Y, T); + + while (left) { + uint8_t block[16]; + size_t len = left < 16 ? left : 16; + ctr_incr(Y); + sm4_encrypt(key, Y, block); + gmssl_memxor(pout, pin, block, len); + pin += len; + pout += len; + left -= len; + } + + ghash(H, aad, aadlen, out, inlen, H); + gmssl_memxor(tag, T, H, taglen); + return 1; +} + +int sm4_gcm_decrypt(const SM4_KEY *key, const uint8_t *iv, size_t ivlen, + const uint8_t *aad, size_t aadlen, const uint8_t *in, size_t inlen, + const uint8_t *tag, size_t taglen, uint8_t *out) +{ + const uint8_t *pin = in; + uint8_t *pout = out; + size_t left = inlen; + uint8_t H[16] = {0}; + uint8_t Y[16]; + uint8_t T[16]; + + sm4_encrypt(key, H, H); + + if (ivlen == 12) { + memcpy(Y, iv, 12); + Y[12] = Y[13] = Y[14] = 0; + Y[15] = 1; + } else { + ghash(H, NULL, 0, iv, ivlen, Y); + } + + ghash(H, aad, aadlen, in, inlen, H); + sm4_encrypt(key, Y, T); + gmssl_memxor(T, T, H, taglen); + if (memcmp(T, tag, taglen) != 0) { + error_print(); + return -1; + } + + while (left) { + uint8_t block[16]; + size_t len = left < 16 ? left : 16; + ctr_incr(Y); + sm4_encrypt(key, Y, block); + gmssl_memxor(pout, pin, block, len); + pin += len; + pout += len; + left -= len; + } + return 1; +} + +int sm4_gcm_encrypt_init(SM4_GCM_CTX *ctx, + const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, + const uint8_t *aad, size_t aadlen, size_t taglen) +{ + uint8_t H[16] = {0}; + uint8_t Y[16]; + + if (!ctx || !key || !iv || (!aad && aadlen)) { + error_print(); + return -1; + } + if (keylen != 16) { + error_print(); + return -1; + } + if (ivlen < SM4_GCM_MIN_IV_SIZE || ivlen > SM4_GCM_MAX_IV_SIZE) { + error_print(); + return -1; + } + if (taglen < 8 || taglen > 16) { + error_print(); + return -1; + } + + memset(ctx, 0, sizeof(*ctx)); + ctx->taglen = taglen; + + if (sm4_ctr_encrypt_init(&ctx->enc_ctx, key, H) != 1) { + error_print(); + return -1; + } + + sm4_encrypt(&ctx->enc_ctx.sm4_key, H, H); + + ghash_init(&ctx->mac_ctx, H, aad, aadlen); + + if (ivlen == 12) { + memcpy(Y, iv, 12); + Y[12] = Y[13] = Y[14] = 0; + Y[15] = 1; + } else { + ghash(H, NULL, 0, iv, ivlen, Y); + } + + sm4_encrypt(&ctx->enc_ctx.sm4_key, Y, ctx->Y); + + ctr_incr(Y); + memcpy(ctx->enc_ctx.ctr, Y, 16); + + gmssl_secure_clear(H, sizeof(H)); + gmssl_secure_clear(Y, sizeof(Y)); + return 1; +} + +int sm4_gcm_encrypt_update(SM4_GCM_CTX *ctx, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) +{ + if (!ctx || !in || !out || !outlen) { + error_print(); + return -1; + } + if (sm4_ctr_encrypt_update(&ctx->enc_ctx, in, inlen, out, outlen) != 1) { + error_print(); + return -1; + } + ghash_update(&ctx->mac_ctx, out, *outlen); + return 1; +} + +int sm4_gcm_encrypt_finish(SM4_GCM_CTX *ctx, uint8_t *out, size_t *outlen) +{ + uint8_t mac[16]; + + if (!ctx || !out || !outlen) { + error_print(); + return -1; + } + if (sm4_ctr_encrypt_finish(&ctx->enc_ctx, out, outlen) != 1) { + error_print(); + return -1; + } + ghash_update(&ctx->mac_ctx, out, *outlen); + ghash_finish(&ctx->mac_ctx, mac); + + gmssl_memxor(mac, mac, ctx->Y, ctx->taglen); + memcpy(out + *outlen, mac, ctx->taglen); + *outlen += ctx->taglen; + + return 1; +} + +int sm4_gcm_decrypt_init(SM4_GCM_CTX *ctx, + const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, + const uint8_t *aad, size_t aadlen, size_t taglen) +{ + return sm4_gcm_encrypt_init(ctx, key, keylen, iv, ivlen, aad, aadlen, taglen); +} + +int sm4_gcm_decrypt_update(SM4_GCM_CTX *ctx, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) +{ + size_t len; + + if (!ctx || !in || !out || !outlen) { + error_print(); + return -1; + } + if (ctx->maclen > ctx->taglen) { + error_print(); + return -1; + } + + if (ctx->maclen < ctx->taglen) { + len = ctx->taglen - ctx->maclen; + if (inlen <= len) { + memcpy(ctx->mac + ctx->maclen, in, inlen); + ctx->maclen += inlen; + return 1; + } else { + memcpy(ctx->mac + ctx->maclen, in, len); + ctx->maclen += len; + in += len; + inlen -= len; + } + } + + if (inlen <= ctx->taglen) { + uint8_t tmp[GHASH_SIZE]; + ghash_update(&ctx->mac_ctx, ctx->mac, inlen); + if (sm4_ctr_decrypt_update(&ctx->enc_ctx, ctx->mac, inlen, out, outlen) != 1) { + error_print(); + return -1; + } + len = ctx->taglen - inlen; + memcpy(tmp, ctx->mac + inlen, len); + memcpy(tmp + len, in, inlen); + memcpy(ctx->mac, tmp, GHASH_SIZE); + } else { + ghash_update(&ctx->mac_ctx, ctx->mac, ctx->taglen); + if (sm4_ctr_decrypt_update(&ctx->enc_ctx, ctx->mac, ctx->taglen, out, outlen) != 1) { + error_print(); + return -1; + } + out += *outlen; + + inlen -= ctx->taglen; + ghash_update(&ctx->mac_ctx, in, inlen); + if (sm4_ctr_decrypt_update(&ctx->enc_ctx, in, inlen, out, &len) != 1) { + error_print(); + return -1; + } + *outlen += len; + memcpy(ctx->mac, in + inlen, GHASH_SIZE); + } + return 1; +} + +int sm4_gcm_decrypt_finish(SM4_GCM_CTX *ctx, uint8_t *out, size_t *outlen) +{ + uint8_t mac[GHASH_SIZE]; + + if (!ctx || !out || !outlen) { + error_print(); + return -1; + } + if (ctx->maclen != ctx->taglen) { + error_print(); + return -1; + } + ghash_finish(&ctx->mac_ctx, mac); + if (sm4_ctr_decrypt_finish(&ctx->enc_ctx, out, outlen) != 1) { + error_print(); + return -1; + } + + gmssl_memxor(mac, mac, ctx->Y, ctx->taglen); + if (memcmp(mac, ctx->mac, ctx->taglen) != 0) { + error_print(); + return -1; + } + memset(ctx->mac, 0, GHASH_SIZE); + ctx->maclen = 0; + return 1; +} +