1*9bac3682Sbeck /* $OpenBSD: e_sm4.c,v 1.13 2024/04/09 13:52:41 beck Exp $ */
285824259Stb /*
385824259Stb * Copyright (c) 2017, 2019 Ribose Inc
485824259Stb *
585824259Stb * Permission to use, copy, modify, and/or distribute this software for any
685824259Stb * purpose with or without fee is hereby granted, provided that the above
785824259Stb * copyright notice and this permission notice appear in all copies.
885824259Stb *
985824259Stb * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1085824259Stb * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1185824259Stb * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1285824259Stb * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1385824259Stb * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1485824259Stb * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1585824259Stb * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1685824259Stb */
1785824259Stb
1885824259Stb #include <openssl/opensslconf.h>
1985824259Stb
2085824259Stb #ifndef OPENSSL_NO_SM4
2185824259Stb #include <openssl/evp.h>
2285824259Stb #include <openssl/modes.h>
2385824259Stb #include <openssl/sm4.h>
2485824259Stb
25c9675a23Stb #include "evp_local.h"
2685824259Stb
2785824259Stb typedef struct {
2885824259Stb SM4_KEY ks;
2985824259Stb } EVP_SM4_KEY;
3085824259Stb
3185824259Stb static int
sm4_init_key(EVP_CIPHER_CTX * ctx,const unsigned char * key,const unsigned char * iv,int enc)3285824259Stb sm4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
3385824259Stb const unsigned char *iv, int enc)
3485824259Stb {
3585824259Stb SM4_set_key(key, ctx->cipher_data);
3685824259Stb return 1;
3785824259Stb }
3885824259Stb
3985824259Stb static void
sm4_cbc_encrypt(const unsigned char * in,unsigned char * out,size_t len,const SM4_KEY * key,unsigned char * ivec,const int enc)4085824259Stb sm4_cbc_encrypt(const unsigned char *in, unsigned char *out, size_t len,
4185824259Stb const SM4_KEY *key, unsigned char *ivec, const int enc)
4285824259Stb {
4385824259Stb if (enc)
4485824259Stb CRYPTO_cbc128_encrypt(in, out, len, key, ivec,
4585824259Stb (block128_f)SM4_encrypt);
4685824259Stb else
4785824259Stb CRYPTO_cbc128_decrypt(in, out, len, key, ivec,
4885824259Stb (block128_f)SM4_decrypt);
4985824259Stb }
5085824259Stb
5185824259Stb static void
sm4_cfb128_encrypt(const unsigned char * in,unsigned char * out,size_t length,const SM4_KEY * key,unsigned char * ivec,int * num,const int enc)5285824259Stb sm4_cfb128_encrypt(const unsigned char *in, unsigned char *out, size_t length,
5385824259Stb const SM4_KEY *key, unsigned char *ivec, int *num, const int enc)
5485824259Stb {
5585824259Stb CRYPTO_cfb128_encrypt(in, out, length, key, ivec, num, enc,
5685824259Stb (block128_f)SM4_encrypt);
5785824259Stb }
5885824259Stb
5985824259Stb static void
sm4_ecb_encrypt(const unsigned char * in,unsigned char * out,const SM4_KEY * key,const int enc)6085824259Stb sm4_ecb_encrypt(const unsigned char *in, unsigned char *out, const SM4_KEY *key,
6185824259Stb const int enc)
6285824259Stb {
6385824259Stb if (enc)
6485824259Stb SM4_encrypt(in, out, key);
6585824259Stb else
6685824259Stb SM4_decrypt(in, out, key);
6785824259Stb }
6885824259Stb
6985824259Stb static void
sm4_ofb128_encrypt(const unsigned char * in,unsigned char * out,size_t length,const SM4_KEY * key,unsigned char * ivec,int * num)7085824259Stb sm4_ofb128_encrypt(const unsigned char *in, unsigned char *out, size_t length,
7185824259Stb const SM4_KEY *key, unsigned char *ivec, int *num)
7285824259Stb {
7385824259Stb CRYPTO_ofb128_encrypt(in, out, length, key, ivec, num,
7485824259Stb (block128_f)SM4_encrypt);
7585824259Stb }
7685824259Stb
778dc670f6Sjsing static int
sm4_cbc_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t inl)788dc670f6Sjsing sm4_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
798dc670f6Sjsing {
808dc670f6Sjsing while (inl >= EVP_MAXCHUNK) {
81d5650aa3Sjsing sm4_cbc_encrypt(in, out, EVP_MAXCHUNK, &((EVP_SM4_KEY *)ctx->cipher_data)->ks, ctx->iv, ctx->encrypt);
828dc670f6Sjsing inl -= EVP_MAXCHUNK;
838dc670f6Sjsing in += EVP_MAXCHUNK;
848dc670f6Sjsing out += EVP_MAXCHUNK;
858dc670f6Sjsing }
868dc670f6Sjsing
878dc670f6Sjsing if (inl)
88d5650aa3Sjsing sm4_cbc_encrypt(in, out, inl, &((EVP_SM4_KEY *)ctx->cipher_data)->ks, ctx->iv, ctx->encrypt);
898dc670f6Sjsing
908dc670f6Sjsing return 1;
918dc670f6Sjsing }
928dc670f6Sjsing
938dc670f6Sjsing static int
sm4_cfb128_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t inl)948dc670f6Sjsing sm4_cfb128_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
958dc670f6Sjsing {
968dc670f6Sjsing size_t chunk = EVP_MAXCHUNK;
978dc670f6Sjsing
988dc670f6Sjsing if (inl < chunk)
998dc670f6Sjsing chunk = inl;
1008dc670f6Sjsing
1018dc670f6Sjsing while (inl && inl >= chunk) {
1027a606269Sjsing sm4_cfb128_encrypt(in, out, chunk, &((EVP_SM4_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num, ctx->encrypt);
1038dc670f6Sjsing inl -= chunk;
1048dc670f6Sjsing in += chunk;
1058dc670f6Sjsing out += chunk;
1068dc670f6Sjsing if (inl < chunk)
1078dc670f6Sjsing chunk = inl;
1088dc670f6Sjsing }
1098dc670f6Sjsing
1108dc670f6Sjsing return 1;
1118dc670f6Sjsing }
1128dc670f6Sjsing
1138dc670f6Sjsing static int
sm4_ecb_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t inl)1148dc670f6Sjsing sm4_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
1158dc670f6Sjsing {
1168dc670f6Sjsing size_t i, bl;
1178dc670f6Sjsing
1188dc670f6Sjsing bl = ctx->cipher->block_size;
1198dc670f6Sjsing
1208dc670f6Sjsing if (inl < bl)
1218dc670f6Sjsing return 1;
1228dc670f6Sjsing
1238dc670f6Sjsing inl -= bl;
1248dc670f6Sjsing
1258dc670f6Sjsing for (i = 0; i <= inl; i += bl)
1268dc670f6Sjsing sm4_ecb_encrypt(in + i, out + i, &((EVP_SM4_KEY *)ctx->cipher_data)->ks, ctx->encrypt);
1278dc670f6Sjsing
1288dc670f6Sjsing return 1;
1298dc670f6Sjsing }
1308dc670f6Sjsing
1318dc670f6Sjsing static int
sm4_ofb_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t inl)1328dc670f6Sjsing sm4_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
1338dc670f6Sjsing {
1348dc670f6Sjsing while (inl >= EVP_MAXCHUNK) {
135d5650aa3Sjsing sm4_ofb128_encrypt(in, out, EVP_MAXCHUNK, &((EVP_SM4_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num);
1368dc670f6Sjsing inl -= EVP_MAXCHUNK;
1378dc670f6Sjsing in += EVP_MAXCHUNK;
1388dc670f6Sjsing out += EVP_MAXCHUNK;
1398dc670f6Sjsing }
1408dc670f6Sjsing
1418dc670f6Sjsing if (inl)
142d5650aa3Sjsing sm4_ofb128_encrypt(in, out, inl, &((EVP_SM4_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num);
1438dc670f6Sjsing
1448dc670f6Sjsing return 1;
1458dc670f6Sjsing }
1468dc670f6Sjsing
1478dc670f6Sjsing static const EVP_CIPHER sm4_cbc = {
1488dc670f6Sjsing .nid = NID_sm4_cbc,
1498dc670f6Sjsing .block_size = 16,
1508dc670f6Sjsing .key_len = 16,
1518dc670f6Sjsing .iv_len = 16,
1528dc670f6Sjsing .flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_CBC_MODE,
1538dc670f6Sjsing .init = sm4_init_key,
1548dc670f6Sjsing .do_cipher = sm4_cbc_cipher,
1558dc670f6Sjsing .cleanup = NULL,
1568dc670f6Sjsing .ctx_size = sizeof(EVP_SM4_KEY),
157040dcbc5Stb .set_asn1_parameters = NULL,
158040dcbc5Stb .get_asn1_parameters = NULL,
159040dcbc5Stb .ctrl = NULL,
1608dc670f6Sjsing };
1618dc670f6Sjsing
1628dc670f6Sjsing const EVP_CIPHER *
EVP_sm4_cbc(void)1638dc670f6Sjsing EVP_sm4_cbc(void)
1648dc670f6Sjsing {
1658dc670f6Sjsing return &sm4_cbc;
1668dc670f6Sjsing }
167*9bac3682Sbeck LCRYPTO_ALIAS(EVP_sm4_cbc);
1688dc670f6Sjsing
1698dc670f6Sjsing static const EVP_CIPHER sm4_cfb128 = {
1708dc670f6Sjsing .nid = NID_sm4_cfb128,
1718dc670f6Sjsing .block_size = 1,
1728dc670f6Sjsing .key_len = 16,
1738dc670f6Sjsing .iv_len = 16,
1748dc670f6Sjsing .flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_CFB_MODE,
1758dc670f6Sjsing .init = sm4_init_key,
1768dc670f6Sjsing .do_cipher = sm4_cfb128_cipher,
1778dc670f6Sjsing .cleanup = NULL,
1788dc670f6Sjsing .ctx_size = sizeof(EVP_SM4_KEY),
179040dcbc5Stb .set_asn1_parameters = NULL,
180040dcbc5Stb .get_asn1_parameters = NULL,
181040dcbc5Stb .ctrl = NULL,
1828dc670f6Sjsing };
1838dc670f6Sjsing
1848dc670f6Sjsing const EVP_CIPHER *
EVP_sm4_cfb128(void)1858dc670f6Sjsing EVP_sm4_cfb128(void)
1868dc670f6Sjsing {
1878dc670f6Sjsing return &sm4_cfb128;
1888dc670f6Sjsing }
189*9bac3682Sbeck LCRYPTO_ALIAS(EVP_sm4_cfb128);
1908dc670f6Sjsing
1918dc670f6Sjsing static const EVP_CIPHER sm4_ofb = {
1928dc670f6Sjsing .nid = NID_sm4_ofb128,
1938dc670f6Sjsing .block_size = 1,
1948dc670f6Sjsing .key_len = 16,
1958dc670f6Sjsing .iv_len = 16,
1968dc670f6Sjsing .flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_OFB_MODE,
1978dc670f6Sjsing .init = sm4_init_key,
1988dc670f6Sjsing .do_cipher = sm4_ofb_cipher,
1998dc670f6Sjsing .cleanup = NULL,
2008dc670f6Sjsing .ctx_size = sizeof(EVP_SM4_KEY),
201040dcbc5Stb .set_asn1_parameters = NULL,
202040dcbc5Stb .get_asn1_parameters = NULL,
203040dcbc5Stb .ctrl = NULL,
2048dc670f6Sjsing };
2058dc670f6Sjsing
2068dc670f6Sjsing const EVP_CIPHER *
EVP_sm4_ofb(void)2078dc670f6Sjsing EVP_sm4_ofb(void)
2088dc670f6Sjsing {
2098dc670f6Sjsing return &sm4_ofb;
2108dc670f6Sjsing }
211*9bac3682Sbeck LCRYPTO_ALIAS(EVP_sm4_ofb);
2128dc670f6Sjsing
2138dc670f6Sjsing static const EVP_CIPHER sm4_ecb = {
2148dc670f6Sjsing .nid = NID_sm4_ecb,
2158dc670f6Sjsing .block_size = 16,
2168dc670f6Sjsing .key_len = 16,
2178dc670f6Sjsing .iv_len = 0,
2188dc670f6Sjsing .flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_ECB_MODE,
2198dc670f6Sjsing .init = sm4_init_key,
2208dc670f6Sjsing .do_cipher = sm4_ecb_cipher,
2218dc670f6Sjsing .cleanup = NULL,
2228dc670f6Sjsing .ctx_size = sizeof(EVP_SM4_KEY),
22363177169Stb .set_asn1_parameters = NULL,
22463177169Stb .get_asn1_parameters = NULL,
22563177169Stb .ctrl = NULL,
2268dc670f6Sjsing };
2278dc670f6Sjsing
2288dc670f6Sjsing const EVP_CIPHER *
EVP_sm4_ecb(void)2298dc670f6Sjsing EVP_sm4_ecb(void)
2308dc670f6Sjsing {
2318dc670f6Sjsing return &sm4_ecb;
2328dc670f6Sjsing }
233*9bac3682Sbeck LCRYPTO_ALIAS(EVP_sm4_ecb);
23485824259Stb
23585824259Stb static int
sm4_ctr_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t len)23685824259Stb sm4_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in,
23785824259Stb size_t len)
23885824259Stb {
2398dc670f6Sjsing EVP_SM4_KEY *key = ((EVP_SM4_KEY *)(ctx)->cipher_data);
24085824259Stb
24185824259Stb CRYPTO_ctr128_encrypt(in, out, len, &key->ks, ctx->iv, ctx->buf,
24285824259Stb &ctx->num, (block128_f)SM4_encrypt);
24385824259Stb return 1;
24485824259Stb }
24585824259Stb
24685824259Stb static const EVP_CIPHER sm4_ctr_mode = {
24785824259Stb .nid = NID_sm4_ctr,
24885824259Stb .block_size = 1,
24985824259Stb .key_len = 16,
25085824259Stb .iv_len = 16,
25185824259Stb .flags = EVP_CIPH_CTR_MODE,
25285824259Stb .init = sm4_init_key,
25385824259Stb .do_cipher = sm4_ctr_cipher,
25485824259Stb .cleanup = NULL,
25585824259Stb .ctx_size = sizeof(EVP_SM4_KEY),
25685824259Stb .set_asn1_parameters = NULL,
25785824259Stb .get_asn1_parameters = NULL,
25885824259Stb .ctrl = NULL,
25985824259Stb };
26085824259Stb
26185824259Stb const EVP_CIPHER *
EVP_sm4_ctr(void)26285824259Stb EVP_sm4_ctr(void)
26385824259Stb {
26485824259Stb return &sm4_ctr_mode;
26585824259Stb }
266*9bac3682Sbeck LCRYPTO_ALIAS(EVP_sm4_ctr);
26785824259Stb #endif
268