• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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 "hkdf_openssl.h"
17 
18 #include "log.h"
19 #include "memory.h"
20 #include "result.h"
21 #include "securec.h"
22 #include "utils.h"
23 #include "openssl_adapter.h"
24 #include "openssl_common.h"
25 #include "openssl/kdf.h"
26 #include "detailed_hkdf_params.h"
27 
28 #define HKDF_ALG_NAME "HKDF"
29 
30 typedef struct {
31     unsigned char *salt;
32     int saltLen;
33     unsigned char *key;
34     int keyLen;
35     unsigned char *info;
36     int infoLen;
37     unsigned char *out;
38     int outLen;
39 } HcfHkdfData;
40 
41 typedef struct {
42     HcfKdfSpi base;
43     int digestAlg;
44     int mode;
45     HcfHkdfData *kdfData;
46 } OpensslHkdfSpiImpl;
47 
EngineGetKdfClass(void)48 static const char *EngineGetKdfClass(void)
49 {
50     return "OpensslHkdf";
51 }
52 
HcfClearAndFree(unsigned char * buf,int bufLen)53 static void HcfClearAndFree(unsigned char *buf, int bufLen)
54 {
55     // when buf == null, bufLen must be 0; in check func, bufLen >= 0
56     if (buf == NULL) {
57         return;
58     }
59     (void)memset_s(buf, bufLen, 0, bufLen);
60     HcfFree(buf);
61 }
62 
FreeHkdfData(HcfHkdfData ** data)63 static void FreeHkdfData(HcfHkdfData **data)
64 {
65     if (data == NULL || *data == NULL) {
66         return;
67     }
68     HcfClearAndFree((*data)->out, (*data)->outLen);
69     (*data)->out = NULL;
70     (*data)->outLen = 0;
71     HcfClearAndFree((*data)->salt, (*data)->saltLen);
72     (*data)->salt = NULL;
73     (*data)->saltLen = 0;
74     HcfClearAndFree((*data)->info, (*data)->infoLen);
75     (*data)->info = NULL;
76     (*data)->infoLen = 0;
77     HcfClearAndFree((*data)->key, (*data)->keyLen);
78     (*data)->key = NULL;
79     (*data)->keyLen = 0;
80     (void)memset_s(*data, sizeof(HcfHkdfData), 0, sizeof(HcfHkdfData));
81     HcfFree(*data);
82     *data = NULL;
83 }
84 
EngineDestroyKdf(HcfObjectBase * self)85 static void EngineDestroyKdf(HcfObjectBase *self)
86 {
87     if (self == NULL) {
88         LOGE("Self ptr is NULL!");
89         return;
90     }
91     if (!HcfIsClassMatch(self, EngineGetKdfClass())) {
92         LOGE("Class is not match.");
93         return;
94     }
95     OpensslHkdfSpiImpl *impl = (OpensslHkdfSpiImpl *)self;
96     FreeHkdfData(&(impl->kdfData));
97     HcfFree(self);
98 }
99 
CheckHkdfParams(HcfHkdfParamsSpec * params)100 static bool CheckHkdfParams(HcfHkdfParamsSpec *params)
101 {
102     // openssl only support INT and blob attribute is size_t, it should samller than INT_MAX.
103     if (params->output.len > INT_MAX || params->salt.len > INT_MAX || params->key.len > INT_MAX ||
104         params->info.len > INT_MAX) {
105             LOGE("beyond the length");
106             return false;
107     }
108     if (params->key.data == NULL && params->key.len == 0) {
109         LOGE("check params failed, key is NULL");
110         return false;
111     }
112     if (params->output.data == NULL || params->output.len == 0) {
113         LOGE("check params failed, output data is NULL");
114         return false;
115     }
116     if (params->salt.data == NULL && params->salt.len == 0) {
117         LOGD("empty salt");
118     }
119     if (params->info.data == NULL && params->info.len == 0) {
120         LOGD("empty info");
121     }
122     return true;
123 }
124 
GetHkdfKeyFromSpec(HcfHkdfData * data,HcfHkdfParamsSpec * params)125 static bool GetHkdfKeyFromSpec(HcfHkdfData *data, HcfHkdfParamsSpec *params)
126 {
127     data->key = (unsigned char *)HcfMalloc(params->key.len, 0);
128     if (data->key == NULL) {
129         return false;
130     }
131     (void)memcpy_s(data->key, params->key.len, params->key.data, params->key.len);
132     data->keyLen = params->key.len;
133     return true;
134 }
135 
GetHkdfMode(OpensslHkdfSpiImpl * self)136 static int GetHkdfMode(OpensslHkdfSpiImpl *self)
137 {
138     switch (self->mode) {
139         case HCF_ALG_MODE_EXTRACT_AND_EXPAND:
140             return EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND;
141         case HCF_ALG_MODE_EXTRACT_ONLY:
142             return EVP_KDF_HKDF_MODE_EXTRACT_ONLY;
143         case HCF_ALG_MODE_EXPAND_ONLY:
144             return EVP_KDF_HKDF_MODE_EXPAND_ONLY;
145         default:
146             return EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND;
147     }
148 }
149 
GetHkdfInfoFromSpec(OpensslHkdfSpiImpl * self,HcfHkdfData * data,HcfHkdfParamsSpec * params)150 static bool GetHkdfInfoFromSpec(OpensslHkdfSpiImpl *self, HcfHkdfData *data, HcfHkdfParamsSpec *params)
151 {
152     if (self->mode == HCF_ALG_MODE_EXTRACT_ONLY) {
153         LOGD("EXTRACT_ONLY mode does not require info");
154         return true;
155     }
156 
157     if (params->info.len == 0) {
158         LOGD("info can be empty.");
159         return true;
160     }
161 
162     data->info = (unsigned char *)HcfMalloc(params->info.len, 0);
163     if (data->info == NULL) {
164         return false;
165     }
166     (void)memcpy_s(data->info, params->info.len, params->info.data, params->info.len);
167     data->infoLen = params->info.len;
168     return true;
169 }
170 
GetHkdfSaltFromSpec(OpensslHkdfSpiImpl * self,HcfHkdfData * data,HcfHkdfParamsSpec * params)171 static bool GetHkdfSaltFromSpec(OpensslHkdfSpiImpl *self, HcfHkdfData *data, HcfHkdfParamsSpec *params)
172 {
173     if (self->mode == HCF_ALG_MODE_EXPAND_ONLY) {
174         LOGD("EXPAND_ONLY mode does not require salt");
175         return true;
176     }
177 
178     if (params->salt.len == 0) {
179         LOGD("salt can be empty.");
180         return true;
181     }
182 
183     data->salt = (unsigned char *)HcfMalloc(params->salt.len, 0);
184     if (data->salt == NULL) {
185         return false;
186     }
187     (void)memcpy_s(data->salt, params->salt.len, params->salt.data, params->salt.len);
188     data->saltLen = params->salt.len;
189     return true;
190 }
191 
InitHkdfData(OpensslHkdfSpiImpl * self,HcfHkdfParamsSpec * params)192 static HcfResult InitHkdfData(OpensslHkdfSpiImpl *self, HcfHkdfParamsSpec *params)
193 {
194     LOGD("MODE IS %d", self->mode);
195     HcfHkdfData *data = (HcfHkdfData *)HcfMalloc(sizeof(HcfHkdfData), 0);
196     do {
197         if (data == NULL) {
198             LOGE("malloc data failed");
199             break;
200         }
201         if (!GetHkdfKeyFromSpec(data, params)) {
202             LOGE("malloc key failed!");
203             break;
204         }
205         if (!GetHkdfSaltFromSpec(self, data, params)) {
206             LOGE("malloc salt failed!");
207             break;
208         }
209         if (!GetHkdfInfoFromSpec(self, data, params)) {
210             LOGE("malloc info failed!");
211             break;
212         }
213         data->out = (unsigned char *)HcfMalloc(params->output.len, 0);
214         if (data->out == NULL) {
215             LOGE("malloc out failed!");
216             break;
217         }
218         data->outLen = params->output.len;
219         self->kdfData = data;
220         return HCF_SUCCESS;
221     } while (0);
222     FreeHkdfData(&data);
223     return HCF_ERR_MALLOC;
224 }
225 
SwitchMd(OpensslHkdfSpiImpl * self)226 static char *SwitchMd(OpensslHkdfSpiImpl *self)
227 {
228     switch (self->digestAlg) {
229         case HCF_OPENSSL_DIGEST_NONE:
230             return "";
231         case HCF_OPENSSL_DIGEST_MD5:
232             return "MD5";
233         case HCF_OPENSSL_DIGEST_SM3:
234             return "SM3";
235         case HCF_OPENSSL_DIGEST_SHA1:
236             return "SHA1";
237         case HCF_OPENSSL_DIGEST_SHA224:
238             return "SHA224";
239         case HCF_OPENSSL_DIGEST_SHA256:
240             return "SHA256";
241         case HCF_OPENSSL_DIGEST_SHA384:
242             return "SHA384";
243         case HCF_OPENSSL_DIGEST_SHA512:
244             return "SHA512";
245         default:
246             return "";
247     }
248 }
249 
OpensslHkdf(OpensslHkdfSpiImpl * self,HcfBlob * output)250 static HcfResult OpensslHkdf(OpensslHkdfSpiImpl *self, HcfBlob *output)
251 {
252     EVP_KDF *kdf = NULL;
253     EVP_KDF_CTX *kctx = NULL;
254     // need set 6 params
255     OSSL_PARAM params[6] = {};
256     OSSL_PARAM *p = params;
257 
258     kdf = OpensslEvpKdfFetch(NULL, "HKDF", NULL);
259     if (kdf == NULL) {
260         LOGE("kdf fetch failed");
261         return HCF_ERR_CRYPTO_OPERATION;
262     }
263 
264     kctx = OpensslEvpKdfCtxNew(kdf);
265     OpensslEvpKdfFree(kdf);
266     if (kctx == NULL) {
267         LOGE("kdf ctx new failed");
268         return HCF_ERR_CRYPTO_OPERATION;
269     }
270 
271     int mode = GetHkdfMode(self);
272     char *digest = SwitchMd(self);
273     *p++ = OpensslOsslParamConstructUtf8String("digest", digest, 0);
274     *p++ = OpensslOsslParamConstructOctetString("key", self->kdfData->key, self->kdfData->keyLen);
275     *p++ = OpensslOsslParamConstructOctetString("info", self->kdfData->info, self->kdfData->infoLen);
276     *p++ = OpensslOsslParamConstructOctetString("salt", self->kdfData->salt, self->kdfData->saltLen);
277     *p++ = OpensslOsslParamConstructInt("mode", &mode);
278     *p = OpensslOsslParamConstructEnd();
279     if (OpensslEvpKdfDerive(kctx, output->data, output->len, params) <= 0) {
280         HcfPrintOpensslError();
281         LOGE("EVP_KDF_derive failed");
282         OpensslEvpKdfCtxFree(kctx);
283         return HCF_ERR_CRYPTO_OPERATION;
284     }
285     OpensslEvpKdfCtxFree(kctx);
286     return HCF_SUCCESS;
287 }
288 
EngineGenerateSecret(HcfKdfSpi * self,HcfKdfParamsSpec * paramsSpec)289 static HcfResult EngineGenerateSecret(HcfKdfSpi *self, HcfKdfParamsSpec *paramsSpec)
290 {
291     if (self == NULL || paramsSpec == NULL) {
292         LOGE("Invalid input parameter.");
293         return HCF_INVALID_PARAMS;
294     }
295     if (!HcfIsClassMatch((HcfObjectBase *)self, EngineGetKdfClass())) {
296         return HCF_INVALID_PARAMS;
297     }
298     OpensslHkdfSpiImpl *hkdfImpl = (OpensslHkdfSpiImpl *)self;
299     if (paramsSpec->algName == NULL || strcmp(paramsSpec->algName, HKDF_ALG_NAME) != 0) {
300         LOGE("Not hkdf paramsSpec");
301         return HCF_INVALID_PARAMS;
302     }
303     HcfHkdfParamsSpec *params = (HcfHkdfParamsSpec *)paramsSpec;
304     if (!CheckHkdfParams(params)) {
305         LOGE("params error");
306         return HCF_INVALID_PARAMS;
307     }
308     HcfResult res = InitHkdfData(hkdfImpl, params);
309     if (res != HCF_SUCCESS) {
310         LOGE("InitCipherData failed!");
311         return res;
312     }
313     res = OpensslHkdf(hkdfImpl, &params->output);
314     FreeHkdfData(&(hkdfImpl->kdfData));
315     return res;
316 }
317 
HcfKdfHkdfSpiCreate(HcfKdfDeriveParams * params,HcfKdfSpi ** spiObj)318 HcfResult HcfKdfHkdfSpiCreate(HcfKdfDeriveParams *params, HcfKdfSpi **spiObj)
319 {
320     if (params == NULL || spiObj == NULL) {
321         LOGE("Invalid input parameter.");
322         return HCF_INVALID_PARAMS;
323     }
324     OpensslHkdfSpiImpl *returnSpiImpl = (OpensslHkdfSpiImpl *)HcfMalloc(sizeof(OpensslHkdfSpiImpl), 0);
325     if (returnSpiImpl == NULL) {
326         LOGE("Failed to allocate returnImpl memory!");
327         return HCF_ERR_MALLOC;
328     }
329     returnSpiImpl->base.base.getClass = EngineGetKdfClass;
330     returnSpiImpl->base.base.destroy = EngineDestroyKdf;
331     returnSpiImpl->base.generateSecret = EngineGenerateSecret;
332     returnSpiImpl->digestAlg = params->md;
333     returnSpiImpl->mode = params->mode;
334     *spiObj = (HcfKdfSpi *)returnSpiImpl;
335     return HCF_SUCCESS;
336 }
337