1b077aed3SPierre Pronchery /*
2*e7be843bSPierre Pronchery * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
3b077aed3SPierre Pronchery *
4b077aed3SPierre Pronchery * Licensed under the Apache License 2.0 (the "License"). You may not use
5b077aed3SPierre Pronchery * this file except in compliance with the License. You can obtain a copy
6b077aed3SPierre Pronchery * in the file LICENSE in the source distribution or at
7b077aed3SPierre Pronchery * https://www.openssl.org/source/license.html
8b077aed3SPierre Pronchery */
9b077aed3SPierre Pronchery
10b077aed3SPierre Pronchery #include "internal/deprecated.h"
11b077aed3SPierre Pronchery
12b077aed3SPierre Pronchery #include <openssl/crypto.h>
13b077aed3SPierre Pronchery #include <openssl/evp.h>
14b077aed3SPierre Pronchery #include <openssl/core_dispatch.h>
15b077aed3SPierre Pronchery #include <openssl/core_names.h>
16b077aed3SPierre Pronchery #include <openssl/params.h>
17b077aed3SPierre Pronchery #include <openssl/err.h>
18b077aed3SPierre Pronchery #include <openssl/proverr.h>
19b077aed3SPierre Pronchery #include "crypto/sm2.h"
20b077aed3SPierre Pronchery #include "prov/provider_ctx.h"
21b077aed3SPierre Pronchery #include "prov/implementations.h"
22*e7be843bSPierre Pronchery #include "prov/providercommon.h"
23b077aed3SPierre Pronchery #include "prov/provider_util.h"
24b077aed3SPierre Pronchery
25b077aed3SPierre Pronchery static OSSL_FUNC_asym_cipher_newctx_fn sm2_newctx;
26b077aed3SPierre Pronchery static OSSL_FUNC_asym_cipher_encrypt_init_fn sm2_init;
27b077aed3SPierre Pronchery static OSSL_FUNC_asym_cipher_encrypt_fn sm2_asym_encrypt;
28b077aed3SPierre Pronchery static OSSL_FUNC_asym_cipher_decrypt_init_fn sm2_init;
29b077aed3SPierre Pronchery static OSSL_FUNC_asym_cipher_decrypt_fn sm2_asym_decrypt;
30b077aed3SPierre Pronchery static OSSL_FUNC_asym_cipher_freectx_fn sm2_freectx;
31b077aed3SPierre Pronchery static OSSL_FUNC_asym_cipher_dupctx_fn sm2_dupctx;
32b077aed3SPierre Pronchery static OSSL_FUNC_asym_cipher_get_ctx_params_fn sm2_get_ctx_params;
33b077aed3SPierre Pronchery static OSSL_FUNC_asym_cipher_gettable_ctx_params_fn sm2_gettable_ctx_params;
34b077aed3SPierre Pronchery static OSSL_FUNC_asym_cipher_set_ctx_params_fn sm2_set_ctx_params;
35b077aed3SPierre Pronchery static OSSL_FUNC_asym_cipher_settable_ctx_params_fn sm2_settable_ctx_params;
36b077aed3SPierre Pronchery
37b077aed3SPierre Pronchery /*
38b077aed3SPierre Pronchery * What's passed as an actual key is defined by the KEYMGMT interface.
39b077aed3SPierre Pronchery * We happen to know that our KEYMGMT simply passes EC_KEY structures, so
40b077aed3SPierre Pronchery * we use that here too.
41b077aed3SPierre Pronchery */
42b077aed3SPierre Pronchery
43b077aed3SPierre Pronchery typedef struct {
44b077aed3SPierre Pronchery OSSL_LIB_CTX *libctx;
45b077aed3SPierre Pronchery EC_KEY *key;
46b077aed3SPierre Pronchery PROV_DIGEST md;
47b077aed3SPierre Pronchery } PROV_SM2_CTX;
48b077aed3SPierre Pronchery
sm2_newctx(void * provctx)49b077aed3SPierre Pronchery static void *sm2_newctx(void *provctx)
50b077aed3SPierre Pronchery {
51b077aed3SPierre Pronchery PROV_SM2_CTX *psm2ctx = OPENSSL_zalloc(sizeof(PROV_SM2_CTX));
52b077aed3SPierre Pronchery
53b077aed3SPierre Pronchery if (psm2ctx == NULL)
54b077aed3SPierre Pronchery return NULL;
55b077aed3SPierre Pronchery psm2ctx->libctx = PROV_LIBCTX_OF(provctx);
56b077aed3SPierre Pronchery
57b077aed3SPierre Pronchery return psm2ctx;
58b077aed3SPierre Pronchery }
59b077aed3SPierre Pronchery
sm2_init(void * vpsm2ctx,void * vkey,const OSSL_PARAM params[])60b077aed3SPierre Pronchery static int sm2_init(void *vpsm2ctx, void *vkey, const OSSL_PARAM params[])
61b077aed3SPierre Pronchery {
62b077aed3SPierre Pronchery PROV_SM2_CTX *psm2ctx = (PROV_SM2_CTX *)vpsm2ctx;
63b077aed3SPierre Pronchery
64b077aed3SPierre Pronchery if (psm2ctx == NULL || vkey == NULL || !EC_KEY_up_ref(vkey))
65b077aed3SPierre Pronchery return 0;
66b077aed3SPierre Pronchery EC_KEY_free(psm2ctx->key);
67b077aed3SPierre Pronchery psm2ctx->key = vkey;
68b077aed3SPierre Pronchery
69b077aed3SPierre Pronchery return sm2_set_ctx_params(psm2ctx, params);
70b077aed3SPierre Pronchery }
71b077aed3SPierre Pronchery
sm2_get_md(PROV_SM2_CTX * psm2ctx)72b077aed3SPierre Pronchery static const EVP_MD *sm2_get_md(PROV_SM2_CTX *psm2ctx)
73b077aed3SPierre Pronchery {
74b077aed3SPierre Pronchery const EVP_MD *md = ossl_prov_digest_md(&psm2ctx->md);
75b077aed3SPierre Pronchery
76b077aed3SPierre Pronchery if (md == NULL)
77b077aed3SPierre Pronchery md = ossl_prov_digest_fetch(&psm2ctx->md, psm2ctx->libctx, "SM3", NULL);
78b077aed3SPierre Pronchery
79b077aed3SPierre Pronchery return md;
80b077aed3SPierre Pronchery }
81b077aed3SPierre Pronchery
sm2_asym_encrypt(void * vpsm2ctx,unsigned char * out,size_t * outlen,size_t outsize,const unsigned char * in,size_t inlen)82b077aed3SPierre Pronchery static int sm2_asym_encrypt(void *vpsm2ctx, unsigned char *out, size_t *outlen,
83b077aed3SPierre Pronchery size_t outsize, const unsigned char *in,
84b077aed3SPierre Pronchery size_t inlen)
85b077aed3SPierre Pronchery {
86b077aed3SPierre Pronchery PROV_SM2_CTX *psm2ctx = (PROV_SM2_CTX *)vpsm2ctx;
87b077aed3SPierre Pronchery const EVP_MD *md = sm2_get_md(psm2ctx);
88b077aed3SPierre Pronchery
89b077aed3SPierre Pronchery if (md == NULL)
90b077aed3SPierre Pronchery return 0;
91b077aed3SPierre Pronchery
92b077aed3SPierre Pronchery if (out == NULL) {
93b077aed3SPierre Pronchery if (!ossl_sm2_ciphertext_size(psm2ctx->key, md, inlen, outlen)) {
94b077aed3SPierre Pronchery ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY);
95b077aed3SPierre Pronchery return 0;
96b077aed3SPierre Pronchery }
97b077aed3SPierre Pronchery return 1;
98b077aed3SPierre Pronchery }
99b077aed3SPierre Pronchery
100b077aed3SPierre Pronchery return ossl_sm2_encrypt(psm2ctx->key, md, in, inlen, out, outlen);
101b077aed3SPierre Pronchery }
102b077aed3SPierre Pronchery
sm2_asym_decrypt(void * vpsm2ctx,unsigned char * out,size_t * outlen,size_t outsize,const unsigned char * in,size_t inlen)103b077aed3SPierre Pronchery static int sm2_asym_decrypt(void *vpsm2ctx, unsigned char *out, size_t *outlen,
104b077aed3SPierre Pronchery size_t outsize, const unsigned char *in,
105b077aed3SPierre Pronchery size_t inlen)
106b077aed3SPierre Pronchery {
107b077aed3SPierre Pronchery PROV_SM2_CTX *psm2ctx = (PROV_SM2_CTX *)vpsm2ctx;
108b077aed3SPierre Pronchery const EVP_MD *md = sm2_get_md(psm2ctx);
109b077aed3SPierre Pronchery
110b077aed3SPierre Pronchery if (md == NULL)
111b077aed3SPierre Pronchery return 0;
112b077aed3SPierre Pronchery
113b077aed3SPierre Pronchery if (out == NULL) {
114b077aed3SPierre Pronchery if (!ossl_sm2_plaintext_size(in, inlen, outlen))
115b077aed3SPierre Pronchery return 0;
116b077aed3SPierre Pronchery return 1;
117b077aed3SPierre Pronchery }
118b077aed3SPierre Pronchery
119b077aed3SPierre Pronchery return ossl_sm2_decrypt(psm2ctx->key, md, in, inlen, out, outlen);
120b077aed3SPierre Pronchery }
121b077aed3SPierre Pronchery
sm2_freectx(void * vpsm2ctx)122b077aed3SPierre Pronchery static void sm2_freectx(void *vpsm2ctx)
123b077aed3SPierre Pronchery {
124b077aed3SPierre Pronchery PROV_SM2_CTX *psm2ctx = (PROV_SM2_CTX *)vpsm2ctx;
125b077aed3SPierre Pronchery
126b077aed3SPierre Pronchery EC_KEY_free(psm2ctx->key);
127b077aed3SPierre Pronchery ossl_prov_digest_reset(&psm2ctx->md);
128b077aed3SPierre Pronchery
129b077aed3SPierre Pronchery OPENSSL_free(psm2ctx);
130b077aed3SPierre Pronchery }
131b077aed3SPierre Pronchery
sm2_dupctx(void * vpsm2ctx)132b077aed3SPierre Pronchery static void *sm2_dupctx(void *vpsm2ctx)
133b077aed3SPierre Pronchery {
134b077aed3SPierre Pronchery PROV_SM2_CTX *srcctx = (PROV_SM2_CTX *)vpsm2ctx;
135b077aed3SPierre Pronchery PROV_SM2_CTX *dstctx;
136b077aed3SPierre Pronchery
137b077aed3SPierre Pronchery dstctx = OPENSSL_zalloc(sizeof(*srcctx));
138b077aed3SPierre Pronchery if (dstctx == NULL)
139b077aed3SPierre Pronchery return NULL;
140b077aed3SPierre Pronchery
141b077aed3SPierre Pronchery *dstctx = *srcctx;
142b077aed3SPierre Pronchery memset(&dstctx->md, 0, sizeof(dstctx->md));
143b077aed3SPierre Pronchery
144b077aed3SPierre Pronchery if (dstctx->key != NULL && !EC_KEY_up_ref(dstctx->key)) {
145b077aed3SPierre Pronchery OPENSSL_free(dstctx);
146b077aed3SPierre Pronchery return NULL;
147b077aed3SPierre Pronchery }
148b077aed3SPierre Pronchery
149b077aed3SPierre Pronchery if (!ossl_prov_digest_copy(&dstctx->md, &srcctx->md)) {
150b077aed3SPierre Pronchery sm2_freectx(dstctx);
151b077aed3SPierre Pronchery return NULL;
152b077aed3SPierre Pronchery }
153b077aed3SPierre Pronchery
154b077aed3SPierre Pronchery return dstctx;
155b077aed3SPierre Pronchery }
156b077aed3SPierre Pronchery
sm2_get_ctx_params(void * vpsm2ctx,OSSL_PARAM * params)157b077aed3SPierre Pronchery static int sm2_get_ctx_params(void *vpsm2ctx, OSSL_PARAM *params)
158b077aed3SPierre Pronchery {
159b077aed3SPierre Pronchery PROV_SM2_CTX *psm2ctx = (PROV_SM2_CTX *)vpsm2ctx;
160b077aed3SPierre Pronchery OSSL_PARAM *p;
161b077aed3SPierre Pronchery
162b077aed3SPierre Pronchery if (vpsm2ctx == NULL)
163b077aed3SPierre Pronchery return 0;
164b077aed3SPierre Pronchery
165b077aed3SPierre Pronchery p = OSSL_PARAM_locate(params, OSSL_ASYM_CIPHER_PARAM_DIGEST);
166b077aed3SPierre Pronchery if (p != NULL) {
167b077aed3SPierre Pronchery const EVP_MD *md = ossl_prov_digest_md(&psm2ctx->md);
168b077aed3SPierre Pronchery
169b077aed3SPierre Pronchery if (!OSSL_PARAM_set_utf8_string(p, md == NULL ? ""
170b077aed3SPierre Pronchery : EVP_MD_get0_name(md)))
171b077aed3SPierre Pronchery return 0;
172b077aed3SPierre Pronchery }
173b077aed3SPierre Pronchery
174b077aed3SPierre Pronchery return 1;
175b077aed3SPierre Pronchery }
176b077aed3SPierre Pronchery
177b077aed3SPierre Pronchery static const OSSL_PARAM known_gettable_ctx_params[] = {
178b077aed3SPierre Pronchery OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_DIGEST, NULL, 0),
179b077aed3SPierre Pronchery OSSL_PARAM_END
180b077aed3SPierre Pronchery };
181b077aed3SPierre Pronchery
sm2_gettable_ctx_params(ossl_unused void * vpsm2ctx,ossl_unused void * provctx)182b077aed3SPierre Pronchery static const OSSL_PARAM *sm2_gettable_ctx_params(ossl_unused void *vpsm2ctx,
183b077aed3SPierre Pronchery ossl_unused void *provctx)
184b077aed3SPierre Pronchery {
185b077aed3SPierre Pronchery return known_gettable_ctx_params;
186b077aed3SPierre Pronchery }
187b077aed3SPierre Pronchery
sm2_set_ctx_params(void * vpsm2ctx,const OSSL_PARAM params[])188b077aed3SPierre Pronchery static int sm2_set_ctx_params(void *vpsm2ctx, const OSSL_PARAM params[])
189b077aed3SPierre Pronchery {
190b077aed3SPierre Pronchery PROV_SM2_CTX *psm2ctx = (PROV_SM2_CTX *)vpsm2ctx;
191b077aed3SPierre Pronchery
192b077aed3SPierre Pronchery if (psm2ctx == NULL)
193b077aed3SPierre Pronchery return 0;
194*e7be843bSPierre Pronchery if (ossl_param_is_empty(params))
195b077aed3SPierre Pronchery return 1;
196b077aed3SPierre Pronchery
197b077aed3SPierre Pronchery if (!ossl_prov_digest_load_from_params(&psm2ctx->md, params,
198b077aed3SPierre Pronchery psm2ctx->libctx))
199b077aed3SPierre Pronchery return 0;
200b077aed3SPierre Pronchery
201b077aed3SPierre Pronchery return 1;
202b077aed3SPierre Pronchery }
203b077aed3SPierre Pronchery
204b077aed3SPierre Pronchery static const OSSL_PARAM known_settable_ctx_params[] = {
205b077aed3SPierre Pronchery OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_DIGEST, NULL, 0),
206b077aed3SPierre Pronchery OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_PROPERTIES, NULL, 0),
207b077aed3SPierre Pronchery OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_ENGINE, NULL, 0),
208b077aed3SPierre Pronchery OSSL_PARAM_END
209b077aed3SPierre Pronchery };
210b077aed3SPierre Pronchery
sm2_settable_ctx_params(ossl_unused void * vpsm2ctx,ossl_unused void * provctx)211b077aed3SPierre Pronchery static const OSSL_PARAM *sm2_settable_ctx_params(ossl_unused void *vpsm2ctx,
212b077aed3SPierre Pronchery ossl_unused void *provctx)
213b077aed3SPierre Pronchery {
214b077aed3SPierre Pronchery return known_settable_ctx_params;
215b077aed3SPierre Pronchery }
216b077aed3SPierre Pronchery
217b077aed3SPierre Pronchery const OSSL_DISPATCH ossl_sm2_asym_cipher_functions[] = {
218b077aed3SPierre Pronchery { OSSL_FUNC_ASYM_CIPHER_NEWCTX, (void (*)(void))sm2_newctx },
219b077aed3SPierre Pronchery { OSSL_FUNC_ASYM_CIPHER_ENCRYPT_INIT, (void (*)(void))sm2_init },
220b077aed3SPierre Pronchery { OSSL_FUNC_ASYM_CIPHER_ENCRYPT, (void (*)(void))sm2_asym_encrypt },
221b077aed3SPierre Pronchery { OSSL_FUNC_ASYM_CIPHER_DECRYPT_INIT, (void (*)(void))sm2_init },
222b077aed3SPierre Pronchery { OSSL_FUNC_ASYM_CIPHER_DECRYPT, (void (*)(void))sm2_asym_decrypt },
223b077aed3SPierre Pronchery { OSSL_FUNC_ASYM_CIPHER_FREECTX, (void (*)(void))sm2_freectx },
224b077aed3SPierre Pronchery { OSSL_FUNC_ASYM_CIPHER_DUPCTX, (void (*)(void))sm2_dupctx },
225b077aed3SPierre Pronchery { OSSL_FUNC_ASYM_CIPHER_GET_CTX_PARAMS,
226b077aed3SPierre Pronchery (void (*)(void))sm2_get_ctx_params },
227b077aed3SPierre Pronchery { OSSL_FUNC_ASYM_CIPHER_GETTABLE_CTX_PARAMS,
228b077aed3SPierre Pronchery (void (*)(void))sm2_gettable_ctx_params },
229b077aed3SPierre Pronchery { OSSL_FUNC_ASYM_CIPHER_SET_CTX_PARAMS,
230b077aed3SPierre Pronchery (void (*)(void))sm2_set_ctx_params },
231b077aed3SPierre Pronchery { OSSL_FUNC_ASYM_CIPHER_SETTABLE_CTX_PARAMS,
232b077aed3SPierre Pronchery (void (*)(void))sm2_settable_ctx_params },
233*e7be843bSPierre Pronchery OSSL_DISPATCH_END
234b077aed3SPierre Pronchery };
235