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