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 "key_agreement.h"
17 
18 #include <securec.h>
19 
20 #include "key_agreement_spi.h"
21 #include "config.h"
22 #include "dh_openssl.h"
23 #include "ecdh_openssl.h"
24 #include "x25519_openssl.h"
25 #include "log.h"
26 #include "memory.h"
27 #include "params_parser.h"
28 #include "utils.h"
29 
30 typedef HcfResult (*HcfKeyAgreementSpiCreateFunc)(HcfKeyAgreementParams *, HcfKeyAgreementSpi **);
31 
32 typedef struct {
33     HcfKeyAgreement base;
34 
35     HcfKeyAgreementSpi *spiObj;
36 
37     char algoName[HCF_MAX_ALGO_NAME_LEN];
38 } HcfKeyAgreementImpl;
39 
40 typedef struct {
41     HcfAlgValue algo;
42 
43     HcfKeyAgreementSpiCreateFunc createSpiFunc;
44 } HcfKeyAgreementGenAbility;
45 
46 static const HcfKeyAgreementGenAbility KEY_AGREEMENT_GEN_ABILITY_SET[] = {
47     { HCF_ALG_ECC, HcfKeyAgreementSpiEcdhCreate },
48     { HCF_ALG_X25519, HcfKeyAgreementSpiX25519Create },
49     { HCF_ALG_DH, HcfKeyAgreementSpiDhCreate }
50 };
51 
FindAbility(HcfKeyAgreementParams * params)52 static HcfKeyAgreementSpiCreateFunc FindAbility(HcfKeyAgreementParams *params)
53 {
54     for (uint32_t i = 0; i < sizeof(KEY_AGREEMENT_GEN_ABILITY_SET) / sizeof(KEY_AGREEMENT_GEN_ABILITY_SET[0]); i++) {
55         if (KEY_AGREEMENT_GEN_ABILITY_SET[i].algo == params->algo) {
56             return KEY_AGREEMENT_GEN_ABILITY_SET[i].createSpiFunc;
57         }
58     }
59     LOGE("Algo not support! [Algo]: %d", params->algo);
60     return NULL;
61 }
62 
SetKeyType(HcfAlgParaValue value,HcfKeyAgreementParams * paramsObj)63 static void SetKeyType(HcfAlgParaValue value, HcfKeyAgreementParams *paramsObj)
64 {
65     switch (value) {
66         case HCF_ALG_ECC_224:
67         case HCF_ALG_ECC_256:
68         case HCF_ALG_ECC_384:
69         case HCF_ALG_ECC_521:
70         case HCF_ALG_ECC_BP160R1:
71         case HCF_ALG_ECC_BP160T1:
72         case HCF_ALG_ECC_BP192R1:
73         case HCF_ALG_ECC_BP192T1:
74         case HCF_ALG_ECC_BP224R1:
75         case HCF_ALG_ECC_BP224T1:
76         case HCF_ALG_ECC_BP256R1:
77         case HCF_ALG_ECC_BP256T1:
78         case HCF_ALG_ECC_BP320R1:
79         case HCF_ALG_ECC_BP320T1:
80         case HCF_ALG_ECC_BP384R1:
81         case HCF_ALG_ECC_BP384T1:
82         case HCF_ALG_ECC_BP512R1:
83         case HCF_ALG_ECC_BP512T1:
84         case HCF_ALG_ECC_SECP256K1:
85             paramsObj->algo = HCF_ALG_ECC;
86             break;
87         case HCF_ALG_X25519_256:
88             paramsObj->algo = HCF_ALG_X25519;
89             break;
90         case HCF_OPENSSL_DH_MODP_1536:
91         case HCF_OPENSSL_DH_MODP_2048:
92         case HCF_OPENSSL_DH_MODP_3072:
93         case HCF_OPENSSL_DH_MODP_4096:
94         case HCF_OPENSSL_DH_MODP_6144:
95         case HCF_OPENSSL_DH_MODP_8192:
96         case HCF_OPENSSL_DH_FFDHE_2048:
97         case HCF_OPENSSL_DH_FFDHE_3072:
98         case HCF_OPENSSL_DH_FFDHE_4096:
99         case HCF_OPENSSL_DH_FFDHE_6144:
100         case HCF_OPENSSL_DH_FFDHE_8192:
101             paramsObj->algo = HCF_ALG_DH;
102             break;
103         default:
104             LOGE("Invalid algo %u.", value);
105             break;
106     }
107 }
108 
SetKeyTypeDefault(HcfAlgParaValue value,HcfKeyAgreementParams * paramsObj)109 static void SetKeyTypeDefault(HcfAlgParaValue value,  HcfKeyAgreementParams *paramsObj)
110 {
111     switch (value) {
112         case HCF_ALG_ECC_DEFAULT:
113             paramsObj->algo = HCF_ALG_ECC;
114             break;
115         case HCF_ALG_X25519_DEFAULT:
116             paramsObj->algo = HCF_ALG_X25519;
117             break;
118         case HCF_ALG_DH_DEFAULT:
119             paramsObj->algo = HCF_ALG_DH;
120             break;
121         default:
122             LOGE("Invalid algo %u.", value);
123             break;
124     }
125 }
126 
ParseKeyAgreementParams(const HcfParaConfig * config,void * params)127 static HcfResult ParseKeyAgreementParams(const HcfParaConfig *config, void *params)
128 {
129     if (config == NULL || params == NULL) {
130         LOGE("Invalid key agreement params");
131         return HCF_INVALID_PARAMS;
132     }
133     HcfResult ret = HCF_SUCCESS;
134     HcfKeyAgreementParams *paramsObj = (HcfKeyAgreementParams *)params;
135     LOGD("Set Parameter: %s", config->tag);
136     switch (config->paraType) {
137         case HCF_ALG_TYPE:
138             SetKeyTypeDefault(config->paraValue, paramsObj);
139             break;
140         case HCF_ALG_KEY_TYPE:
141             SetKeyType(config->paraValue, paramsObj);
142             break;
143         default:
144             ret = HCF_INVALID_PARAMS;
145             break;
146     }
147     return ret;
148 }
149 
150 // export interfaces
GetKeyAgreementClass(void)151 static const char *GetKeyAgreementClass(void)
152 {
153     return "HcfKeyAgreement";
154 }
155 
GetAlgoName(HcfKeyAgreement * self)156 static const char *GetAlgoName(HcfKeyAgreement *self)
157 {
158     if (self == NULL) {
159         LOGE("The input self ptr is NULL!");
160         return NULL;
161     }
162     if (!HcfIsClassMatch((HcfObjectBase *)self, GetKeyAgreementClass())) {
163         return NULL;
164     }
165     return ((HcfKeyAgreementImpl *)self)->algoName;
166 }
167 
GenerateSecret(HcfKeyAgreement * self,HcfPriKey * priKey,HcfPubKey * pubKey,HcfBlob * returnSecret)168 static HcfResult GenerateSecret(HcfKeyAgreement *self, HcfPriKey *priKey,
169     HcfPubKey *pubKey, HcfBlob *returnSecret)
170 {
171     if (self == NULL) {
172         LOGE("Invalid input parameter.");
173         return HCF_INVALID_PARAMS;
174     }
175     if (!HcfIsClassMatch((HcfObjectBase *)self, GetKeyAgreementClass())) {
176         return HCF_INVALID_PARAMS;
177     }
178 
179     return ((HcfKeyAgreementImpl *)self)->spiObj->engineGenerateSecret(
180         ((HcfKeyAgreementImpl *)self)->spiObj, priKey, pubKey, returnSecret);
181 }
182 
DestroyKeyAgreement(HcfObjectBase * self)183 static void DestroyKeyAgreement(HcfObjectBase *self)
184 {
185     if (self == NULL) {
186         return;
187     }
188     if (!HcfIsClassMatch((HcfObjectBase *)self, GetKeyAgreementClass())) {
189         return;
190     }
191     HcfKeyAgreementImpl *impl = (HcfKeyAgreementImpl *)self;
192     HcfObjDestroy(impl->spiObj);
193     impl->spiObj = NULL;
194     HcfFree(impl);
195 }
196 
HcfKeyAgreementCreate(const char * algoName,HcfKeyAgreement ** returnObj)197 HcfResult HcfKeyAgreementCreate(const char *algoName, HcfKeyAgreement **returnObj)
198 {
199     if ((!HcfIsStrValid(algoName, HCF_MAX_ALGO_NAME_LEN)) || (returnObj == NULL)) {
200         return HCF_INVALID_PARAMS;
201     }
202 
203     HcfKeyAgreementParams params = { 0 };
204     if (ParseAndSetParameter(algoName, &params, ParseKeyAgreementParams) != HCF_SUCCESS) {
205         LOGE("Failed to parse params!");
206         return HCF_INVALID_PARAMS;
207     }
208 
209     HcfKeyAgreementSpiCreateFunc createSpiFunc = FindAbility(&params);
210     if (createSpiFunc == NULL) {
211         return HCF_NOT_SUPPORT;
212     }
213 
214     HcfKeyAgreementImpl *returnGenerator = (HcfKeyAgreementImpl *)HcfMalloc(sizeof(HcfKeyAgreementImpl), 0);
215     if (returnGenerator == NULL) {
216         LOGE("Failed to allocate returnGenerator memory!");
217         return HCF_ERR_MALLOC;
218     }
219     if (strcpy_s(returnGenerator->algoName, HCF_MAX_ALGO_NAME_LEN, algoName) != EOK) {
220         LOGE("Failed to copy algoName!");
221         HcfFree(returnGenerator);
222         return HCF_INVALID_PARAMS;
223     }
224     HcfKeyAgreementSpi *spiObj = NULL;
225     HcfResult res = createSpiFunc(&params, &spiObj);
226     if (res != HCF_SUCCESS) {
227         LOGE("Failed to create spi object!");
228         HcfFree(returnGenerator);
229         return res;
230     }
231     returnGenerator->base.base.destroy = DestroyKeyAgreement;
232     returnGenerator->base.base.getClass = GetKeyAgreementClass;
233     returnGenerator->base.generateSecret = GenerateSecret;
234     returnGenerator->base.getAlgoName = GetAlgoName;
235     returnGenerator->spiObj = spiObj;
236 
237     *returnObj = (HcfKeyAgreement *)returnGenerator;
238     return HCF_SUCCESS;
239 }
240