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