1 /*
2 * Copyright (C) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "cipher_rsa_openssl.h"
17 #include "securec.h"
18 #include "openssl/rsa.h"
19 #include "rsa_openssl_common.h"
20 #include "log.h"
21 #include "memory.h"
22 #include "openssl_class.h"
23 #include "openssl_common.h"
24 #include "stdbool.h"
25 #include "string.h"
26 #include "utils.h"
27
28 static const char *EngineGetClass(void);
29
30 typedef struct {
31 HcfCipherGeneratorSpi super;
32
33 CipherAttr attr;
34
35 InitFlag initFlag;
36
37 EVP_PKEY_CTX *ctx;
38 } HcfCipherRsaGeneratorSpiImpl;
39
CheckCipherInitParams(enum HcfCryptoMode opMode,HcfKey * key)40 static HcfResult CheckCipherInitParams(enum HcfCryptoMode opMode, HcfKey *key)
41 {
42 switch (opMode) {
43 case ENCRYPT_MODE:
44 if (!IsClassMatch((HcfObjectBase *)key, OPENSSL_RSA_PUBKEY_CLASS)) {
45 LOGE("Class not match");
46 return HCF_INVALID_PARAMS;
47 }
48 break;
49 case DECRYPT_MODE:
50 if (!IsClassMatch((HcfObjectBase *)key, OPENSSL_RSA_PRIKEY_CLASS)) {
51 LOGE("Class not match");
52 return HCF_INVALID_PARAMS;
53 }
54 break;
55 default:
56 LOGE("Invalid opMode %u", opMode);
57 return HCF_INVALID_PARAMS;
58 }
59
60 return HCF_SUCCESS;
61 }
62
DuplicateRsaFromKey(HcfKey * key,enum HcfCryptoMode opMode,RSA ** dupRsa)63 static HcfResult DuplicateRsaFromKey(HcfKey *key, enum HcfCryptoMode opMode, RSA **dupRsa)
64 {
65 HcfResult ret = HCF_SUCCESS;
66 if (opMode == ENCRYPT_MODE) {
67 ret = DuplicateRsa(((HcfOpensslRsaPubKey *)key)->pk, false, dupRsa);
68 if (ret != HCF_SUCCESS) {
69 LOGE("dup pub rsa fail.");
70 return ret;
71 }
72 } else if (opMode == DECRYPT_MODE) {
73 ret = DuplicateRsa(((HcfOpensslRsaPriKey *)key)->sk, true, dupRsa);
74 if (ret != HCF_SUCCESS) {
75 LOGE("dup pri rsa fail.");
76 return ret;
77 }
78 } else {
79 LOGE("OpMode not match.");
80 return HCF_INVALID_PARAMS;
81 }
82 return ret;
83 }
84
InitEvpPkeyCtx(HcfCipherRsaGeneratorSpiImpl * impl,HcfKey * key,enum HcfCryptoMode opMode)85 static HcfResult InitEvpPkeyCtx(HcfCipherRsaGeneratorSpiImpl *impl, HcfKey *key, enum HcfCryptoMode opMode)
86 {
87 RSA *rsa = NULL;
88 HcfResult ret = HCF_SUCCESS;
89 ret = DuplicateRsaFromKey(key, opMode, &rsa);
90 if (ret != HCF_SUCCESS) {
91 LOGE("DuplicateRsaFromKey fail.");
92 return ret;
93 }
94 EVP_PKEY *pkey = NewEvpPkeyByRsa(rsa, false);
95 if (pkey == NULL) {
96 LOGE("NewEvpPkeyByRsa fail");
97 HcfPrintOpensslError();
98 RSA_free(rsa);
99 return HCF_ERR_CRYPTO_OPERATION;
100 }
101 impl->ctx = EVP_PKEY_CTX_new(pkey, NULL);
102 if (impl->ctx == NULL) {
103 LOGE("EVP_PKEY_CTX_new fail");
104 HcfPrintOpensslError();
105 EVP_PKEY_free(pkey);
106 return HCF_ERR_CRYPTO_OPERATION;
107 }
108 int32_t sslRet = HCF_OPENSSL_SUCCESS;
109 if (opMode == ENCRYPT_MODE) {
110 sslRet = EVP_PKEY_encrypt_init(impl->ctx);
111 } else {
112 sslRet = EVP_PKEY_decrypt_init(impl->ctx);
113 }
114 if (sslRet != HCF_OPENSSL_SUCCESS) {
115 LOGE("Init EVP_PKEY fail");
116 HcfPrintOpensslError();
117 EVP_PKEY_free(pkey);
118 EVP_PKEY_CTX_free(impl->ctx);
119 return HCF_ERR_CRYPTO_OPERATION;
120 }
121 EVP_PKEY_free(pkey);
122 return HCF_SUCCESS;
123 }
124
SetDetailParams(HcfCipherRsaGeneratorSpiImpl * impl)125 static HcfResult SetDetailParams(HcfCipherRsaGeneratorSpiImpl *impl)
126 {
127 CipherAttr attr = impl->attr;
128 const EVP_MD *md = GetOpensslDigestAlg(attr.md);
129 if (md == NULL && attr.paddingMode == HCF_OPENSSL_RSA_PKCS1_OAEP_PADDING) {
130 LOGE("md is NULL.");
131 return HCF_INVALID_PARAMS;
132 }
133 const EVP_MD *mgf1md = GetOpensslDigestAlg(attr.mgf1md);
134 if (mgf1md == NULL && attr.paddingMode == HCF_OPENSSL_RSA_PKCS1_OAEP_PADDING) {
135 LOGE("mgf1md is NULL.");
136 return HCF_INVALID_PARAMS;
137 }
138 int32_t opensslPadding = 0;
139 if (GetOpensslPadding(attr.paddingMode, &opensslPadding) != HCF_SUCCESS) {
140 LOGE("Padding is dismatch.");
141 return HCF_INVALID_PARAMS;
142 }
143 if (EVP_PKEY_CTX_set_rsa_padding(impl->ctx, opensslPadding) != HCF_OPENSSL_SUCCESS) {
144 LOGE("Cipher set padding fail.");
145 HcfPrintOpensslError();
146 return HCF_ERR_CRYPTO_OPERATION;
147 }
148 if (attr.paddingMode == HCF_OPENSSL_RSA_PKCS1_OAEP_PADDING) {
149 // set md and mgf1md
150 if (EVP_PKEY_CTX_set_rsa_oaep_md(impl->ctx, md) != HCF_OPENSSL_SUCCESS
151 || EVP_PKEY_CTX_set_rsa_mgf1_md(impl->ctx, mgf1md) != HCF_OPENSSL_SUCCESS) {
152 LOGE("Set md or mgf1md fail");
153 HcfPrintOpensslError();
154 return HCF_ERR_CRYPTO_OPERATION;
155 }
156 }
157 return HCF_SUCCESS;
158 }
159
EngineInit(HcfCipherGeneratorSpi * self,enum HcfCryptoMode opMode,HcfKey * key,HcfParamsSpec * params)160 static HcfResult EngineInit(HcfCipherGeneratorSpi *self, enum HcfCryptoMode opMode,
161 HcfKey *key, HcfParamsSpec *params)
162 {
163 LOGI("EngineInit start");
164 if (!IsClassMatch((HcfObjectBase *)self, EngineGetClass())) {
165 LOGE("Class not match");
166 return HCF_INVALID_PARAMS;
167 }
168 HcfCipherRsaGeneratorSpiImpl *impl = (HcfCipherRsaGeneratorSpiImpl *)self;
169 if (impl->initFlag != UNINITIALIZED) {
170 LOGE("The cipher has been initialize, don't init again.");
171 return HCF_INVALID_PARAMS;
172 }
173
174 // check opMode is matched with Key
175 if (CheckCipherInitParams(opMode, key) != HCF_SUCCESS) {
176 LOGE("OpMode dismatch with keyType.");
177 return HCF_INVALID_PARAMS;
178 }
179 impl->attr.mode = (int32_t)opMode;
180 if (InitEvpPkeyCtx(impl, key, opMode) != HCF_SUCCESS) {
181 LOGE("InitEvpPkeyCtx fail");
182 return HCF_ERR_CRYPTO_OPERATION;
183 }
184
185 if (SetDetailParams(impl) != HCF_SUCCESS) {
186 EVP_PKEY_CTX_free(impl->ctx);
187 LOGE("SetDetailParams fail.");
188 return HCF_ERR_CRYPTO_OPERATION;
189 }
190 impl->initFlag = INITIALIZED;
191 LOGI("EngineInit end");
192 return HCF_SUCCESS;
193 }
194
EngineUpdata(HcfCipherGeneratorSpi * self,HcfBlob * input,HcfBlob * output)195 static HcfResult EngineUpdata(HcfCipherGeneratorSpi *self, HcfBlob *input, HcfBlob *output)
196 {
197 LOGE("Openssl don't support update");
198 (void)self;
199 (void)input;
200 (void)output;
201 return HCF_NOT_SUPPORT;
202 }
203
DoRsaCrypt(EVP_PKEY_CTX * ctx,HcfBlob * input,HcfBlob * output,int32_t mode)204 static HcfResult DoRsaCrypt(EVP_PKEY_CTX *ctx, HcfBlob *input, HcfBlob *output, int32_t mode)
205 {
206 int32_t ret = HCF_OPENSSL_SUCCESS;
207 if (mode == ENCRYPT_MODE) {
208 ret = EVP_PKEY_encrypt(ctx, output->data, &output->len, input->data, input->len);
209 } else if (mode == DECRYPT_MODE) {
210 ret = EVP_PKEY_decrypt(ctx, output->data, &output->len, input->data, input->len);
211 } else {
212 LOGE("OpMode is invalid.");
213 return HCF_INVALID_PARAMS;
214 }
215 if (ret != HCF_OPENSSL_SUCCESS) {
216 HcfPrintOpensslError();
217 return HCF_ERR_CRYPTO_OPERATION;
218 }
219 return HCF_SUCCESS;
220 }
221
EngineDoFinal(HcfCipherGeneratorSpi * self,HcfBlob * input,HcfBlob * output)222 static HcfResult EngineDoFinal(HcfCipherGeneratorSpi *self, HcfBlob *input, HcfBlob *output)
223 {
224 LOGI("EngineDoFinal start");
225 if (self == NULL || input == NULL || input->data == NULL) {
226 LOGE("Param is invalid.");
227 return HCF_INVALID_PARAMS;
228 }
229 if (!IsClassMatch((HcfObjectBase *)self, EngineGetClass())) {
230 LOGE("Class not match");
231 return HCF_INVALID_PARAMS;
232 }
233 HcfCipherRsaGeneratorSpiImpl *impl = (HcfCipherRsaGeneratorSpiImpl *)self;
234 if (impl->initFlag != INITIALIZED) {
235 LOGE("RSACipher has not been init");
236 return HCF_INVALID_PARAMS;
237 }
238 CipherAttr attr = impl->attr;
239 output->len = 0;
240 output->data = NULL;
241 HcfResult ret = DoRsaCrypt(impl->ctx, input, output, attr.mode);
242 if (ret != HCF_SUCCESS) {
243 LOGE("GetOutLen fail.");
244 return HCF_ERR_CRYPTO_OPERATION;
245 }
246 LOGI("ouput data len is %zu.", output->len);
247
248 output->data = (uint8_t *)HcfMalloc(sizeof(uint8_t) * output->len, 0);
249 ret = DoRsaCrypt(impl->ctx, input, output, attr.mode);
250 if (ret != HCF_SUCCESS) {
251 HcfFree(output->data);
252 output->data = NULL;
253 output->len = 0;
254 return HCF_ERR_CRYPTO_OPERATION;
255 }
256 LOGI("EngineDoFinal end");
257 return HCF_SUCCESS;
258 }
259
EngineDestroySpiImpl(HcfObjectBase * generator)260 static void EngineDestroySpiImpl(HcfObjectBase *generator)
261 {
262 if (generator == NULL) {
263 return;
264 }
265 if (!IsClassMatch((HcfObjectBase *)generator, EngineGetClass())) {
266 LOGE("Class not match");
267 return;
268 }
269 HcfCipherRsaGeneratorSpiImpl *impl = (HcfCipherRsaGeneratorSpiImpl *)generator;
270 EVP_PKEY_CTX_free(impl->ctx);
271 impl->ctx = NULL;
272 HcfFree(impl);
273 }
274
EngineGetClass(void)275 static const char *EngineGetClass(void)
276 {
277 return OPENSSL_RSA_CIPHER_CLASS;
278 }
279
CheckRsaCipherParams(CipherAttr * params)280 static HcfResult CheckRsaCipherParams(CipherAttr *params)
281 {
282 int32_t opensslPadding = 0;
283 if (params->algo != HCF_ALG_RSA) {
284 LOGE("Cipher algo %u is invalid.", params->algo);
285 return HCF_INVALID_PARAMS;
286 }
287 if (GetOpensslPadding(params->paddingMode, &opensslPadding) != HCF_SUCCESS) {
288 LOGE("Cipher create without padding");
289 return HCF_INVALID_PARAMS;
290 }
291 if (params->paddingMode == HCF_ALG_NOPADDING && (GetOpensslDigestAlg(params->md) != NULL ||
292 GetOpensslDigestAlg(params->mgf1md) != NULL)) {
293 LOGE("Nopadding don't need md or mgf1md");
294 return HCF_INVALID_PARAMS;
295 }
296
297 if (params->paddingMode == HCF_OPENSSL_RSA_PKCS1_OAEP_PADDING && GetOpensslDigestAlg(params->md) == NULL) {
298 LOGE("md is NULL");
299 return HCF_INVALID_PARAMS;
300 }
301 if (params->paddingMode == HCF_OPENSSL_RSA_PKCS1_OAEP_PADDING && GetOpensslDigestAlg(params->mgf1md) == NULL) {
302 LOGE("Use pkcs1_oaep padding, but mgf1md is NULL");
303 return HCF_INVALID_PARAMS;
304 }
305 return HCF_SUCCESS;
306 }
307
HcfCipherRsaCipherSpiCreate(CipherAttr * params,HcfCipherGeneratorSpi ** generator)308 HcfResult HcfCipherRsaCipherSpiCreate(CipherAttr *params, HcfCipherGeneratorSpi **generator)
309 {
310 LOGI("Start create rsa cipher spiObj.");
311 if (generator == NULL || params == NULL) {
312 LOGE("Invalid input parameter.");
313 return HCF_INVALID_PARAMS;
314 }
315 HcfCipherRsaGeneratorSpiImpl *returnImpl = (HcfCipherRsaGeneratorSpiImpl *)HcfMalloc(
316 sizeof(HcfCipherRsaGeneratorSpiImpl), 0);
317 if (returnImpl == NULL) {
318 LOGE("Malloc rsa cipher fail.");
319 return HCF_ERR_MALLOC;
320 }
321 (void)memcpy_s(&returnImpl->attr, sizeof(CipherAttr), params, sizeof(CipherAttr));
322
323 if (CheckRsaCipherParams(&returnImpl->attr) != HCF_SUCCESS) {
324 HcfFree(returnImpl);
325 returnImpl = NULL;
326 return HCF_INVALID_PARAMS;
327 }
328
329 returnImpl->super.init = EngineInit;
330 returnImpl->super.update = EngineUpdata;
331 returnImpl->super.doFinal = EngineDoFinal;
332 returnImpl->super.base.destroy = EngineDestroySpiImpl;
333 returnImpl->super.base.getClass = EngineGetClass;
334 returnImpl->initFlag = UNINITIALIZED;
335 *generator = (HcfCipherGeneratorSpi *)returnImpl;
336 LOGI("Rsa Cipher create success.");
337 return HCF_SUCCESS;
338 }
339