1 /* $OpenBSD: e_sm4.c,v 1.4 2022/09/04 15:56:51 jsing 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_locl.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, (long)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, (long)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, (long)inl, &((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, (long)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, (long)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 = 0, 158 .get_asn1_parameters = 0, 159 .ctrl = 0, 160 .app_data = NULL, 161 }; 162 163 const EVP_CIPHER * 164 EVP_sm4_cbc(void) 165 { 166 return &sm4_cbc; 167 } 168 169 static const EVP_CIPHER sm4_cfb128 = { 170 .nid = NID_sm4_cfb128, 171 .block_size = 1, 172 .key_len = 16, 173 .iv_len = 16, 174 .flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_CFB_MODE, 175 .init = sm4_init_key, 176 .do_cipher = sm4_cfb128_cipher, 177 .cleanup = NULL, 178 .ctx_size = sizeof(EVP_SM4_KEY), 179 .set_asn1_parameters = 0, 180 .get_asn1_parameters = 0, 181 .ctrl = 0, 182 .app_data = NULL, 183 }; 184 185 const EVP_CIPHER * 186 EVP_sm4_cfb128(void) 187 { 188 return &sm4_cfb128; 189 } 190 191 static const EVP_CIPHER sm4_ofb = { 192 .nid = NID_sm4_ofb128, 193 .block_size = 1, 194 .key_len = 16, 195 .iv_len = 16, 196 .flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_OFB_MODE, 197 .init = sm4_init_key, 198 .do_cipher = sm4_ofb_cipher, 199 .cleanup = NULL, 200 .ctx_size = sizeof(EVP_SM4_KEY), 201 .set_asn1_parameters = 0, 202 .get_asn1_parameters = 0, 203 .ctrl = 0, 204 .app_data = NULL, 205 }; 206 207 const EVP_CIPHER * 208 EVP_sm4_ofb(void) 209 { 210 return &sm4_ofb; 211 } 212 213 static const EVP_CIPHER sm4_ecb = { 214 .nid = NID_sm4_ecb, 215 .block_size = 16, 216 .key_len = 16, 217 .iv_len = 0, 218 .flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_ECB_MODE, 219 .init = sm4_init_key, 220 .do_cipher = sm4_ecb_cipher, 221 .cleanup = NULL, 222 .ctx_size = sizeof(EVP_SM4_KEY), 223 .set_asn1_parameters = 0, 224 .get_asn1_parameters = 0, 225 .ctrl = 0, 226 .app_data = NULL, 227 }; 228 229 const EVP_CIPHER * 230 EVP_sm4_ecb(void) 231 { 232 return &sm4_ecb; 233 } 234 235 static int 236 sm4_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, 237 size_t len) 238 { 239 EVP_SM4_KEY *key = ((EVP_SM4_KEY *)(ctx)->cipher_data); 240 241 CRYPTO_ctr128_encrypt(in, out, len, &key->ks, ctx->iv, ctx->buf, 242 &ctx->num, (block128_f)SM4_encrypt); 243 return 1; 244 } 245 246 static const EVP_CIPHER sm4_ctr_mode = { 247 .nid = NID_sm4_ctr, 248 .block_size = 1, 249 .key_len = 16, 250 .iv_len = 16, 251 .flags = EVP_CIPH_CTR_MODE, 252 .init = sm4_init_key, 253 .do_cipher = sm4_ctr_cipher, 254 .cleanup = NULL, 255 .ctx_size = sizeof(EVP_SM4_KEY), 256 .set_asn1_parameters = NULL, 257 .get_asn1_parameters = NULL, 258 .ctrl = NULL, 259 .app_data = NULL, 260 }; 261 262 const EVP_CIPHER * 263 EVP_sm4_ctr(void) 264 { 265 return &sm4_ctr_mode; 266 } 267 #endif 268