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