1/*
2 * Copyright (C) 2022-2023 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 "md.h"
17
18#include <securec.h>
19
20#include "sym_key.h"
21#include "md_spi.h"
22#ifdef CRYPTO_MBEDTLS
23#include "mbedtls_md.h"
24#else
25#include "md_openssl.h"
26#endif
27
28#include "log.h"
29#include "config.h"
30#include "memory.h"
31#include "utils.h"
32
33typedef HcfResult (*HcfMdSpiCreateFunc)(const char *, HcfMdSpi **);
34
35typedef struct {
36    HcfMd base;
37
38    HcfMdSpi *spiObj;
39
40    char algoName[HCF_MAX_ALGO_NAME_LEN];
41} HcfMdImpl;
42
43typedef struct {
44    char *algoName;
45
46    HcfMdSpiCreateFunc createSpiFunc;
47} HcfMdAbility;
48
49static const HcfMdAbility MD_ABILITY_SET[] = {
50#ifdef CRYPTO_MBEDTLS
51    { "SHA1", MbedtlsMdSpiCreate },
52    { "SHA256", MbedtlsMdSpiCreate },
53    { "SHA512", MbedtlsMdSpiCreate },
54    { "MD5", MbedtlsMdSpiCreate },
55#else
56    { "SHA1", OpensslMdSpiCreate },
57    { "SHA224", OpensslMdSpiCreate },
58    { "SHA256", OpensslMdSpiCreate },
59    { "SHA384", OpensslMdSpiCreate },
60    { "SHA512", OpensslMdSpiCreate },
61    { "MD5", OpensslMdSpiCreate },
62    { "SM3", OpensslMdSpiCreate },
63#endif
64};
65
66static const char *GetMdClass(void)
67{
68    return "Md";
69}
70
71static HcfMdSpiCreateFunc FindAbility(const char *algoName)
72{
73    for (uint32_t i = 0; i < (sizeof(MD_ABILITY_SET) / sizeof(MD_ABILITY_SET[0])); i++) {
74        if (strcmp(MD_ABILITY_SET[i].algoName, algoName) == 0) {
75            return MD_ABILITY_SET[i].createSpiFunc;
76        }
77    }
78    LOGE("Algo not support! [Algo]: %s", algoName);
79    return NULL;
80}
81
82static HcfResult Update(HcfMd *self, HcfBlob *input)
83{
84    if ((self == NULL) || (!HcfIsBlobValid(input))) {
85        LOGE("The input self ptr or dataBlob is NULL!");
86        return HCF_INVALID_PARAMS;
87    }
88    if (!HcfIsClassMatch((HcfObjectBase *)self, GetMdClass())) {
89        LOGE("Class is not match.");
90        return HCF_INVALID_PARAMS;
91    }
92    return ((HcfMdImpl *)self)->spiObj->engineUpdateMd(
93        ((HcfMdImpl *)self)->spiObj, input);
94}
95
96static HcfResult DoFinal(HcfMd *self, HcfBlob *output)
97{
98    if ((self == NULL) || (output == NULL)) {
99        LOGE("The input self ptr or dataBlob is NULL!");
100        return HCF_INVALID_PARAMS;
101    }
102    if (!HcfIsClassMatch((HcfObjectBase *)self, GetMdClass())) {
103        LOGE("Class is not match.");
104        return HCF_INVALID_PARAMS;
105    }
106    return ((HcfMdImpl *)self)->spiObj->engineDoFinalMd(
107        ((HcfMdImpl *)self)->spiObj, output);
108}
109
110static uint32_t GetMdLength(HcfMd *self)
111{
112    if (self == NULL) {
113        LOGE("The input self ptr is NULL!");
114        return 0;
115    }
116    if (!HcfIsClassMatch((HcfObjectBase *)self, GetMdClass())) {
117        LOGE("Class is not match.");
118        return 0;
119    }
120    return ((HcfMdImpl *)self)->spiObj->engineGetMdLength(
121        ((HcfMdImpl *)self)->spiObj);
122}
123
124static const char *GetAlgoName(HcfMd *self)
125{
126    if (self == NULL) {
127        LOGE("The input self ptr is NULL!");
128        return NULL;
129    }
130    if (!HcfIsClassMatch((HcfObjectBase *)self, GetMdClass())) {
131        LOGE("Class is not match.");
132        return NULL;
133    }
134    return ((HcfMdImpl *)self)->algoName;
135}
136
137static void MdDestroy(HcfObjectBase *self)
138{
139    if (self == NULL) {
140        LOGE("The input self ptr is NULL!");
141        return;
142    }
143    if (!HcfIsClassMatch((HcfObjectBase *)self, GetMdClass())) {
144        LOGE("Class is not match.");
145        return;
146    }
147    HcfMdImpl *impl = (HcfMdImpl *)self;
148    HcfObjDestroy(impl->spiObj);
149    HcfFree(impl);
150}
151
152HcfResult HcfMdCreate(const char *algoName, HcfMd **md)
153{
154    if (!HcfIsStrValid(algoName, HCF_MAX_ALGO_NAME_LEN) || (md == NULL)) {
155        LOGE("Invalid input params while creating md!");
156        return HCF_INVALID_PARAMS;
157    }
158    HcfMdSpiCreateFunc createSpiFunc = FindAbility(algoName);
159    if (createSpiFunc == NULL) {
160        LOGE("Algo name is error!");
161        return HCF_INVALID_PARAMS;
162    }
163    HcfMdImpl *returnMdApi = (HcfMdImpl *)HcfMalloc(sizeof(HcfMdImpl), 0);
164    if (returnMdApi == NULL) {
165        LOGE("Failed to allocate Md Obj memory!");
166        return HCF_ERR_MALLOC;
167    }
168    if (strcpy_s(returnMdApi->algoName, HCF_MAX_ALGO_NAME_LEN, algoName) != EOK) {
169        LOGE("Failed to copy algoName!");
170        HcfFree(returnMdApi);
171        return HCF_INVALID_PARAMS;
172    }
173    HcfMdSpi *spiObj = NULL;
174    HcfResult res = createSpiFunc(algoName, &spiObj);
175    if (res != HCF_SUCCESS) {
176        LOGE("Failed to create spi object!");
177        HcfFree(returnMdApi);
178        return res;
179    }
180    returnMdApi->base.base.getClass = GetMdClass;
181    returnMdApi->base.base.destroy = MdDestroy;
182    returnMdApi->base.update = Update;
183    returnMdApi->base.doFinal = DoFinal;
184    returnMdApi->base.getMdLength = GetMdLength;
185    returnMdApi->base.getAlgoName = GetAlgoName;
186    returnMdApi->spiObj = spiObj;
187    *md = (HcfMd *)returnMdApi;
188    return HCF_SUCCESS;
189}