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