• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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