1 /* $OpenBSD: sm2_pmeth.c,v 1.1.1.1 2021/08/18 16:04:32 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 #ifndef OPENSSL_NO_SM2 19 20 #include <string.h> 21 22 #include <openssl/sm2.h> 23 #include <openssl/asn1t.h> 24 #include <openssl/x509.h> 25 #include <openssl/err.h> 26 #include <openssl/evp.h> 27 28 #include "evp_locl.h" 29 #include "sm2_locl.h" 30 31 /* SM2 pkey context structure */ 32 33 typedef struct { 34 /* key and paramgen group */ 35 EC_GROUP *gen_group; 36 /* message digest */ 37 const EVP_MD *md; 38 EVP_MD_CTX *md_ctx; 39 /* personalization string */ 40 uint8_t* uid; 41 size_t uid_len; 42 } SM2_PKEY_CTX; 43 44 static int 45 pkey_sm2_init(EVP_PKEY_CTX *ctx) 46 { 47 SM2_PKEY_CTX *dctx; 48 49 if ((dctx = calloc(1, sizeof(*dctx))) == NULL) { 50 SM2error(ERR_R_MALLOC_FAILURE); 51 return 0; 52 } 53 ctx->data = dctx; 54 return 1; 55 } 56 57 static void 58 pkey_sm2_cleanup(EVP_PKEY_CTX *ctx) 59 { 60 SM2_PKEY_CTX *dctx = ctx->data; 61 62 if (ctx == NULL || ctx->data == NULL) 63 return; 64 65 EC_GROUP_free(dctx->gen_group); 66 free(dctx->uid); 67 free(dctx); 68 ctx->data = NULL; 69 } 70 71 static int 72 pkey_sm2_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) 73 { 74 SM2_PKEY_CTX *dctx, *sctx; 75 76 if (!pkey_sm2_init(dst)) 77 return 0; 78 sctx = src->data; 79 dctx = dst->data; 80 if (sctx->gen_group) { 81 if ((dctx->gen_group = EC_GROUP_dup(sctx->gen_group)) == NULL) { 82 SM2error(ERR_R_MALLOC_FAILURE); 83 goto err; 84 } 85 } 86 87 if (sctx->uid != NULL) { 88 if ((dctx->uid = malloc(sctx->uid_len)) == NULL) { 89 SM2error(ERR_R_MALLOC_FAILURE); 90 goto err; 91 } 92 memcpy(dctx->uid, sctx->uid, sctx->uid_len); 93 dctx->uid_len = sctx->uid_len; 94 } 95 96 dctx->md = sctx->md; 97 98 if (!EVP_MD_CTX_copy(dctx->md_ctx, sctx->md_ctx)) 99 goto err; 100 101 return 1; 102 103 err: 104 pkey_sm2_cleanup(dst); 105 return 0; 106 } 107 108 static int 109 pkey_sm2_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, 110 const unsigned char *tbs, size_t tbslen) 111 { 112 unsigned int sltmp; 113 int ret, sig_sz; 114 115 if ((sig_sz = ECDSA_size(ctx->pkey->pkey.ec)) <= 0) 116 return 0; 117 118 if (sig == NULL) { 119 *siglen = sig_sz; 120 return 1; 121 } 122 123 if (*siglen < (size_t)sig_sz) { 124 SM2error(SM2_R_BUFFER_TOO_SMALL); 125 return 0; 126 } 127 128 if ((ret = SM2_sign(tbs, tbslen, sig, &sltmp, ctx->pkey->pkey.ec)) <= 0) 129 return ret; 130 131 *siglen = (size_t)sltmp; 132 return 1; 133 } 134 135 static int 136 pkey_sm2_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig, size_t siglen, 137 const unsigned char *tbs, size_t tbslen) 138 { 139 return SM2_verify(tbs, tbslen, sig, siglen, ctx->pkey->pkey.ec); 140 } 141 142 static int 143 pkey_sm2_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, 144 const unsigned char *in, size_t inlen) 145 { 146 SM2_PKEY_CTX *dctx = ctx->data; 147 const EVP_MD *md = (dctx->md == NULL) ? EVP_sm3() : dctx->md; 148 149 if (out == NULL) { 150 if (!SM2_ciphertext_size(ctx->pkey->pkey.ec, md, inlen, outlen)) 151 return -1; 152 else 153 return 1; 154 } 155 156 return SM2_encrypt(ctx->pkey->pkey.ec, md, in, inlen, out, outlen); 157 } 158 159 static int 160 pkey_sm2_decrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, 161 const unsigned char *in, size_t inlen) 162 { 163 SM2_PKEY_CTX *dctx = ctx->data; 164 const EVP_MD *md = (dctx->md == NULL) ? EVP_sm3() : dctx->md; 165 166 if (out == NULL) { 167 if (!SM2_plaintext_size(ctx->pkey->pkey.ec, md, inlen, outlen)) 168 return -1; 169 else 170 return 1; 171 } 172 173 return SM2_decrypt(ctx->pkey->pkey.ec, md, in, inlen, out, outlen); 174 } 175 176 static int 177 pkey_sm2_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) 178 { 179 SM2_PKEY_CTX *dctx = ctx->data; 180 EC_GROUP *group = NULL; 181 182 switch (type) { 183 case EVP_PKEY_CTRL_DIGESTINIT: 184 dctx->md_ctx = p2; 185 return 1; 186 187 case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID: 188 if ((group = EC_GROUP_new_by_curve_name(p1)) == NULL) { 189 SM2error(SM2_R_INVALID_CURVE); 190 return 0; 191 } 192 EC_GROUP_free(dctx->gen_group); 193 dctx->gen_group = group; 194 return 1; 195 196 case EVP_PKEY_CTRL_SM2_SET_UID: 197 if ((p1 < 0) || ((p1 == 0) && (p2 != NULL))) { 198 SM2error(SM2_R_INVALID_ARGUMENT); 199 return 0; 200 } 201 if ((p1 > 0) && (p2 == NULL)) { 202 SM2error(ERR_R_PASSED_NULL_PARAMETER); 203 return 0; 204 } 205 free(dctx->uid); 206 if (p2 == NULL) { 207 dctx->uid = NULL; 208 dctx->uid_len = 0; 209 return 1; 210 } 211 212 if ((dctx->uid = malloc(p1)) == NULL) { 213 SM2error(ERR_R_MALLOC_FAILURE); 214 return 1; 215 } 216 memcpy(dctx->uid, p2, p1); 217 dctx->uid_len = p1; 218 return 1; 219 220 case EVP_PKEY_CTRL_SM2_HASH_UID: 221 { 222 const EVP_MD* md; 223 uint8_t za[EVP_MAX_MD_SIZE] = {0}; 224 int md_len; 225 226 if (dctx->uid == NULL) { 227 SM2error(SM2_R_INVALID_ARGUMENT); 228 return 0; 229 } 230 231 if ((md = EVP_MD_CTX_md(dctx->md_ctx)) == NULL) { 232 SM2error(ERR_R_EVP_LIB); 233 return 0; 234 } 235 236 if ((md_len = EVP_MD_size(md)) < 0) { 237 SM2error(SM2_R_INVALID_DIGEST); 238 return 0; 239 } 240 241 if (sm2_compute_userid_digest(za, md, dctx->uid, dctx->uid_len, 242 ctx->pkey->pkey.ec) != 1) { 243 SM2error(SM2_R_DIGEST_FAILURE); 244 return 0; 245 } 246 return EVP_DigestUpdate(dctx->md_ctx, za, md_len); 247 } 248 249 case EVP_PKEY_CTRL_SM2_GET_UID_LEN: 250 if (p2 == NULL) { 251 SM2error(ERR_R_PASSED_NULL_PARAMETER); 252 return 0; 253 } 254 *(size_t *)p2 = dctx->uid_len; 255 return 1; 256 257 case EVP_PKEY_CTRL_SM2_GET_UID: 258 if (p2 == NULL) { 259 SM2error(ERR_R_PASSED_NULL_PARAMETER); 260 return 0; 261 } 262 if (dctx->uid_len == 0) { 263 return 1; 264 } 265 memcpy(p2, dctx->uid, dctx->uid_len); 266 return 1; 267 268 case EVP_PKEY_CTRL_MD: 269 dctx->md = p2; 270 return 1; 271 272 default: 273 return -2; 274 } 275 } 276 277 static int 278 pkey_sm2_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, const char *value) 279 { 280 int nid; 281 282 if (strcmp(type, "ec_paramgen_curve") == 0) { 283 if (((nid = EC_curve_nist2nid(value)) == NID_undef) && 284 ((nid = OBJ_sn2nid(value)) == NID_undef) && 285 ((nid = OBJ_ln2nid(value)) == NID_undef)) { 286 SM2error(SM2_R_INVALID_CURVE); 287 return 0; 288 } 289 return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid); 290 } else if (strcmp(type, "sm2_uid") == 0) { 291 return EVP_PKEY_CTX_set_sm2_uid(ctx, (void*) value, 292 (int)strlen(value)); 293 } 294 295 return -2; 296 } 297 298 const EVP_PKEY_METHOD sm2_pkey_meth = { 299 .pkey_id = EVP_PKEY_SM2, 300 .init = pkey_sm2_init, 301 .copy = pkey_sm2_copy, 302 .cleanup = pkey_sm2_cleanup, 303 304 .sign = pkey_sm2_sign, 305 306 .verify = pkey_sm2_verify, 307 308 .encrypt = pkey_sm2_encrypt, 309 310 .decrypt = pkey_sm2_decrypt, 311 312 .ctrl = pkey_sm2_ctrl, 313 .ctrl_str = pkey_sm2_ctrl_str 314 }; 315 316 #endif /* OPENSSL_NO_SM2 */ 317