1 /*
2 * Copyright (C) 2023-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 "mac_openssl.h"
17
18 #include "openssl_adapter.h"
19 #include "sym_common_defines.h"
20 #include "openssl_common.h"
21 #include "securec.h"
22 #include "log.h"
23 #include "memory.h"
24 #include "config.h"
25 #include "utils.h"
26 #include "detailed_hmac_params.h"
27 #include "detailed_cmac_params.h"
28
29 typedef struct {
30 HcfMacSpi base;
31
32 HMAC_CTX *ctx;
33
34 char opensslMdName[HCF_MAX_MD_NAME_LEN];
35 } HcfHmacSpiImpl;
36
37 typedef struct {
38 HcfMacSpi base;
39
40 EVP_MAC_CTX *ctx;
41
42 char opensslCipherName[HCF_MAX_CIPHER_NAME_LEN];
43 } HcfCmacSpiImpl;
44
OpensslGetHmacClass(void)45 static const char *OpensslGetHmacClass(void)
46 {
47 return "OpensslHmac";
48 }
49
OpensslGetCmacClass(void)50 static const char *OpensslGetCmacClass(void)
51 {
52 return "OpensslCmac";
53 }
54
OpensslGetHmacCtx(HcfMacSpi * self)55 static HMAC_CTX *OpensslGetHmacCtx(HcfMacSpi *self)
56 {
57 if (!HcfIsClassMatch((HcfObjectBase *)self, OpensslGetHmacClass())) {
58 LOGE("Class is not match.");
59 return NULL;
60 }
61 return ((HcfHmacSpiImpl *)self)->ctx;
62 }
63
OpensslGetCmacCtx(HcfMacSpi * self)64 static EVP_MAC_CTX *OpensslGetCmacCtx(HcfMacSpi *self)
65 {
66 if (!HcfIsClassMatch((HcfObjectBase *)self, OpensslGetCmacClass())) {
67 LOGE("Class is not match.");
68 return NULL;
69 }
70 return ((HcfCmacSpiImpl *)self)->ctx;
71 }
72
OpensslGetHmacAlgoFromString(const char * mdName)73 static const EVP_MD *OpensslGetHmacAlgoFromString(const char *mdName)
74 {
75 if (strcmp(mdName, "SHA1") == 0) {
76 return OpensslEvpSha1();
77 } else if (strcmp(mdName, "SHA224") == 0) {
78 return OpensslEvpSha224();
79 } else if (strcmp(mdName, "SHA256") == 0) {
80 return OpensslEvpSha256();
81 } else if (strcmp(mdName, "SHA384") == 0) {
82 return OpensslEvpSha384();
83 } else if (strcmp(mdName, "SHA512") == 0) {
84 return OpensslEvpSha512();
85 } else if (strcmp(mdName, "SM3") == 0) {
86 return OpensslEvpSm3();
87 } else if (strcmp(mdName, "MD5") == 0) {
88 return OpensslEvpMd5();
89 }
90 return NULL;
91 }
92
OpensslEngineInitHmac(HcfMacSpi * self,const HcfSymKey * key)93 static HcfResult OpensslEngineInitHmac(HcfMacSpi *self, const HcfSymKey *key)
94 {
95 if (OpensslGetHmacCtx(self) == NULL) {
96 LOGD("[error] The CTX is NULL!");
97 return HCF_ERR_CRYPTO_OPERATION;
98 }
99 if (!HcfIsClassMatch((const HcfObjectBase *)key, OPENSSL_SYM_KEY_CLASS)) {
100 LOGE("Class is not match.");
101 return HCF_INVALID_PARAMS;
102 }
103 if (!HcfIsClassMatch((HcfObjectBase *)self, OpensslGetHmacClass())) {
104 LOGE("Class is not match.");
105 return HCF_INVALID_PARAMS;
106 }
107 HcfBlob keyBlob = ((SymKeyImpl *)key)->keyMaterial;
108 if (!HcfIsBlobValid(&keyBlob)) {
109 LOGE("Invalid keyMaterial");
110 return HCF_INVALID_PARAMS;
111 }
112 const EVP_MD *mdfunc = OpensslGetHmacAlgoFromString(((HcfHmacSpiImpl *)self)->opensslMdName);
113 int32_t ret = OpensslHmacInitEx(OpensslGetHmacCtx(self), keyBlob.data, keyBlob.len, mdfunc, NULL);
114 if (ret != HCF_OPENSSL_SUCCESS) {
115 LOGD("[error] HMAC_Init_ex return error!");
116 HcfPrintOpensslError();
117 return HCF_ERR_CRYPTO_OPERATION;
118 }
119 return HCF_SUCCESS;
120 }
121
OpensslEngineUpdateHmac(HcfMacSpi * self,HcfBlob * input)122 static HcfResult OpensslEngineUpdateHmac(HcfMacSpi *self, HcfBlob *input)
123 {
124 if (OpensslGetHmacCtx(self) == NULL) {
125 LOGD("[error] The CTX is NULL!");
126 return HCF_ERR_CRYPTO_OPERATION;
127 }
128 if (HMAC_Update(OpensslGetHmacCtx(self), input->data, input->len) != HCF_OPENSSL_SUCCESS) {
129 LOGD("[error] HMAC_Update return error!");
130 HcfPrintOpensslError();
131 return HCF_ERR_CRYPTO_OPERATION;
132 }
133 return HCF_SUCCESS;
134 }
135
OpensslEngineDoFinalHmac(HcfMacSpi * self,HcfBlob * output)136 static HcfResult OpensslEngineDoFinalHmac(HcfMacSpi *self, HcfBlob *output)
137 {
138 if (OpensslGetHmacCtx(self) == NULL) {
139 LOGD("[error] The CTX is NULL!");
140 return HCF_ERR_CRYPTO_OPERATION;
141 }
142 unsigned char outputBuf[EVP_MAX_MD_SIZE];
143 uint32_t outputLen;
144 int32_t ret = OpensslHmacFinal(OpensslGetHmacCtx(self), outputBuf, &outputLen);
145 if (ret != HCF_OPENSSL_SUCCESS) {
146 LOGD("[error] HMAC_Final return error!");
147 HcfPrintOpensslError();
148 return HCF_ERR_CRYPTO_OPERATION;
149 }
150 output->data = (uint8_t *)HcfMalloc(outputLen, 0);
151 if (output->data == NULL) {
152 LOGE("Failed to allocate output->data memory!");
153 return HCF_ERR_MALLOC;
154 }
155 (void)memcpy_s(output->data, outputLen, outputBuf, outputLen);
156 output->len = outputLen;
157 return HCF_SUCCESS;
158 }
159
OpensslEngineGetHmacLength(HcfMacSpi * self)160 static uint32_t OpensslEngineGetHmacLength(HcfMacSpi *self)
161 {
162 if (OpensslGetHmacCtx(self) == NULL) {
163 LOGD("[error] The CTX is NULL!");
164 return HCF_OPENSSL_INVALID_MAC_LEN;
165 }
166 return OpensslHmacSize(OpensslGetHmacCtx(self));
167 }
168
OpensslDestroyHmac(HcfObjectBase * self)169 static void OpensslDestroyHmac(HcfObjectBase *self)
170 {
171 if (self == NULL) {
172 LOGE("Self ptr is NULL");
173 return;
174 }
175 if (!HcfIsClassMatch(self, OpensslGetHmacClass())) {
176 LOGE("Class is not match.");
177 return;
178 }
179 if (OpensslGetHmacCtx((HcfMacSpi *)self) != NULL) {
180 OpensslHmacCtxFree(OpensslGetHmacCtx((HcfMacSpi *)self));
181 }
182 HcfFree(self);
183 }
184
OpensslHmacSpiCreate(HcfMacParamsSpec * paramsSpec,HcfMacSpi ** spiObj)185 HcfResult OpensslHmacSpiCreate(HcfMacParamsSpec *paramsSpec, HcfMacSpi **spiObj)
186 {
187 if (paramsSpec == NULL || spiObj == NULL) {
188 LOGE("Invalid input parameter.");
189 return HCF_INVALID_PARAMS;
190 }
191 HcfHmacSpiImpl *returnSpiImpl = (HcfHmacSpiImpl *)HcfMalloc(sizeof(HcfHmacSpiImpl), 0);
192 if (returnSpiImpl == NULL) {
193 LOGE("Failed to allocate returnImpl memory!");
194 return HCF_ERR_MALLOC;
195 }
196 if (strcpy_s(returnSpiImpl->opensslMdName, HCF_MAX_MD_NAME_LEN, ((HcfHmacParamsSpec *)paramsSpec)->mdName) != EOK) {
197 LOGE("Failed to copy algoName!");
198 HcfFree(returnSpiImpl);
199 returnSpiImpl = NULL;
200 return HCF_INVALID_PARAMS;
201 }
202 returnSpiImpl->ctx = OpensslHmacCtxNew();
203 if (returnSpiImpl->ctx == NULL) {
204 LOGD("[error] Failed to create ctx!");
205 HcfFree(returnSpiImpl);
206 returnSpiImpl = NULL;
207 return HCF_ERR_CRYPTO_OPERATION;
208 }
209 returnSpiImpl->base.base.getClass = OpensslGetHmacClass;
210 returnSpiImpl->base.base.destroy = OpensslDestroyHmac;
211 returnSpiImpl->base.engineInitMac = OpensslEngineInitHmac;
212 returnSpiImpl->base.engineUpdateMac = OpensslEngineUpdateHmac;
213 returnSpiImpl->base.engineDoFinalMac = OpensslEngineDoFinalHmac;
214 returnSpiImpl->base.engineGetMacLength = OpensslEngineGetHmacLength;
215 *spiObj = (HcfMacSpi *)returnSpiImpl;
216 return HCF_SUCCESS;
217 }
218
OpensslEngineInitCmac(HcfMacSpi * self,const HcfSymKey * key)219 static HcfResult OpensslEngineInitCmac(HcfMacSpi *self, const HcfSymKey *key)
220 {
221 OSSL_PARAM params[4] = {};
222 OSSL_PARAM *p = params;
223 if (OpensslGetCmacCtx(self) == NULL) {
224 LOGD("[error] The CTX is NULL!");
225 return HCF_ERR_CRYPTO_OPERATION;
226 }
227 if (!HcfIsClassMatch((const HcfObjectBase *)key, OPENSSL_SYM_KEY_CLASS)) {
228 LOGE("Class is not match.");
229 return HCF_INVALID_PARAMS;
230 }
231 if (!HcfIsClassMatch((HcfObjectBase *)self, OpensslGetCmacClass())) {
232 LOGE("Class is not match.");
233 return HCF_INVALID_PARAMS;
234 }
235 HcfBlob keyBlob = ((SymKeyImpl *)key)->keyMaterial;
236 if (!HcfIsBlobValid(&keyBlob)) {
237 LOGE("Invalid keyMaterial");
238 return HCF_INVALID_PARAMS;
239 }
240 *p++ = OpensslOsslParamConstructUtf8String("cipher", ((HcfCmacSpiImpl *)self)->opensslCipherName,
241 strlen(((HcfCmacSpiImpl *)self)->opensslCipherName));
242 *p++ = OpensslOsslParamConstructEnd();
243 int32_t ret = OpensslCmacInit(OpensslGetCmacCtx(self), keyBlob.data, keyBlob.len, params);
244 if (ret != HCF_OPENSSL_SUCCESS) {
245 LOGE("CMAC_Init return error!");
246 HcfPrintOpensslError();
247 return HCF_ERR_CRYPTO_OPERATION;
248 }
249 return HCF_SUCCESS;
250 }
251
OpensslEngineUpdateCmac(HcfMacSpi * self,HcfBlob * input)252 static HcfResult OpensslEngineUpdateCmac(HcfMacSpi *self, HcfBlob *input)
253 {
254 if (OpensslGetCmacCtx(self) == NULL) {
255 LOGE("The CTX is NULL!");
256 return HCF_ERR_CRYPTO_OPERATION;
257 }
258 if (OpensslCmacUpdate(OpensslGetCmacCtx(self), input->data, input->len) != HCF_OPENSSL_SUCCESS) {
259 LOGE("CMAC_Update return error!");
260 HcfPrintOpensslError();
261 return HCF_ERR_CRYPTO_OPERATION;
262 }
263 return HCF_SUCCESS;
264 }
265
OpensslEngineDoFinalCmac(HcfMacSpi * self,HcfBlob * output)266 static HcfResult OpensslEngineDoFinalCmac(HcfMacSpi *self, HcfBlob *output)
267 {
268 if (OpensslGetCmacCtx(self) == NULL) {
269 LOGE("The CTX is NULL!");
270 return HCF_ERR_CRYPTO_OPERATION;
271 }
272 size_t outputLen = 0;
273 unsigned char outputBuf[EVP_MAX_MD_SIZE];
274 int32_t ret = OpensslCmacFinal(OpensslGetCmacCtx(self), NULL, &outputLen, 0);
275 if (ret != HCF_OPENSSL_SUCCESS) {
276 LOGE("CMAC_Final return error!");
277 HcfPrintOpensslError();
278 return HCF_ERR_CRYPTO_OPERATION;
279 }
280 ret = OpensslCmacFinal(OpensslGetCmacCtx(self), outputBuf, &outputLen, outputLen);
281 if (ret != HCF_OPENSSL_SUCCESS) {
282 LOGE("CMAC_Final return error!");
283 HcfPrintOpensslError();
284 return HCF_ERR_CRYPTO_OPERATION;
285 }
286 output->data = (uint8_t *)HcfMalloc(outputLen, 0);
287 if (output->data == NULL) {
288 LOGE("Failed to allocate output->data memory!");
289 return HCF_ERR_MALLOC;
290 }
291 (void)memcpy_s(output->data, outputLen, outputBuf, outputLen);
292 output->len = outputLen;
293 return HCF_SUCCESS;
294 }
295
OpensslEngineGetCmacLength(HcfMacSpi * self)296 static uint32_t OpensslEngineGetCmacLength(HcfMacSpi *self)
297 {
298 if (OpensslGetCmacCtx(self) == NULL) {
299 LOGE("The CTX is NULL!");
300 return HCF_OPENSSL_INVALID_MAC_LEN;
301 }
302 return OpensslCmacSize(OpensslGetCmacCtx(self));
303 }
304
OpensslDestroyCmac(HcfObjectBase * self)305 static void OpensslDestroyCmac(HcfObjectBase *self)
306 {
307 if (self == NULL) {
308 LOGE("Self ptr is NULL");
309 return;
310 }
311 if (!HcfIsClassMatch(self, OpensslGetCmacClass())) {
312 LOGE("Class is not match.");
313 return;
314 }
315 if (OpensslGetCmacCtx((HcfMacSpi *)self) != NULL) {
316 OpensslCmacCtxFree(OpensslGetCmacCtx((HcfMacSpi *)self));
317 }
318 HcfFree(self);
319 }
320
OpensslCmacSpiCreate(HcfMacParamsSpec * paramsSpec,HcfMacSpi ** spiObj)321 HcfResult OpensslCmacSpiCreate(HcfMacParamsSpec *paramsSpec, HcfMacSpi **spiObj)
322 {
323 if (paramsSpec == NULL || spiObj == NULL) {
324 LOGE("Invalid input parameter.");
325 return HCF_INVALID_PARAMS;
326 }
327 HcfCmacSpiImpl *returnSpiImpl = (HcfCmacSpiImpl *)HcfMalloc(sizeof(HcfCmacSpiImpl), 0);
328 if (returnSpiImpl == NULL) {
329 LOGE("Failed to allocate returnImpl memory!");
330 return HCF_ERR_MALLOC;
331 }
332 if (strcpy_s(returnSpiImpl->opensslCipherName, HCF_MAX_CIPHER_NAME_LEN,
333 ((HcfCmacParamsSpec *)paramsSpec)->cipherName) != EOK) {
334 LOGE("Failed to copy algoName!");
335 HcfFree(returnSpiImpl);
336 returnSpiImpl = NULL;
337 return HCF_INVALID_PARAMS;
338 }
339 EVP_MAC *mac = EVP_MAC_fetch(NULL, "CMAC", NULL);
340 if (mac == NULL) {
341 LOGE("fetch failed");
342 HcfFree(returnSpiImpl);
343 returnSpiImpl = NULL;
344 return HCF_ERR_CRYPTO_OPERATION;
345 }
346 returnSpiImpl->ctx = EVP_MAC_CTX_new(mac);
347 if (returnSpiImpl->ctx == NULL) {
348 LOGD("[error] Failed to create ctx!");
349 HcfFree(returnSpiImpl);
350 returnSpiImpl = NULL;
351 OpensslMacFree(mac);
352 return HCF_ERR_CRYPTO_OPERATION;
353 }
354 OpensslMacFree(mac);
355 returnSpiImpl->base.base.getClass = OpensslGetCmacClass;
356 returnSpiImpl->base.base.destroy = OpensslDestroyCmac;
357 returnSpiImpl->base.engineInitMac = OpensslEngineInitCmac;
358 returnSpiImpl->base.engineUpdateMac = OpensslEngineUpdateCmac;
359 returnSpiImpl->base.engineDoFinalMac = OpensslEngineDoFinalCmac;
360 returnSpiImpl->base.engineGetMacLength = OpensslEngineGetCmacLength;
361 *spiObj = (HcfMacSpi *)returnSpiImpl;
362 return HCF_SUCCESS;
363 }