• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022-2023 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 "ecdh_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 typedef struct {
30     HcfKeyAgreementSpi base;
31 } HcfKeyAgreementSpiEcdhOpensslImpl;
32 
AssignEcKeyToPkey(EC_KEY * ecKey)33 static EVP_PKEY *AssignEcKeyToPkey(EC_KEY *ecKey)
34 {
35     EVP_PKEY *pKey = Openssl_EVP_PKEY_new();
36     if (pKey == NULL) {
37         HcfPrintOpensslError();
38         return NULL;
39     }
40     if (Openssl_EVP_PKEY_assign_EC_KEY(pKey, ecKey) != HCF_OPENSSL_SUCCESS) {
41         HcfPrintOpensslError();
42         Openssl_EVP_PKEY_free(pKey);
43         return NULL;
44     }
45     return pKey;
46 }
47 
NewPKeyByEccPubKey(HcfOpensslEccPubKey * publicKey)48 static EVP_PKEY *NewPKeyByEccPubKey(HcfOpensslEccPubKey *publicKey)
49 {
50     EC_KEY *ecKey = Openssl_EC_KEY_dup(publicKey->ecKey);
51     if (ecKey == NULL) {
52         return NULL;
53     }
54     EVP_PKEY *res = AssignEcKeyToPkey(ecKey);
55     if (res == NULL) {
56         Openssl_EC_KEY_free(ecKey);
57     }
58     return res;
59 }
60 
NewPKeyByEccPriKey(HcfOpensslEccPriKey * privateKey)61 static EVP_PKEY *NewPKeyByEccPriKey(HcfOpensslEccPriKey *privateKey)
62 {
63     EC_KEY *ecKey = Openssl_EC_KEY_dup(privateKey->ecKey);
64     if (ecKey == NULL) {
65         return NULL;
66     }
67     EVP_PKEY *res = AssignEcKeyToPkey(ecKey);
68     if (res == NULL) {
69         Openssl_EC_KEY_free(ecKey);
70     }
71     return res;
72 }
73 
EcdhDerive(EVP_PKEY * priPKey,EVP_PKEY * pubPKey,HcfBlob * returnSecret)74 static HcfResult EcdhDerive(EVP_PKEY *priPKey, EVP_PKEY *pubPKey, HcfBlob *returnSecret)
75 {
76     EVP_PKEY_CTX *ctx = Openssl_EVP_PKEY_CTX_new(priPKey, NULL);
77     if (ctx == NULL) {
78         HcfPrintOpensslError();
79         return HCF_ERR_CRYPTO_OPERATION;
80     }
81     if (Openssl_EVP_PKEY_derive_init(ctx) != HCF_OPENSSL_SUCCESS) {
82         HcfPrintOpensslError();
83         Openssl_EVP_PKEY_CTX_free(ctx);
84         return HCF_ERR_CRYPTO_OPERATION;
85     }
86     if (Openssl_EVP_PKEY_derive_set_peer(ctx, pubPKey) != HCF_OPENSSL_SUCCESS) {
87         HcfPrintOpensslError();
88         Openssl_EVP_PKEY_CTX_free(ctx);
89         return HCF_ERR_CRYPTO_OPERATION;
90     }
91     size_t maxLen;
92     if (Openssl_EVP_PKEY_derive(ctx, NULL, &maxLen) != HCF_OPENSSL_SUCCESS) {
93         HcfPrintOpensslError();
94         Openssl_EVP_PKEY_CTX_free(ctx);
95         return HCF_ERR_CRYPTO_OPERATION;
96     }
97     uint8_t *secretData = (uint8_t *)HcfMalloc(maxLen, 0);
98     if (secretData == NULL) {
99         LOGE("Failed to allocate secretData memory!");
100         Openssl_EVP_PKEY_CTX_free(ctx);
101         return HCF_ERR_MALLOC;
102     }
103     size_t actualLen = maxLen;
104     if (Openssl_EVP_PKEY_derive(ctx, secretData, &actualLen) != HCF_OPENSSL_SUCCESS) {
105         HcfPrintOpensslError();
106         Openssl_EVP_PKEY_CTX_free(ctx);
107         HcfFree(secretData);
108         return HCF_ERR_CRYPTO_OPERATION;
109     }
110     Openssl_EVP_PKEY_CTX_free(ctx);
111     if (actualLen > maxLen) {
112         LOGE("signature data too long.");
113         HcfFree(secretData);
114         return HCF_ERR_CRYPTO_OPERATION;
115     }
116 
117     returnSecret->data = secretData;
118     returnSecret->len = actualLen;
119     return HCF_SUCCESS;
120 }
121 
GetEcdhClass(void)122 static const char *GetEcdhClass(void)
123 {
124     return "HcfKeyAgreement.HcfKeyAgreementSpiEcdhOpensslImpl";
125 }
126 
DestroyEcdh(HcfObjectBase * self)127 static void DestroyEcdh(HcfObjectBase *self)
128 {
129     if (self == NULL) {
130         return;
131     }
132     if (!IsClassMatch(self, GetEcdhClass())) {
133         return;
134     }
135     HcfFree(self);
136 }
137 
EngineGenerateSecret(HcfKeyAgreementSpi * self,HcfPriKey * priKey,HcfPubKey * pubKey,HcfBlob * returnSecret)138 static HcfResult EngineGenerateSecret(HcfKeyAgreementSpi *self, HcfPriKey *priKey,
139     HcfPubKey *pubKey, HcfBlob *returnSecret)
140 {
141     if ((self == NULL) || (priKey == NULL) || (pubKey == NULL) || (returnSecret == NULL)) {
142         LOGE("Invalid input parameter.");
143         return HCF_INVALID_PARAMS;
144     }
145     if ((!IsClassMatch((HcfObjectBase *)self, GetEcdhClass())) ||
146         (!IsClassMatch((HcfObjectBase *)priKey, HCF_OPENSSL_ECC_PRI_KEY_CLASS)) ||
147         (!IsClassMatch((HcfObjectBase *)pubKey, HCF_OPENSSL_ECC_PUB_KEY_CLASS))) {
148         return HCF_INVALID_PARAMS;
149     }
150 
151     EVP_PKEY *priPKey = NewPKeyByEccPriKey((HcfOpensslEccPriKey *)priKey);
152     if (priPKey == NULL) {
153         LOGE("Gen EVP_PKEY priKey failed");
154         return HCF_ERR_CRYPTO_OPERATION;
155     }
156     EVP_PKEY *pubPKey = NewPKeyByEccPubKey((HcfOpensslEccPubKey *)pubKey);
157     if (pubPKey == NULL) {
158         LOGE("Gen EVP_PKEY pubKey failed");
159         EVP_PKEY_free(priPKey);
160         return HCF_ERR_CRYPTO_OPERATION;
161     }
162 
163     HcfResult res = EcdhDerive(priPKey, pubPKey, returnSecret);
164     Openssl_EVP_PKEY_free(priPKey);
165     Openssl_EVP_PKEY_free(pubPKey);
166     return res;
167 }
168 
HcfKeyAgreementSpiEcdhCreate(HcfKeyAgreementParams * params,HcfKeyAgreementSpi ** returnObj)169 HcfResult HcfKeyAgreementSpiEcdhCreate(HcfKeyAgreementParams *params, HcfKeyAgreementSpi **returnObj)
170 {
171     if ((params == NULL) || (returnObj == NULL)) {
172         LOGE("Invalid input parameter.");
173         return HCF_INVALID_PARAMS;
174     }
175 
176     HcfKeyAgreementSpiEcdhOpensslImpl *returnImpl = (HcfKeyAgreementSpiEcdhOpensslImpl *)HcfMalloc(
177         sizeof(HcfKeyAgreementSpiEcdhOpensslImpl), 0);
178     if (returnImpl == NULL) {
179         LOGE("Failed to allocate returnImpl memroy!");
180         return HCF_ERR_MALLOC;
181     }
182     returnImpl->base.base.getClass = GetEcdhClass;
183     returnImpl->base.base.destroy = DestroyEcdh;
184     returnImpl->base.engineGenerateSecret = EngineGenerateSecret;
185 
186     *returnObj = (HcfKeyAgreementSpi *)returnImpl;
187     return HCF_SUCCESS;
188 }
189