• 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 "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