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 
27 typedef struct {
28     HcfMacSpi base;
29 
30     HMAC_CTX *ctx;
31 
32     char opensslAlgoName[HCF_MAX_ALGO_NAME_LEN];
33 } HcfMacSpiImpl;
34 
OpensslGetMacClass(void)35 static const char *OpensslGetMacClass(void)
36 {
37     return "OpensslMac";
38 }
39 
OpensslGetMacCtx(HcfMacSpi * self)40 static HMAC_CTX *OpensslGetMacCtx(HcfMacSpi *self)
41 {
42     if (!HcfIsClassMatch((HcfObjectBase *)self, OpensslGetMacClass())) {
43         LOGE("Class is not match.");
44         return NULL;
45     }
46     return ((HcfMacSpiImpl *)self)->ctx;
47 }
48 
OpensslGetMacAlgoFromString(const char * mdName)49 static const EVP_MD *OpensslGetMacAlgoFromString(const char *mdName)
50 {
51     if (strcmp(mdName, "SHA1") == 0) {
52         return OpensslEvpSha1();
53     } else if (strcmp(mdName, "SHA224") == 0) {
54         return OpensslEvpSha224();
55     } else if (strcmp(mdName, "SHA256") == 0) {
56         return OpensslEvpSha256();
57     } else if (strcmp(mdName, "SHA384") == 0) {
58         return OpensslEvpSha384();
59     } else if (strcmp(mdName, "SHA512") == 0) {
60         return OpensslEvpSha512();
61     } else if (strcmp(mdName, "SM3") == 0) {
62         return OpensslEvpSm3();
63     } else if (strcmp(mdName, "MD5") == 0) {
64         return OpensslEvpMd5();
65     }
66     return NULL;
67 }
68 
OpensslEngineInitMac(HcfMacSpi * self,const HcfSymKey * key)69 static HcfResult OpensslEngineInitMac(HcfMacSpi *self, const HcfSymKey *key)
70 {
71     if (OpensslGetMacCtx(self) == NULL) {
72         LOGD("[error] The CTX is NULL!");
73         return HCF_ERR_CRYPTO_OPERATION;
74     }
75     if (!HcfIsClassMatch((const HcfObjectBase *)key, OPENSSL_SYM_KEY_CLASS)) {
76         LOGE("Class is not match.");
77         return HCF_INVALID_PARAMS;
78     }
79     if (!HcfIsClassMatch((HcfObjectBase *)self, OpensslGetMacClass())) {
80         LOGE("Class is not match.");
81         return HCF_INVALID_PARAMS;
82     }
83     HcfBlob keyBlob = ((SymKeyImpl *)key)->keyMaterial;
84     if (!HcfIsBlobValid(&keyBlob)) {
85         LOGE("Invalid keyMaterial");
86         return HCF_INVALID_PARAMS;
87     }
88     const EVP_MD *mdfunc = OpensslGetMacAlgoFromString(((HcfMacSpiImpl *)self)->opensslAlgoName);
89     int32_t ret = OpensslHmacInitEx(OpensslGetMacCtx(self), keyBlob.data, keyBlob.len, mdfunc, NULL);
90     if (ret != HCF_OPENSSL_SUCCESS) {
91         LOGD("[error] HMAC_Init_ex return error!");
92         HcfPrintOpensslError();
93         return HCF_ERR_CRYPTO_OPERATION;
94     }
95     return HCF_SUCCESS;
96 }
97 
OpensslEngineUpdateMac(HcfMacSpi * self,HcfBlob * input)98 static HcfResult OpensslEngineUpdateMac(HcfMacSpi *self, HcfBlob *input)
99 {
100     if (OpensslGetMacCtx(self) == NULL) {
101         LOGD("[error] The CTX is NULL!");
102         return HCF_ERR_CRYPTO_OPERATION;
103     }
104     if (HMAC_Update(OpensslGetMacCtx(self), input->data, input->len) != HCF_OPENSSL_SUCCESS) {
105         LOGD("[error] HMAC_Update return error!");
106         HcfPrintOpensslError();
107         return HCF_ERR_CRYPTO_OPERATION;
108     }
109     return HCF_SUCCESS;
110 }
111 
OpensslEngineDoFinalMac(HcfMacSpi * self,HcfBlob * output)112 static HcfResult OpensslEngineDoFinalMac(HcfMacSpi *self, HcfBlob *output)
113 {
114     if (OpensslGetMacCtx(self) == NULL) {
115         LOGD("[error] The CTX is NULL!");
116         return HCF_ERR_CRYPTO_OPERATION;
117     }
118     unsigned char outputBuf[EVP_MAX_MD_SIZE];
119     uint32_t outputLen;
120     int32_t ret = OpensslHmacFinal(OpensslGetMacCtx(self), outputBuf, &outputLen);
121     if (ret != HCF_OPENSSL_SUCCESS) {
122         LOGD("[error] HMAC_Final return error!");
123         HcfPrintOpensslError();
124         return HCF_ERR_CRYPTO_OPERATION;
125     }
126     output->data = (uint8_t *)HcfMalloc(outputLen, 0);
127     if (output->data == NULL) {
128         LOGE("Failed to allocate output->data memory!");
129         return HCF_ERR_MALLOC;
130     }
131     (void)memcpy_s(output->data, outputLen, outputBuf, outputLen);
132     output->len = outputLen;
133     return HCF_SUCCESS;
134 }
135 
OpensslEngineGetMacLength(HcfMacSpi * self)136 static uint32_t OpensslEngineGetMacLength(HcfMacSpi *self)
137 {
138     if (OpensslGetMacCtx(self) == NULL) {
139         LOGD("[error] The CTX is NULL!");
140         return HCF_OPENSSL_INVALID_MAC_LEN;
141     }
142     return OpensslHmacSize(OpensslGetMacCtx(self));
143 }
144 
OpensslDestroyMac(HcfObjectBase * self)145 static void OpensslDestroyMac(HcfObjectBase *self)
146 {
147     if (self == NULL) {
148         LOGE("Self ptr is NULL");
149         return;
150     }
151     if (!HcfIsClassMatch(self, OpensslGetMacClass())) {
152         LOGE("Class is not match.");
153         return;
154     }
155     if (OpensslGetMacCtx((HcfMacSpi *)self) != NULL) {
156         OpensslHmacCtxFree(OpensslGetMacCtx((HcfMacSpi *)self));
157     }
158     HcfFree(self);
159 }
160 
OpensslMacSpiCreate(const char * opensslAlgoName,HcfMacSpi ** spiObj)161 HcfResult OpensslMacSpiCreate(const char *opensslAlgoName, HcfMacSpi **spiObj)
162 {
163     if (spiObj == NULL) {
164         LOGE("Invalid input parameter.");
165         return HCF_INVALID_PARAMS;
166     }
167     HcfMacSpiImpl *returnSpiImpl = (HcfMacSpiImpl *)HcfMalloc(sizeof(HcfMacSpiImpl), 0);
168     if (returnSpiImpl == NULL) {
169         LOGE("Failed to allocate returnImpl memory!");
170         return HCF_ERR_MALLOC;
171     }
172     if (strcpy_s(returnSpiImpl->opensslAlgoName, HCF_MAX_ALGO_NAME_LEN, opensslAlgoName) != EOK) {
173         LOGE("Failed to copy algoName!");
174         HcfFree(returnSpiImpl);
175         return HCF_INVALID_PARAMS;
176     }
177     returnSpiImpl->ctx = OpensslHmacCtxNew();
178     if (returnSpiImpl->ctx == NULL) {
179         LOGD("[error] Failed to create ctx!");
180         HcfFree(returnSpiImpl);
181         return HCF_ERR_CRYPTO_OPERATION;
182     }
183     returnSpiImpl->base.base.getClass = OpensslGetMacClass;
184     returnSpiImpl->base.base.destroy = OpensslDestroyMac;
185     returnSpiImpl->base.engineInitMac = OpensslEngineInitMac;
186     returnSpiImpl->base.engineUpdateMac = OpensslEngineUpdateMac;
187     returnSpiImpl->base.engineDoFinalMac = OpensslEngineDoFinalMac;
188     returnSpiImpl->base.engineGetMacLength = OpensslEngineGetMacLength;
189     *spiObj = (HcfMacSpi *)returnSpiImpl;
190     return HCF_SUCCESS;
191 }