1 /* $OpenBSD: e_sm4.c,v 1.12 2024/01/04 17:38:36 tb Exp $ */ 2 /* 3 * Copyright (c) 2017, 2019 Ribose Inc 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <openssl/opensslconf.h> 19 20 #ifndef OPENSSL_NO_SM4 21 #include <openssl/evp.h> 22 #include <openssl/modes.h> 23 #include <openssl/sm4.h> 24 25 #include "evp_local.h" 26 27 typedef struct { 28 SM4_KEY ks; 29 } EVP_SM4_KEY; 30 31 static int 32 sm4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, 33 const unsigned char *iv, int enc) 34 { 35 SM4_set_key(key, ctx->cipher_data); 36 return 1; 37 } 38 39 static void 40 sm4_cbc_encrypt(const unsigned char *in, unsigned char *out, size_t len, 41 const SM4_KEY *key, unsigned char *ivec, const int enc) 42 { 43 if (enc) 44 CRYPTO_cbc128_encrypt(in, out, len, key, ivec, 45 (block128_f)SM4_encrypt); 46 else 47 CRYPTO_cbc128_decrypt(in, out, len, key, ivec, 48 (block128_f)SM4_decrypt); 49 } 50 51 static void 52 sm4_cfb128_encrypt(const unsigned char *in, unsigned char *out, size_t length, 53 const SM4_KEY *key, unsigned char *ivec, int *num, const int enc) 54 { 55 CRYPTO_cfb128_encrypt(in, out, length, key, ivec, num, enc, 56 (block128_f)SM4_encrypt); 57 } 58 59 static void 60 sm4_ecb_encrypt(const unsigned char *in, unsigned char *out, const SM4_KEY *key, 61 const int enc) 62 { 63 if (enc) 64 SM4_encrypt(in, out, key); 65 else 66 SM4_decrypt(in, out, key); 67 } 68 69 static void 70 sm4_ofb128_encrypt(const unsigned char *in, unsigned char *out, size_t length, 71 const SM4_KEY *key, unsigned char *ivec, int *num) 72 { 73 CRYPTO_ofb128_encrypt(in, out, length, key, ivec, num, 74 (block128_f)SM4_encrypt); 75 } 76 77 static int 78 sm4_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) 79 { 80 while (inl >= EVP_MAXCHUNK) { 81 sm4_cbc_encrypt(in, out, EVP_MAXCHUNK, &((EVP_SM4_KEY *)ctx->cipher_data)->ks, ctx->iv, ctx->encrypt); 82 inl -= EVP_MAXCHUNK; 83 in += EVP_MAXCHUNK; 84 out += EVP_MAXCHUNK; 85 } 86 87 if (inl) 88 sm4_cbc_encrypt(in, out, inl, &((EVP_SM4_KEY *)ctx->cipher_data)->ks, ctx->iv, ctx->encrypt); 89 90 return 1; 91 } 92 93 static int 94 sm4_cfb128_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) 95 { 96 size_t chunk = EVP_MAXCHUNK; 97 98 if (inl < chunk) 99 chunk = inl; 100 101 while (inl && inl >= chunk) { 102 sm4_cfb128_encrypt(in, out, chunk, &((EVP_SM4_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num, ctx->encrypt); 103 inl -= chunk; 104 in += chunk; 105 out += chunk; 106 if (inl < chunk) 107 chunk = inl; 108 } 109 110 return 1; 111 } 112 113 static int 114 sm4_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) 115 { 116 size_t i, bl; 117 118 bl = ctx->cipher->block_size; 119 120 if (inl < bl) 121 return 1; 122 123 inl -= bl; 124 125 for (i = 0; i <= inl; i += bl) 126 sm4_ecb_encrypt(in + i, out + i, &((EVP_SM4_KEY *)ctx->cipher_data)->ks, ctx->encrypt); 127 128 return 1; 129 } 130 131 static int 132 sm4_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) 133 { 134 while (inl >= EVP_MAXCHUNK) { 135 sm4_ofb128_encrypt(in, out, EVP_MAXCHUNK, &((EVP_SM4_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num); 136 inl -= EVP_MAXCHUNK; 137 in += EVP_MAXCHUNK; 138 out += EVP_MAXCHUNK; 139 } 140 141 if (inl) 142 sm4_ofb128_encrypt(in, out, inl, &((EVP_SM4_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num); 143 144 return 1; 145 } 146 147 static const EVP_CIPHER sm4_cbc = { 148 .nid = NID_sm4_cbc, 149 .block_size = 16, 150 .key_len = 16, 151 .iv_len = 16, 152 .flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_CBC_MODE, 153 .init = sm4_init_key, 154 .do_cipher = sm4_cbc_cipher, 155 .cleanup = NULL, 156 .ctx_size = sizeof(EVP_SM4_KEY), 157 .set_asn1_parameters = NULL, 158 .get_asn1_parameters = NULL, 159 .ctrl = NULL, 160 }; 161 162 const EVP_CIPHER * 163 EVP_sm4_cbc(void) 164 { 165 return &sm4_cbc; 166 } 167 168 static const EVP_CIPHER sm4_cfb128 = { 169 .nid = NID_sm4_cfb128, 170 .block_size = 1, 171 .key_len = 16, 172 .iv_len = 16, 173 .flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_CFB_MODE, 174 .init = sm4_init_key, 175 .do_cipher = sm4_cfb128_cipher, 176 .cleanup = NULL, 177 .ctx_size = sizeof(EVP_SM4_KEY), 178 .set_asn1_parameters = NULL, 179 .get_asn1_parameters = NULL, 180 .ctrl = NULL, 181 }; 182 183 const EVP_CIPHER * 184 EVP_sm4_cfb128(void) 185 { 186 return &sm4_cfb128; 187 } 188 189 static const EVP_CIPHER sm4_ofb = { 190 .nid = NID_sm4_ofb128, 191 .block_size = 1, 192 .key_len = 16, 193 .iv_len = 16, 194 .flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_OFB_MODE, 195 .init = sm4_init_key, 196 .do_cipher = sm4_ofb_cipher, 197 .cleanup = NULL, 198 .ctx_size = sizeof(EVP_SM4_KEY), 199 .set_asn1_parameters = NULL, 200 .get_asn1_parameters = NULL, 201 .ctrl = NULL, 202 }; 203 204 const EVP_CIPHER * 205 EVP_sm4_ofb(void) 206 { 207 return &sm4_ofb; 208 } 209 210 static const EVP_CIPHER sm4_ecb = { 211 .nid = NID_sm4_ecb, 212 .block_size = 16, 213 .key_len = 16, 214 .iv_len = 0, 215 .flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_ECB_MODE, 216 .init = sm4_init_key, 217 .do_cipher = sm4_ecb_cipher, 218 .cleanup = NULL, 219 .ctx_size = sizeof(EVP_SM4_KEY), 220 .set_asn1_parameters = NULL, 221 .get_asn1_parameters = NULL, 222 .ctrl = NULL, 223 }; 224 225 const EVP_CIPHER * 226 EVP_sm4_ecb(void) 227 { 228 return &sm4_ecb; 229 } 230 231 static int 232 sm4_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, 233 size_t len) 234 { 235 EVP_SM4_KEY *key = ((EVP_SM4_KEY *)(ctx)->cipher_data); 236 237 CRYPTO_ctr128_encrypt(in, out, len, &key->ks, ctx->iv, ctx->buf, 238 &ctx->num, (block128_f)SM4_encrypt); 239 return 1; 240 } 241 242 static const EVP_CIPHER sm4_ctr_mode = { 243 .nid = NID_sm4_ctr, 244 .block_size = 1, 245 .key_len = 16, 246 .iv_len = 16, 247 .flags = EVP_CIPH_CTR_MODE, 248 .init = sm4_init_key, 249 .do_cipher = sm4_ctr_cipher, 250 .cleanup = NULL, 251 .ctx_size = sizeof(EVP_SM4_KEY), 252 .set_asn1_parameters = NULL, 253 .get_asn1_parameters = NULL, 254 .ctrl = NULL, 255 }; 256 257 const EVP_CIPHER * 258 EVP_sm4_ctr(void) 259 { 260 return &sm4_ctr_mode; 261 } 262 #endif 263