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             paramsObj->algo = HCF_ALG_ECC;
85             break;
86         case HCF_ALG_X25519_256:
87             paramsObj->algo = HCF_ALG_X25519;
88             break;
89         case HCF_OPENSSL_DH_MODP_1536:
90         case HCF_OPENSSL_DH_MODP_2048:
91         case HCF_OPENSSL_DH_MODP_3072:
92         case HCF_OPENSSL_DH_MODP_4096:
93         case HCF_OPENSSL_DH_MODP_6144:
94         case HCF_OPENSSL_DH_MODP_8192:
95         case HCF_OPENSSL_DH_FFDHE_2048:
96         case HCF_OPENSSL_DH_FFDHE_3072:
97         case HCF_OPENSSL_DH_FFDHE_4096:
98         case HCF_OPENSSL_DH_FFDHE_6144:
99         case HCF_OPENSSL_DH_FFDHE_8192:
100             paramsObj->algo = HCF_ALG_DH;
101             break;
102         default:
103             LOGE("Invalid algo %u.", value);
104             break;
105     }
106 }
107 
SetKeyTypeDefault(HcfAlgParaValue value, HcfKeyAgreementParams *paramsObj)108 static void SetKeyTypeDefault(HcfAlgParaValue value,  HcfKeyAgreementParams *paramsObj)
109 {
110     switch (value) {
111         case HCF_ALG_ECC_DEFAULT:
112             paramsObj->algo = HCF_ALG_ECC;
113             break;
114         case HCF_ALG_X25519_DEFAULT:
115             paramsObj->algo = HCF_ALG_X25519;
116             break;
117         case HCF_ALG_DH_DEFAULT:
118             paramsObj->algo = HCF_ALG_DH;
119             break;
120         default:
121             LOGE("Invalid algo %u.", value);
122             break;
123     }
124 }
125 
ParseKeyAgreementParams(const HcfParaConfig *config, void *params)126 static HcfResult ParseKeyAgreementParams(const HcfParaConfig *config, void *params)
127 {
128     if (config == NULL || params == NULL) {
129         LOGE("Invalid key agreement params");
130         return HCF_INVALID_PARAMS;
131     }
132     HcfResult ret = HCF_SUCCESS;
133     HcfKeyAgreementParams *paramsObj = (HcfKeyAgreementParams *)params;
134     LOGD("Set Parameter: %s", config->tag);
135     switch (config->paraType) {
136         case HCF_ALG_TYPE:
137             SetKeyTypeDefault(config->paraValue, paramsObj);
138             break;
139         case HCF_ALG_KEY_TYPE:
140             SetKeyType(config->paraValue, paramsObj);
141             break;
142         default:
143             ret = HCF_INVALID_PARAMS;
144             break;
145     }
146     return ret;
147 }
148 
149 // export interfaces
GetKeyAgreementClass(void)150 static const char *GetKeyAgreementClass(void)
151 {
152     return "HcfKeyAgreement";
153 }
154 
GetAlgoName(HcfKeyAgreement *self)155 static const char *GetAlgoName(HcfKeyAgreement *self)
156 {
157     if (self == NULL) {
158         LOGE("The input self ptr is NULL!");
159         return NULL;
160     }
161     if (!HcfIsClassMatch((HcfObjectBase *)self, GetKeyAgreementClass())) {
162         return NULL;
163     }
164     return ((HcfKeyAgreementImpl *)self)->algoName;
165 }
166 
GenerateSecret(HcfKeyAgreement *self, HcfPriKey *priKey, HcfPubKey *pubKey, HcfBlob *returnSecret)167 static HcfResult GenerateSecret(HcfKeyAgreement *self, HcfPriKey *priKey,
168     HcfPubKey *pubKey, HcfBlob *returnSecret)
169 {
170     if (self == NULL) {
171         LOGE("Invalid input parameter.");
172         return HCF_INVALID_PARAMS;
173     }
174     if (!HcfIsClassMatch((HcfObjectBase *)self, GetKeyAgreementClass())) {
175         return HCF_INVALID_PARAMS;
176     }
177 
178     return ((HcfKeyAgreementImpl *)self)->spiObj->engineGenerateSecret(
179         ((HcfKeyAgreementImpl *)self)->spiObj, priKey, pubKey, returnSecret);
180 }
181 
DestroyKeyAgreement(HcfObjectBase *self)182 static void DestroyKeyAgreement(HcfObjectBase *self)
183 {
184     if (self == NULL) {
185         return;
186     }
187     if (!HcfIsClassMatch((HcfObjectBase *)self, GetKeyAgreementClass())) {
188         return;
189     }
190     HcfKeyAgreementImpl *impl = (HcfKeyAgreementImpl *)self;
191     HcfObjDestroy(impl->spiObj);
192     impl->spiObj = NULL;
193     HcfFree(impl);
194 }
195 
HcfKeyAgreementCreate(const char *algoName, HcfKeyAgreement **returnObj)196 HcfResult HcfKeyAgreementCreate(const char *algoName, HcfKeyAgreement **returnObj)
197 {
198     if ((!HcfIsStrValid(algoName, HCF_MAX_ALGO_NAME_LEN)) || (returnObj == NULL)) {
199         return HCF_INVALID_PARAMS;
200     }
201 
202     HcfKeyAgreementParams params = { 0 };
203     if (ParseAndSetParameter(algoName, &params, ParseKeyAgreementParams) != HCF_SUCCESS) {
204         LOGE("Failed to parse params!");
205         return HCF_INVALID_PARAMS;
206     }
207 
208     HcfKeyAgreementSpiCreateFunc createSpiFunc = FindAbility(&params);
209     if (createSpiFunc == NULL) {
210         return HCF_NOT_SUPPORT;
211     }
212 
213     HcfKeyAgreementImpl *returnGenerator = (HcfKeyAgreementImpl *)HcfMalloc(sizeof(HcfKeyAgreementImpl), 0);
214     if (returnGenerator == NULL) {
215         LOGE("Failed to allocate returnGenerator memory!");
216         return HCF_ERR_MALLOC;
217     }
218     if (strcpy_s(returnGenerator->algoName, HCF_MAX_ALGO_NAME_LEN, algoName) != EOK) {
219         LOGE("Failed to copy algoName!");
220         HcfFree(returnGenerator);
221         return HCF_INVALID_PARAMS;
222     }
223     HcfKeyAgreementSpi *spiObj = NULL;
224     HcfResult res = createSpiFunc(&params, &spiObj);
225     if (res != HCF_SUCCESS) {
226         LOGE("Failed to create spi object!");
227         HcfFree(returnGenerator);
228         return res;
229     }
230     returnGenerator->base.base.destroy = DestroyKeyAgreement;
231     returnGenerator->base.base.getClass = GetKeyAgreementClass;
232     returnGenerator->base.generateSecret = GenerateSecret;
233     returnGenerator->base.getAlgoName = GetAlgoName;
234     returnGenerator->spiObj = spiObj;
235 
236     *returnObj = (HcfKeyAgreement *)returnGenerator;
237     return HCF_SUCCESS;
238 }
239