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, ¶ms->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