xref: /freebsd/crypto/openssl/providers/implementations/asymciphers/sm2_enc.c (revision e7be843b4a162e68651d3911f0357ed464915629)
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