2 * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
11 * ECDSA low level APIs are deprecated for public use, but still ok for
14 #include "internal/deprecated.h"
16 #include "internal/cryptlib.h"
17 #include <openssl/asn1t.h>
18 #include <openssl/ec.h>
19 #include <openssl/evp.h>
20 #include "crypto/evp.h"
21 #include "crypto/sm2.h"
22 #include "crypto/sm2err.h"
24 /* EC pkey context structure */
29 /* Distinguishing Identifier, ISO/IEC 15946-3, FIPS 196 */
32 /* id_set indicates if the 'id' field is set (1) or not (0) */
36 static int pkey_sm2_init(EVP_PKEY_CTX
*ctx
)
40 if ((smctx
= OPENSSL_zalloc(sizeof(*smctx
))) == NULL
) {
41 SM2err(SM2_F_PKEY_SM2_INIT
, ERR_R_MALLOC_FAILURE
);
49 static void pkey_sm2_cleanup(EVP_PKEY_CTX
*ctx
)
51 SM2_PKEY_CTX
*smctx
= ctx
->data
;
54 OPENSSL_free(smctx
->id
);
60 static int pkey_sm2_copy(EVP_PKEY_CTX
*dst
, const EVP_PKEY_CTX
*src
)
62 SM2_PKEY_CTX
*dctx
, *sctx
;
64 if (!pkey_sm2_init(dst
))
68 if (sctx
->id
!= NULL
) {
69 dctx
->id
= OPENSSL_malloc(sctx
->id_len
);
70 if (dctx
->id
== NULL
) {
71 SM2err(SM2_F_PKEY_SM2_COPY
, ERR_R_MALLOC_FAILURE
);
72 pkey_sm2_cleanup(dst
);
75 memcpy(dctx
->id
, sctx
->id
, sctx
->id_len
);
77 dctx
->id_len
= sctx
->id_len
;
78 dctx
->id_set
= sctx
->id_set
;
84 static int pkey_sm2_sign(EVP_PKEY_CTX
*ctx
, unsigned char *sig
, size_t *siglen
,
85 const unsigned char *tbs
, size_t tbslen
)
89 EC_KEY
*ec
= ctx
->pkey
->pkey
.ec
;
90 const int sig_sz
= ECDSA_size(ctx
->pkey
->pkey
.ec
);
97 *siglen
= (size_t)sig_sz
;
101 if (*siglen
< (size_t)sig_sz
) {
102 SM2err(SM2_F_PKEY_SM2_SIGN
, SM2_R_BUFFER_TOO_SMALL
);
106 ret
= sm2_sign(tbs
, tbslen
, sig
, &sltmp
, ec
);
110 *siglen
= (size_t)sltmp
;
114 static int pkey_sm2_verify(EVP_PKEY_CTX
*ctx
,
115 const unsigned char *sig
, size_t siglen
,
116 const unsigned char *tbs
, size_t tbslen
)
118 EC_KEY
*ec
= ctx
->pkey
->pkey
.ec
;
120 return sm2_verify(tbs
, tbslen
, sig
, siglen
, ec
);
123 static int pkey_sm2_encrypt(EVP_PKEY_CTX
*ctx
,
124 unsigned char *out
, size_t *outlen
,
125 const unsigned char *in
, size_t inlen
)
127 EC_KEY
*ec
= ctx
->pkey
->pkey
.ec
;
128 SM2_PKEY_CTX
*dctx
= ctx
->data
;
129 const EVP_MD
*md
= (dctx
->md
== NULL
) ? EVP_sm3() : dctx
->md
;
132 if (!sm2_ciphertext_size(ec
, md
, inlen
, outlen
))
138 return sm2_encrypt(ec
, md
, in
, inlen
, out
, outlen
);
141 static int pkey_sm2_decrypt(EVP_PKEY_CTX
*ctx
,
142 unsigned char *out
, size_t *outlen
,
143 const unsigned char *in
, size_t inlen
)
145 EC_KEY
*ec
= ctx
->pkey
->pkey
.ec
;
146 SM2_PKEY_CTX
*dctx
= ctx
->data
;
147 const EVP_MD
*md
= (dctx
->md
== NULL
) ? EVP_sm3() : dctx
->md
;
150 if (!sm2_plaintext_size(ec
, md
, inlen
, outlen
))
156 return sm2_decrypt(ec
, md
, in
, inlen
, out
, outlen
);
159 static int pkey_sm2_ctrl(EVP_PKEY_CTX
*ctx
, int type
, int p1
, void *p2
)
161 SM2_PKEY_CTX
*smctx
= ctx
->data
;
165 case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID
:
167 * This control could be removed, which would signal it being
168 * unsupported. However, that means that when the caller uses
169 * the correct curve, it may interpret the unsupported signal
170 * as an error, so it's better to accept the control, check the
171 * value and return a corresponding value.
174 SM2err(SM2_F_PKEY_SM2_CTRL
, SM2_R_INVALID_CURVE
);
179 case EVP_PKEY_CTRL_MD
:
183 case EVP_PKEY_CTRL_GET_MD
:
184 *(const EVP_MD
**)p2
= smctx
->md
;
187 case EVP_PKEY_CTRL_SET1_ID
:
189 tmp_id
= OPENSSL_malloc(p1
);
190 if (tmp_id
== NULL
) {
191 SM2err(SM2_F_PKEY_SM2_CTRL
, ERR_R_MALLOC_FAILURE
);
194 memcpy(tmp_id
, p2
, p1
);
195 OPENSSL_free(smctx
->id
);
199 OPENSSL_free(smctx
->id
);
202 smctx
->id_len
= (size_t)p1
;
206 case EVP_PKEY_CTRL_GET1_ID
:
207 memcpy(p2
, smctx
->id
, smctx
->id_len
);
210 case EVP_PKEY_CTRL_GET1_ID_LEN
:
211 *(size_t *)p2
= smctx
->id_len
;
214 case EVP_PKEY_CTRL_DIGESTINIT
:
215 /* nothing to be inited, this is to suppress the error... */
223 static int pkey_sm2_ctrl_str(EVP_PKEY_CTX
*ctx
,
224 const char *type
, const char *value
)
230 if (strcmp(type
, "ec_paramgen_curve") == 0) {
233 if (((nid
= EC_curve_nist2nid(value
)) == NID_undef
)
234 && ((nid
= OBJ_sn2nid(value
)) == NID_undef
)
235 && ((nid
= OBJ_ln2nid(value
)) == NID_undef
)) {
236 SM2err(SM2_F_PKEY_SM2_CTRL_STR
, SM2_R_INVALID_CURVE
);
239 return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx
, nid
);
240 } else if (strcmp(type
, "ec_param_enc") == 0) {
243 if (strcmp(value
, "explicit") == 0)
245 else if (strcmp(value
, "named_curve") == 0)
246 param_enc
= OPENSSL_EC_NAMED_CURVE
;
249 return EVP_PKEY_CTX_set_ec_param_enc(ctx
, param_enc
);
250 } else if (strcmp(type
, "distid") == 0) {
251 return pkey_sm2_ctrl(ctx
, EVP_PKEY_CTRL_SET1_ID
,
252 (int)strlen(value
), (void *)value
);
253 } else if (strcmp(type
, "hexdistid") == 0) {
254 hex_id
= OPENSSL_hexstr2buf((const char *)value
, &hex_len
);
255 if (hex_id
== NULL
) {
256 SM2err(SM2_F_PKEY_SM2_CTRL_STR
, ERR_R_PASSED_INVALID_ARGUMENT
);
259 ret
= pkey_sm2_ctrl(ctx
, EVP_PKEY_CTRL_SET1_ID
, (int)hex_len
,
261 OPENSSL_free(hex_id
);
268 static int pkey_sm2_digest_custom(EVP_PKEY_CTX
*ctx
, EVP_MD_CTX
*mctx
)
270 uint8_t z
[EVP_MAX_MD_SIZE
];
271 SM2_PKEY_CTX
*smctx
= ctx
->data
;
272 EC_KEY
*ec
= ctx
->pkey
->pkey
.ec
;
273 const EVP_MD
*md
= EVP_MD_CTX_md(mctx
);
274 int mdlen
= EVP_MD_size(md
);
276 if (!smctx
->id_set
) {
278 * An ID value must be set. The specifications are not clear whether a
279 * NULL is allowed. We only allow it if set explicitly for maximum
282 SM2err(SM2_F_PKEY_SM2_DIGEST_CUSTOM
, SM2_R_ID_NOT_SET
);
287 SM2err(SM2_F_PKEY_SM2_DIGEST_CUSTOM
, SM2_R_INVALID_DIGEST
);
291 /* get hashed prefix 'z' of tbs message */
292 if (!sm2_compute_z_digest(z
, md
, smctx
->id
, smctx
->id_len
, ec
))
295 return EVP_DigestUpdate(mctx
, z
, (size_t)mdlen
);
298 static int pkey_sm2_paramgen(EVP_PKEY_CTX
*ctx
, EVP_PKEY
*pkey
)
303 ec
= EC_KEY_new_by_curve_name(NID_sm2
);
306 if (!ossl_assert(ret
= EVP_PKEY_assign_EC_KEY(pkey
, ec
)))
311 static int pkey_sm2_keygen(EVP_PKEY_CTX
*ctx
, EVP_PKEY
*pkey
)
315 ec
= EC_KEY_new_by_curve_name(NID_sm2
);
318 if (!ossl_assert(EVP_PKEY_assign_EC_KEY(pkey
, ec
))) {
322 /* Note: if error is returned, we count on caller to free pkey->pkey.ec */
323 if (ctx
->pkey
!= NULL
324 && !EVP_PKEY_copy_parameters(pkey
, ctx
->pkey
))
327 return EC_KEY_generate_key(ec
);
330 static const EVP_PKEY_METHOD sm2_pkey_meth
= {
368 pkey_sm2_digest_custom
371 const EVP_PKEY_METHOD
*sm2_pkey_method(void)
373 return &sm2_pkey_meth
;