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 "mbedtls_md.h"
17
18 #include "mbedtls_common.h"
19 #include "mbedtls/md.h"
20 #include "securec.h"
21 #include "log.h"
22 #include "memory.h"
23 #include "config.h"
24 #include "utils.h"
25
26 typedef struct {
27 HcfMdSpi base;
28 mbedtls_md_context_t *ctx;
29 char mbedtlsAlgoName[HCF_MAX_ALGO_NAME_LEN];
30 } MbedtlsMdSpiImpl;
31
MbedtlsEvpMdCtxNew(void)32 mbedtls_md_context_t *MbedtlsEvpMdCtxNew(void)
33 {
34 return (mbedtls_md_context_t *)HcfMalloc(sizeof(mbedtls_md_context_t), 0);
35 }
36
MbedtlsEvpMdCtxFree(mbedtls_md_context_t * ctx)37 void MbedtlsEvpMdCtxFree(mbedtls_md_context_t *ctx)
38 {
39 HcfFree(ctx);
40 }
41
MbedtlsGetMdClass(void)42 static const char *MbedtlsGetMdClass(void)
43 {
44 return "MbedtlsMd";
45 }
46
MbedtlsGetMdCtx(HcfMdSpi * self)47 static mbedtls_md_context_t *MbedtlsGetMdCtx(HcfMdSpi *self)
48 {
49 if (!HcfIsClassMatch((HcfObjectBase *)self, MbedtlsGetMdClass())) {
50 LOGE("Class is not match.");
51 return NULL;
52 }
53
54 return ((MbedtlsMdSpiImpl *)self)->ctx;
55 }
56
MbedtlsEngineUpdateMd(HcfMdSpi * self,HcfBlob * input)57 static HcfResult MbedtlsEngineUpdateMd(HcfMdSpi *self, HcfBlob *input)
58 {
59 mbedtls_md_context_t *ctx = MbedtlsGetMdCtx(self);
60 if (ctx == NULL) {
61 LOGD("The CTX is NULL!");
62 return HCF_INVALID_PARAMS;
63 }
64 int32_t ret = mbedtls_md_update(ctx, (const unsigned char *)input->data, input->len);
65 if (ret != HCF_MBEDTLS_SUCCESS) {
66 LOGD("EVP_DigestUpdate return error %d!", ret);
67 return HCF_ERR_CRYPTO_OPERATION;
68 }
69
70 return HCF_SUCCESS;
71 }
72
MbedtlsEngineDoFinalMd(HcfMdSpi * self,HcfBlob * output)73 static HcfResult MbedtlsEngineDoFinalMd(HcfMdSpi *self, HcfBlob *output)
74 {
75 if ((self == NULL) || (output == NULL)) {
76 LOGE("The input self ptr is NULL!");
77 return HCF_INVALID_PARAMS;
78 }
79 mbedtls_md_context_t *ctx = MbedtlsGetMdCtx(self);
80 if (ctx == NULL) {
81 LOGE("The CTX is NULL!");
82 return HCF_INVALID_PARAMS;
83 }
84 unsigned char outputBuf[HCF_EVP_MAX_MD_SIZE] = { 0 };
85 uint8_t outputLen = mbedtls_md_get_size(mbedtls_md_info_from_ctx(ctx));
86 if (outputLen == 0) {
87 LOGD("Failed to md get size is 0!");
88 return HCF_ERR_CRYPTO_OPERATION;
89 }
90 int32_t ret = mbedtls_md_finish(ctx, outputBuf);
91 if (ret != HCF_MBEDTLS_SUCCESS) {
92 LOGD("Failed to md finish return error is %d!", ret);
93 return HCF_ERR_CRYPTO_OPERATION;
94 }
95 output->data = (uint8_t *)HcfMalloc(outputLen, 0);
96 if (output->data == NULL) {
97 LOGE("Failed to allocate output->data memory!");
98 return HCF_ERR_MALLOC;
99 }
100 (void)memcpy_s(output->data, outputLen, outputBuf, outputLen);
101 output->len = outputLen;
102
103 return HCF_SUCCESS;
104 }
105
MbedtlsEngineGetMdLength(HcfMdSpi * self)106 static uint32_t MbedtlsEngineGetMdLength(HcfMdSpi *self)
107 {
108 mbedtls_md_context_t *ctx = MbedtlsGetMdCtx(self);
109 if (ctx == NULL) {
110 LOGD("The CTX is NULL!");
111 return HCF_MBEDTLS_INVALID_MD_LEN;
112 }
113 uint8_t outputLen = mbedtls_md_get_size(mbedtls_md_info_from_ctx(ctx));
114 if ((outputLen == 0) || (outputLen > HCF_EVP_MAX_MD_SIZE)) {
115 LOGD("Get the overflow path length is %d in mbedtls!", outputLen);
116 return HCF_MBEDTLS_INVALID_MD_LEN;
117 }
118
119 return outputLen;
120 }
121
MbedtlsDestroyMd(HcfObjectBase * self)122 static void MbedtlsDestroyMd(HcfObjectBase *self)
123 {
124 if (self == NULL) {
125 LOGE("The input self ptr is NULL!");
126 return;
127 }
128 if (!HcfIsClassMatch(self, MbedtlsGetMdClass())) {
129 LOGE("Class is not match.");
130 return;
131 }
132 if (MbedtlsGetMdCtx((HcfMdSpi *)self) != NULL) {
133 mbedtls_md_free(MbedtlsGetMdCtx((HcfMdSpi *)self));
134 MbedtlsEvpMdCtxFree(MbedtlsGetMdCtx((HcfMdSpi *)self));
135 }
136 HcfFree(self);
137 }
138
139 typedef struct {
140 char *mdAlg;
141 mbedtls_md_type_t mdType;
142 } MdAlgTypeMap;
143
144 static MdAlgTypeMap g_mdAlgMap[] = {
145 { "MD5", MBEDTLS_MD_MD5 },
146 { "SHA1", MBEDTLS_MD_SHA1 },
147 { "SHA256", MBEDTLS_MD_SHA256 },
148 { "SHA512", MBEDTLS_MD_SHA512 },
149 };
150
MbedtlsEvpDigestInitEx(mbedtls_md_context_t * ctx,const char * mbedtlsAlgoName)151 int MbedtlsEvpDigestInitEx(mbedtls_md_context_t *ctx, const char *mbedtlsAlgoName)
152 {
153 for (uint32_t index = 0; index < sizeof(g_mdAlgMap) / sizeof(g_mdAlgMap[0]); index++) {
154 if (strcmp(g_mdAlgMap[index].mdAlg, mbedtlsAlgoName) == 0) {
155 mbedtls_md_init(ctx);
156 mbedtls_md_setup(ctx, mbedtls_md_info_from_type(g_mdAlgMap[index].mdType), 0);
157 mbedtls_md_starts(ctx);
158 return HCF_MBEDTLS_SUCCESS;
159 }
160 }
161
162 return HCF_MBEDTLS_FAILURE;
163 }
164
MbedtlsMdSpiCreate(const char * mbedtlsAlgoName,HcfMdSpi ** spiObj)165 HcfResult MbedtlsMdSpiCreate(const char *mbedtlsAlgoName, HcfMdSpi **spiObj)
166 {
167 if (spiObj == NULL) {
168 LOGE("Invalid input parameter.");
169 return HCF_INVALID_PARAMS;
170 }
171 MbedtlsMdSpiImpl *returnSpiImpl = (MbedtlsMdSpiImpl *)HcfMalloc(sizeof(MbedtlsMdSpiImpl), 0);
172 if (returnSpiImpl == NULL) {
173 LOGE("Failed to allocate returnImpl memory!");
174 return HCF_ERR_MALLOC;
175 }
176 returnSpiImpl->ctx = MbedtlsEvpMdCtxNew();
177 if (returnSpiImpl->ctx == NULL) {
178 LOGE("Failed to create ctx!");
179 HcfFree(returnSpiImpl);
180 returnSpiImpl = NULL;
181 return HCF_ERR_MALLOC;
182 }
183 int32_t ret = MbedtlsEvpDigestInitEx(returnSpiImpl->ctx, mbedtlsAlgoName);
184 if (ret != HCF_MBEDTLS_SUCCESS) {
185 LOGD("Failed to init MD ret is %d!", ret);
186 MbedtlsEvpMdCtxFree(returnSpiImpl->ctx);
187 returnSpiImpl->ctx = NULL;
188 HcfFree(returnSpiImpl);
189 returnSpiImpl = NULL;
190 return HCF_ERR_CRYPTO_OPERATION;
191 }
192 returnSpiImpl->base.base.getClass = MbedtlsGetMdClass;
193 returnSpiImpl->base.base.destroy = MbedtlsDestroyMd;
194 returnSpiImpl->base.engineUpdateMd = MbedtlsEngineUpdateMd;
195 returnSpiImpl->base.engineDoFinalMd = MbedtlsEngineDoFinalMd;
196 returnSpiImpl->base.engineGetMdLength = MbedtlsEngineGetMdLength;
197 *spiObj = (HcfMdSpi *)returnSpiImpl;
198
199 return HCF_SUCCESS;
200 }
201