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 "ecdsa_openssl.h"
17
18 #include <openssl/bio.h>
19 #include <openssl/err.h>
20
21 #include "algorithm_parameter.h"
22 #include "openssl_adapter.h"
23 #include "openssl_class.h"
24 #include "openssl_common.h"
25 #include "log.h"
26 #include "memory.h"
27 #include "utils.h"
28
29 #define OPENSSL_ECC_SIGN_CLASS "OPENSSL.ECC.SIGN"
30 #define OPENSSL_ECC_VERIFY_CLASS "OPENSSL.ECC.VERIFY"
31
32 typedef struct {
33 HcfSignSpi base;
34
35 const EVP_MD *digestAlg;
36
37 EVP_MD_CTX *ctx;
38
39 CryptoStatus status;
40 } HcfSignSpiEcdsaOpensslImpl;
41
42 typedef struct {
43 HcfVerifySpi base;
44
45 const EVP_MD *digestAlg;
46
47 EVP_MD_CTX *ctx;
48
49 CryptoStatus status;
50 } HcfVerifySpiEcdsaOpensslImpl;
51
IsDigestAlgValid(uint32_t alg)52 static bool IsDigestAlgValid(uint32_t alg)
53 {
54 if ((alg == HCF_OPENSSL_DIGEST_SHA1) || (alg == HCF_OPENSSL_DIGEST_SHA224) ||
55 (alg == HCF_OPENSSL_DIGEST_SHA256) ||(alg == HCF_OPENSSL_DIGEST_SHA384) ||
56 (alg == HCF_OPENSSL_DIGEST_SHA512)) {
57 return true;
58 } else {
59 LOGE("Invalid digest num is %u.", alg);
60 return false;
61 }
62 }
63
64 // export interfaces
GetEcdsaSignClass(void)65 static const char *GetEcdsaSignClass(void)
66 {
67 return OPENSSL_ECC_SIGN_CLASS;
68 }
69
GetEcdsaVerifyClass(void)70 static const char *GetEcdsaVerifyClass(void)
71 {
72 return OPENSSL_ECC_VERIFY_CLASS;
73 }
74
DestroyEcdsaSign(HcfObjectBase * self)75 static void DestroyEcdsaSign(HcfObjectBase *self)
76 {
77 if (self == NULL) {
78 return;
79 }
80 if (!IsClassMatch(self, GetEcdsaSignClass())) {
81 return;
82 }
83 HcfSignSpiEcdsaOpensslImpl *impl = (HcfSignSpiEcdsaOpensslImpl *)self;
84 Openssl_EVP_MD_CTX_free(impl->ctx);
85 impl->ctx = NULL;
86 HcfFree(impl);
87 }
88
DestroyEcdsaVerify(HcfObjectBase * self)89 static void DestroyEcdsaVerify(HcfObjectBase *self)
90 {
91 if (self == NULL) {
92 return;
93 }
94 if (!IsClassMatch(self, GetEcdsaVerifyClass())) {
95 return;
96 }
97 HcfVerifySpiEcdsaOpensslImpl *impl = (HcfVerifySpiEcdsaOpensslImpl *)self;
98 Openssl_EVP_MD_CTX_free(impl->ctx);
99 impl->ctx = NULL;
100 HcfFree(impl);
101 }
102
EngineSignInit(HcfSignSpi * self,HcfParamsSpec * params,HcfPriKey * privateKey)103 static HcfResult EngineSignInit(HcfSignSpi *self, HcfParamsSpec *params, HcfPriKey *privateKey)
104 {
105 (void)params;
106 if ((self == NULL) || (privateKey == NULL)) {
107 LOGE("Invalid input parameter.");
108 return HCF_INVALID_PARAMS;
109 }
110 if ((!IsClassMatch((HcfObjectBase *)self, GetEcdsaSignClass())) ||
111 (!IsClassMatch((HcfObjectBase *)privateKey, HCF_OPENSSL_ECC_PRI_KEY_CLASS))) {
112 return HCF_INVALID_PARAMS;
113 }
114
115 HcfSignSpiEcdsaOpensslImpl *impl = (HcfSignSpiEcdsaOpensslImpl *)self;
116 if (impl->status != UNINITIALIZED) {
117 LOGE("Repeated initialization is not allowed.");
118 return HCF_INVALID_PARAMS;
119 }
120 EC_KEY *ecKey = Openssl_EC_KEY_dup(((HcfOpensslEccPriKey *)privateKey)->ecKey);
121 if (ecKey == NULL) {
122 HcfPrintOpensslError();
123 return HCF_ERR_CRYPTO_OPERATION;
124 }
125 EVP_PKEY *pKey = Openssl_EVP_PKEY_new();
126 if (pKey == NULL) {
127 HcfPrintOpensslError();
128 Openssl_EC_KEY_free(ecKey);
129 return HCF_ERR_CRYPTO_OPERATION;
130 }
131 if (Openssl_EVP_PKEY_assign_EC_KEY(pKey, ecKey) != HCF_OPENSSL_SUCCESS) {
132 HcfPrintOpensslError();
133 Openssl_EC_KEY_free(ecKey);
134 Openssl_EVP_PKEY_free(pKey);
135 return HCF_ERR_CRYPTO_OPERATION;
136 }
137 if (Openssl_EVP_DigestSignInit(impl->ctx, NULL, impl->digestAlg, NULL, pKey) != HCF_OPENSSL_SUCCESS) {
138 HcfPrintOpensslError();
139 Openssl_EVP_PKEY_free(pKey);
140 return HCF_ERR_CRYPTO_OPERATION;
141 }
142 Openssl_EVP_PKEY_free(pKey);
143 impl->status = INITIALIZED;
144 return HCF_SUCCESS;
145 }
146
EngineSignUpdate(HcfSignSpi * self,HcfBlob * data)147 static HcfResult EngineSignUpdate(HcfSignSpi *self, HcfBlob *data)
148 {
149 if ((self == NULL) || (!IsBlobValid(data))) {
150 LOGE("Invalid input parameter.");
151 return HCF_INVALID_PARAMS;
152 }
153 if (!IsClassMatch((HcfObjectBase *)self, GetEcdsaSignClass())) {
154 return HCF_INVALID_PARAMS;
155 }
156 HcfSignSpiEcdsaOpensslImpl *impl = (HcfSignSpiEcdsaOpensslImpl *)self;
157 if (impl->status == UNINITIALIZED) {
158 LOGE("Sign object has not been initialized.");
159 return HCF_INVALID_PARAMS;
160 }
161 if (Openssl_EVP_DigestSignUpdate(impl->ctx, data->data, data->len) != HCF_OPENSSL_SUCCESS) {
162 HcfPrintOpensslError();
163 return HCF_ERR_CRYPTO_OPERATION;
164 }
165 impl->status = READY;
166 return HCF_SUCCESS;
167 }
168
EngineSignDoFinal(HcfSignSpi * self,HcfBlob * data,HcfBlob * returnSignatureData)169 static HcfResult EngineSignDoFinal(HcfSignSpi *self, HcfBlob *data, HcfBlob *returnSignatureData)
170 {
171 if ((self == NULL) || (returnSignatureData == NULL)) {
172 LOGE("Invalid input parameter.");
173 return HCF_INVALID_PARAMS;
174 }
175 if (!IsClassMatch((HcfObjectBase *)self, GetEcdsaSignClass())) {
176 return HCF_INVALID_PARAMS;
177 }
178
179 HcfSignSpiEcdsaOpensslImpl *impl = (HcfSignSpiEcdsaOpensslImpl *)self;
180 if (IsBlobValid(data)) {
181 if (Openssl_EVP_DigestSignUpdate(impl->ctx, data->data, data->len) != HCF_OPENSSL_SUCCESS) {
182 HcfPrintOpensslError();
183 return HCF_ERR_CRYPTO_OPERATION;
184 }
185 impl->status = READY;
186 }
187 if (impl->status != READY) {
188 LOGE("The message has not been transferred.");
189 return HCF_INVALID_PARAMS;
190 }
191 size_t maxLen;
192 if (Openssl_EVP_DigestSignFinal(impl->ctx, NULL, &maxLen) != HCF_OPENSSL_SUCCESS) {
193 HcfPrintOpensslError();
194 return HCF_ERR_CRYPTO_OPERATION;
195 }
196 uint8_t *outData = (uint8_t *)HcfMalloc(maxLen, 0);
197 if (outData == NULL) {
198 LOGE("Failed to allocate outData memory!");
199 return HCF_ERR_MALLOC;
200 }
201 size_t actualLen = maxLen;
202 if (Openssl_EVP_DigestSignFinal(impl->ctx, outData, &actualLen) != HCF_OPENSSL_SUCCESS) {
203 HcfPrintOpensslError();
204 HcfFree(outData);
205 return HCF_ERR_CRYPTO_OPERATION;
206 }
207 if (actualLen > maxLen) {
208 LOGE("signature data too long.");
209 HcfFree(outData);
210 return HCF_ERR_CRYPTO_OPERATION;
211 }
212
213 returnSignatureData->data = outData;
214 returnSignatureData->len = (uint32_t)actualLen;
215 return HCF_SUCCESS;
216 }
217
EngineVerifyInit(HcfVerifySpi * self,HcfParamsSpec * params,HcfPubKey * publicKey)218 static HcfResult EngineVerifyInit(HcfVerifySpi *self, HcfParamsSpec *params, HcfPubKey *publicKey)
219 {
220 (void)params;
221 if ((self == NULL) || (publicKey == NULL)) {
222 LOGE("Invalid input parameter.");
223 return HCF_INVALID_PARAMS;
224 }
225 if ((!IsClassMatch((HcfObjectBase *)self, GetEcdsaVerifyClass())) ||
226 (!IsClassMatch((HcfObjectBase *)publicKey, HCF_OPENSSL_ECC_PUB_KEY_CLASS))) {
227 return HCF_INVALID_PARAMS;
228 }
229
230 HcfVerifySpiEcdsaOpensslImpl *impl = (HcfVerifySpiEcdsaOpensslImpl *)self;
231 if (impl->status != UNINITIALIZED) {
232 LOGE("Repeated initialization is not allowed.");
233 return HCF_INVALID_PARAMS;
234 }
235 EC_KEY *ecKey = Openssl_EC_KEY_dup(((HcfOpensslEccPubKey *)publicKey)->ecKey);
236 if (ecKey == NULL) {
237 HcfPrintOpensslError();
238 return HCF_ERR_CRYPTO_OPERATION;
239 }
240 EVP_PKEY *pKey = Openssl_EVP_PKEY_new();
241 if (pKey == NULL) {
242 HcfPrintOpensslError();
243 Openssl_EC_KEY_free(ecKey);
244 return HCF_ERR_CRYPTO_OPERATION;
245 }
246 if (Openssl_EVP_PKEY_assign_EC_KEY(pKey, ecKey) != HCF_OPENSSL_SUCCESS) {
247 HcfPrintOpensslError();
248 Openssl_EC_KEY_free(ecKey);
249 Openssl_EVP_PKEY_free(pKey);
250 return HCF_ERR_CRYPTO_OPERATION;
251 }
252 if (Openssl_EVP_DigestVerifyInit(impl->ctx, NULL, impl->digestAlg, NULL, pKey) != HCF_OPENSSL_SUCCESS) {
253 HcfPrintOpensslError();
254 Openssl_EVP_PKEY_free(pKey);
255 return HCF_ERR_CRYPTO_OPERATION;
256 }
257 Openssl_EVP_PKEY_free(pKey);
258 impl->status = INITIALIZED;
259 return HCF_SUCCESS;
260 }
261
EngineVerifyUpdate(HcfVerifySpi * self,HcfBlob * data)262 static HcfResult EngineVerifyUpdate(HcfVerifySpi *self, HcfBlob *data)
263 {
264 if ((self == NULL) || (!IsBlobValid(data))) {
265 LOGE("Invalid input parameter.");
266 return HCF_INVALID_PARAMS;
267 }
268 if (!IsClassMatch((HcfObjectBase *)self, GetEcdsaVerifyClass())) {
269 return HCF_INVALID_PARAMS;
270 }
271
272 HcfVerifySpiEcdsaOpensslImpl *impl = (HcfVerifySpiEcdsaOpensslImpl *)self;
273 if (impl->status == UNINITIALIZED) {
274 LOGE("Verify object has not been initialized.");
275 return HCF_INVALID_PARAMS;
276 }
277 if (Openssl_EVP_DigestVerifyUpdate(impl->ctx, data->data, data->len) != HCF_OPENSSL_SUCCESS) {
278 HcfPrintOpensslError();
279 return HCF_ERR_CRYPTO_OPERATION;
280 }
281 impl->status = READY;
282 return HCF_SUCCESS;
283 }
284
EngineVerifyDoFinal(HcfVerifySpi * self,HcfBlob * data,HcfBlob * signatureData)285 static bool EngineVerifyDoFinal(HcfVerifySpi *self, HcfBlob *data, HcfBlob *signatureData)
286 {
287 if ((self == NULL) || (!IsBlobValid(signatureData))) {
288 LOGE("Invalid input parameter.");
289 return false;
290 }
291 if (!IsClassMatch((HcfObjectBase *)self, GetEcdsaVerifyClass())) {
292 return false;
293 }
294
295 HcfVerifySpiEcdsaOpensslImpl *impl = (HcfVerifySpiEcdsaOpensslImpl *)self;
296 if (IsBlobValid(data)) {
297 if (Openssl_EVP_DigestVerifyUpdate(impl->ctx, data->data, data->len) != HCF_OPENSSL_SUCCESS) {
298 HcfPrintOpensslError();
299 return false;
300 }
301 impl->status = READY;
302 }
303 if (impl->status != READY) {
304 LOGE("The message has not been transferred.");
305 return false;
306 }
307 if (Openssl_EVP_DigestVerifyFinal(impl->ctx, signatureData->data, signatureData->len) != HCF_OPENSSL_SUCCESS) {
308 HcfPrintOpensslError();
309 return false;
310 }
311 return true;
312 }
313
HcfSignSpiEcdsaCreate(HcfSignatureParams * params,HcfSignSpi ** returnObj)314 HcfResult HcfSignSpiEcdsaCreate(HcfSignatureParams *params, HcfSignSpi **returnObj)
315 {
316 if ((params == NULL) || (returnObj == NULL)) {
317 LOGE("Invalid input parameter.");
318 return HCF_INVALID_PARAMS;
319 }
320 if (!IsDigestAlgValid(params->md)) {
321 return HCF_INVALID_PARAMS;
322 }
323 EVP_MD *opensslAlg = NULL;
324 int32_t ret = GetOpensslDigestAlg(params->md, &opensslAlg);
325 if (ret != HCF_SUCCESS || opensslAlg == NULL) {
326 LOGE("Failed to Invalid digest!");
327 return HCF_INVALID_PARAMS;
328 }
329
330 HcfSignSpiEcdsaOpensslImpl *returnImpl = (HcfSignSpiEcdsaOpensslImpl *)HcfMalloc(
331 sizeof(HcfSignSpiEcdsaOpensslImpl), 0);
332 if (returnImpl == NULL) {
333 LOGE("Failed to allocate returnImpl memroy!");
334 return HCF_ERR_MALLOC;
335 }
336 returnImpl->base.base.getClass = GetEcdsaSignClass;
337 returnImpl->base.base.destroy = DestroyEcdsaSign;
338 returnImpl->base.engineInit = EngineSignInit;
339 returnImpl->base.engineUpdate = EngineSignUpdate;
340 returnImpl->base.engineSign = EngineSignDoFinal;
341 returnImpl->digestAlg = opensslAlg;
342 returnImpl->status = UNINITIALIZED;
343 returnImpl->ctx = Openssl_EVP_MD_CTX_new();
344 if (returnImpl->ctx == NULL) {
345 LOGE("Failed to allocate ctx memory!");
346 HcfFree(returnImpl);
347 return HCF_ERR_MALLOC;
348 }
349
350 *returnObj = (HcfSignSpi *)returnImpl;
351 return HCF_SUCCESS;
352 }
353
HcfVerifySpiEcdsaCreate(HcfSignatureParams * params,HcfVerifySpi ** returnObj)354 HcfResult HcfVerifySpiEcdsaCreate(HcfSignatureParams *params, HcfVerifySpi **returnObj)
355 {
356 if ((params == NULL) || (returnObj == NULL)) {
357 LOGE("Invalid input parameter.");
358 return HCF_INVALID_PARAMS;
359 }
360 if (!IsDigestAlgValid(params->md)) {
361 return HCF_INVALID_PARAMS;
362 }
363 EVP_MD *opensslAlg = NULL;
364 int32_t ret = GetOpensslDigestAlg(params->md, &opensslAlg);
365 if (ret != HCF_SUCCESS || opensslAlg == NULL) {
366 LOGE("Failed to Invalid digest!");
367 return HCF_INVALID_PARAMS;
368 }
369
370 HcfVerifySpiEcdsaOpensslImpl *returnImpl = (HcfVerifySpiEcdsaOpensslImpl *)HcfMalloc(
371 sizeof(HcfVerifySpiEcdsaOpensslImpl), 0);
372 if (returnImpl == NULL) {
373 LOGE("Failed to allocate returnImpl memroy!");
374 return HCF_ERR_MALLOC;
375 }
376 returnImpl->base.base.getClass = GetEcdsaVerifyClass;
377 returnImpl->base.base.destroy = DestroyEcdsaVerify;
378 returnImpl->base.engineInit = EngineVerifyInit;
379 returnImpl->base.engineUpdate = EngineVerifyUpdate;
380 returnImpl->base.engineVerify = EngineVerifyDoFinal;
381 returnImpl->digestAlg = opensslAlg;
382 returnImpl->status = UNINITIALIZED;
383 returnImpl->ctx = Openssl_EVP_MD_CTX_new();
384 if (returnImpl->ctx == NULL) {
385 LOGE("Failed to allocate ctx memory!");
386 HcfFree(returnImpl);
387 return HCF_ERR_MALLOC;
388 }
389
390 *returnObj = (HcfVerifySpi *)returnImpl;
391 return HCF_SUCCESS;
392 }
393