1 /*
2  * Copyright (C) 2022 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_openssl.h"
17 
18 #include "openssl_adapter.h"
19 #include "openssl_common.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 
29     EVP_MD_CTX *ctx;
30 
31     char opensslAlgoName[HCF_MAX_ALGO_NAME_LEN];
32 } OpensslMdSpiImpl;
33 
OpensslGetMdClass(void)34 static const char *OpensslGetMdClass(void)
35 {
36     return "OpensslMd";
37 }
38 
OpensslGetMdCtx(HcfMdSpi * self)39 static EVP_MD_CTX *OpensslGetMdCtx(HcfMdSpi *self)
40 {
41     if (!HcfIsClassMatch((HcfObjectBase *)self, OpensslGetMdClass())) {
42         LOGE("Class is not match.");
43         return NULL;
44     }
45     return ((OpensslMdSpiImpl *)self)->ctx;
46 }
47 
OpensslGetMdAlgoFromString(const char * mdName)48 static const EVP_MD *OpensslGetMdAlgoFromString(const char *mdName)
49 {
50     if (strcmp(mdName, "SHA1") == 0) {
51         return OpensslEvpSha1();
52     } else if (strcmp(mdName, "SHA224") == 0) {
53         return OpensslEvpSha224();
54     } else if (strcmp(mdName, "SHA256") == 0) {
55         return OpensslEvpSha256();
56     } else if (strcmp(mdName, "SHA384") == 0) {
57         return OpensslEvpSha384();
58     } else if (strcmp(mdName, "SHA512") == 0) {
59         return OpensslEvpSha512();
60     } else if (strcmp(mdName, "MD5") == 0) {
61         return OpensslEvpMd5();
62     } else if (strcmp(mdName, "SM3") == 0) {
63         return OpensslEvpSm3();
64     }
65     return NULL;
66 }
67 
OpensslEngineUpdateMd(HcfMdSpi * self,HcfBlob * input)68 static HcfResult OpensslEngineUpdateMd(HcfMdSpi *self, HcfBlob *input)
69 {
70     if (input == NULL) {
71         LOGE("The input is NULL!");
72         return HCF_INVALID_PARAMS;
73     }
74     if (OpensslGetMdCtx(self) == NULL) {
75         LOGD("[error] The CTX is NULL!");
76         return HCF_ERR_CRYPTO_OPERATION;
77     }
78     if (EVP_DigestUpdate(OpensslGetMdCtx(self), input->data, input->len) != HCF_OPENSSL_SUCCESS) {
79         LOGD("[error] EVP_DigestUpdate return error!");
80         HcfPrintOpensslError();
81         return HCF_ERR_CRYPTO_OPERATION;
82     }
83     return HCF_SUCCESS;
84 }
85 
OpensslEngineDoFinalMd(HcfMdSpi * self,HcfBlob * output)86 static HcfResult OpensslEngineDoFinalMd(HcfMdSpi *self, HcfBlob *output)
87 {
88     if (output == NULL) {
89         LOGE("The output is NULL!");
90         return HCF_INVALID_PARAMS;
91     }
92     EVP_MD_CTX *localCtx = OpensslGetMdCtx(self);
93     if (localCtx == NULL) {
94         LOGE("The CTX is NULL!");
95         return HCF_ERR_CRYPTO_OPERATION;
96     }
97     unsigned char outputBuf[EVP_MAX_MD_SIZE];
98     uint32_t outputLen;
99     int32_t ret = OpensslEvpDigestFinalEx(localCtx, outputBuf, &outputLen);
100     if (ret != HCF_OPENSSL_SUCCESS) {
101         LOGD("[error] EVP_DigestFinal_ex return error!");
102         HcfPrintOpensslError();
103         return HCF_ERR_CRYPTO_OPERATION;
104     }
105     output->data = (uint8_t *)HcfMalloc(outputLen, 0);
106     if (output->data == NULL) {
107         LOGE("Failed to allocate output->data memory!");
108         return HCF_ERR_MALLOC;
109     }
110     (void)memcpy_s(output->data, outputLen, outputBuf, outputLen);
111     output->len = outputLen;
112     return HCF_SUCCESS;
113 }
114 
OpensslEngineGetMdLength(HcfMdSpi * self)115 static uint32_t OpensslEngineGetMdLength(HcfMdSpi *self)
116 {
117     if (OpensslGetMdCtx(self) == NULL) {
118         LOGD("[error] The CTX is NULL!");
119         return HCF_OPENSSL_INVALID_MD_LEN;
120     }
121     int32_t size = OpensslEvpMdCtxSize(OpensslGetMdCtx(self));
122     if (size < 0) {
123         LOGD("[error] Get the overflow path length in openssl!");
124         return HCF_OPENSSL_INVALID_MD_LEN;
125     }
126     return size;
127 }
128 
OpensslDestroyMd(HcfObjectBase * self)129 static void OpensslDestroyMd(HcfObjectBase *self)
130 {
131     if (self == NULL) {
132         LOGE("Self ptr is NULL!");
133         return;
134     }
135     if (!HcfIsClassMatch(self, OpensslGetMdClass())) {
136         LOGE("Class is not match.");
137         return;
138     }
139     if (OpensslGetMdCtx((HcfMdSpi *)self) != NULL) {
140         OpensslEvpMdCtxFree(OpensslGetMdCtx((HcfMdSpi *)self));
141     }
142     HcfFree(self);
143 }
144 
OpensslMdSpiCreate(const char * opensslAlgoName,HcfMdSpi ** spiObj)145 HcfResult OpensslMdSpiCreate(const char *opensslAlgoName, HcfMdSpi **spiObj)
146 {
147     if (spiObj == NULL || opensslAlgoName == NULL) {
148         LOGE("Invalid input parameter.");
149         return HCF_INVALID_PARAMS;
150     }
151     OpensslMdSpiImpl *returnSpiImpl = (OpensslMdSpiImpl *)HcfMalloc(sizeof(OpensslMdSpiImpl), 0);
152     if (returnSpiImpl == NULL) {
153         LOGE("Failed to allocate MdSpiImpl memory!");
154         return HCF_ERR_MALLOC;
155     }
156     returnSpiImpl->ctx = OpensslEvpMdCtxNew();
157     if (returnSpiImpl->ctx == NULL) {
158         LOGE("Failed to create ctx!");
159         HcfFree(returnSpiImpl);
160         return HCF_ERR_MALLOC;
161     }
162     const EVP_MD *mdfunc = OpensslGetMdAlgoFromString(opensslAlgoName);
163     if (mdfunc == NULL) {
164         LOGE("OpensslGetMdAlgoFromString failed!");
165         OpensslEvpMdCtxFree(returnSpiImpl->ctx);
166         HcfFree(returnSpiImpl);
167         return HCF_ERR_CRYPTO_OPERATION;
168     }
169     int32_t ret = OpensslEvpDigestInitEx(returnSpiImpl->ctx, mdfunc, NULL);
170     if (ret != HCF_OPENSSL_SUCCESS) {
171         LOGD("[error] Failed to init MD!");
172         OpensslEvpMdCtxFree(returnSpiImpl->ctx);
173         HcfFree(returnSpiImpl);
174         return HCF_ERR_CRYPTO_OPERATION;
175     }
176     returnSpiImpl->base.base.getClass = OpensslGetMdClass;
177     returnSpiImpl->base.base.destroy = OpensslDestroyMd;
178     returnSpiImpl->base.engineUpdateMd = OpensslEngineUpdateMd;
179     returnSpiImpl->base.engineDoFinalMd = OpensslEngineDoFinalMd;
180     returnSpiImpl->base.engineGetMdLength = OpensslEngineGetMdLength;
181     *spiObj = (HcfMdSpi *)returnSpiImpl;
182     return HCF_SUCCESS;
183 }