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_common.h"
19 #include "securec.h"
20 #include "log.h"
21 #include "memory.h"
22 #include "config.h"
23 #include "utils.h"
24
25 #include <openssl/evp.h>
26
27 typedef struct {
28 HcfMdSpi base;
29
30 EVP_MD_CTX *ctx;
31
32 char opensslAlgoName[HCF_MAX_ALGO_NAME_LEN];
33 } OpensslMdSpiImpl;
34
OpensslGetMdClass(void)35 static const char *OpensslGetMdClass(void)
36 {
37 return "OpensslMd";
38 }
39
OpensslGetMdCtx(HcfMdSpi * self)40 static EVP_MD_CTX *OpensslGetMdCtx(HcfMdSpi *self)
41 {
42 if (!IsClassMatch((HcfObjectBase *)self, OpensslGetMdClass())) {
43 LOGE("Class is not match.");
44 return NULL;
45 }
46 return ((OpensslMdSpiImpl *)self)->ctx;
47 }
48
OpensslGetMdAlgoFromString(const char * mdName)49 static const EVP_MD *OpensslGetMdAlgoFromString(const char *mdName)
50 {
51 if (strcmp(mdName, "SHA1") == 0) {
52 return EVP_sha1();
53 } else if (strcmp(mdName, "SHA224") == 0) {
54 return EVP_sha224();
55 } else if (strcmp(mdName, "SHA256") == 0) {
56 return EVP_sha256();
57 } else if (strcmp(mdName, "SHA384") == 0) {
58 return EVP_sha384();
59 } else if (strcmp(mdName, "SHA512") == 0) {
60 return EVP_sha512();
61 } else if (strcmp(mdName, "MD5") == 0) {
62 return EVP_md5();
63 }
64 return NULL;
65 }
66
OpensslEngineUpdateMd(HcfMdSpi * self,HcfBlob * input)67 static HcfResult OpensslEngineUpdateMd(HcfMdSpi *self, HcfBlob *input)
68 {
69 if (OpensslGetMdCtx(self) == NULL) {
70 LOGE("The CTX is NULL!");
71 return HCF_ERR_CRYPTO_OPERATION;
72 }
73 if (EVP_DigestUpdate(OpensslGetMdCtx(self), input->data, input->len) != HCF_OPENSSL_SUCCESS) {
74 LOGE("EVP_DigestUpdate return error!");
75 HcfPrintOpensslError();
76 return HCF_ERR_CRYPTO_OPERATION;
77 }
78 return HCF_SUCCESS;
79 }
80
OpensslEngineDoFinalMd(HcfMdSpi * self,HcfBlob * output)81 static HcfResult OpensslEngineDoFinalMd(HcfMdSpi *self, HcfBlob *output)
82 {
83 EVP_MD_CTX *localCtx = OpensslGetMdCtx(self);
84 if (localCtx == NULL) {
85 LOGE("The CTX is NULL!");
86 return HCF_ERR_CRYPTO_OPERATION;
87 }
88 unsigned char outputBuf[EVP_MAX_MD_SIZE];
89 uint32_t outputLen;
90 int32_t ret = EVP_DigestFinal_ex(localCtx, outputBuf, &outputLen);
91 if (ret != HCF_OPENSSL_SUCCESS) {
92 LOGE("EVP_DigestFinal_ex return error!");
93 HcfPrintOpensslError();
94 return HCF_ERR_CRYPTO_OPERATION;
95 }
96 output->data = (uint8_t *)HcfMalloc(outputLen, 0);
97 if (output->data == NULL) {
98 LOGE("Failed to allocate output->data memory!");
99 return HCF_ERR_MALLOC;
100 }
101 (void)memcpy_s(output->data, outputLen, outputBuf, outputLen);
102 output->len = outputLen;
103 return HCF_SUCCESS;
104 }
105
OpensslEngineGetMdLength(HcfMdSpi * self)106 static uint32_t OpensslEngineGetMdLength(HcfMdSpi *self)
107 {
108 if (OpensslGetMdCtx(self) == NULL) {
109 LOGE("The CTX is NULL!");
110 return HCF_OPENSSL_INVALID_MD_LEN;
111 }
112 int32_t size = EVP_MD_CTX_size(OpensslGetMdCtx(self));
113 if (size < 0) {
114 LOGE("Get the overflow path length in openssl!");
115 return HCF_OPENSSL_INVALID_MD_LEN;
116 }
117 return size;
118 }
119
OpensslDestroyMd(HcfObjectBase * self)120 static void OpensslDestroyMd(HcfObjectBase *self)
121 {
122 if (self == NULL) {
123 LOGE("Self ptr is NULL!");
124 return;
125 }
126 if (!IsClassMatch(self, OpensslGetMdClass())) {
127 LOGE("Class is not match.");
128 return;
129 }
130 if (OpensslGetMdCtx((HcfMdSpi *)self) != NULL) {
131 EVP_MD_CTX_free(OpensslGetMdCtx((HcfMdSpi *)self));
132 }
133 HcfFree(self);
134 }
135
OpensslMdSpiCreate(const char * opensslAlgoName,HcfMdSpi ** spiObj)136 HcfResult OpensslMdSpiCreate(const char *opensslAlgoName, HcfMdSpi **spiObj)
137 {
138 if (spiObj == NULL) {
139 LOGE("Invalid input parameter.");
140 return HCF_INVALID_PARAMS;
141 }
142 OpensslMdSpiImpl *returnSpiImpl = (OpensslMdSpiImpl *)HcfMalloc(sizeof(OpensslMdSpiImpl), 0);
143 if (returnSpiImpl == NULL) {
144 LOGE("Failed to allocate returnImpl memory!");
145 return HCF_ERR_MALLOC;
146 }
147 returnSpiImpl->ctx = EVP_MD_CTX_new();
148 if (returnSpiImpl->ctx == NULL) {
149 LOGE("Failed to create ctx!");
150 HcfFree(returnSpiImpl);
151 return HCF_ERR_MALLOC;
152 }
153 const EVP_MD *mdfunc = OpensslGetMdAlgoFromString(opensslAlgoName);
154 int32_t ret = EVP_DigestInit_ex(returnSpiImpl->ctx, mdfunc, NULL);
155 if (ret != HCF_OPENSSL_SUCCESS) {
156 LOGE("Failed to init MD!");
157 HcfFree(returnSpiImpl);
158 EVP_MD_CTX_free(returnSpiImpl->ctx);
159 return HCF_ERR_CRYPTO_OPERATION;
160 }
161 returnSpiImpl->base.base.getClass = OpensslGetMdClass;
162 returnSpiImpl->base.base.destroy = OpensslDestroyMd;
163 returnSpiImpl->base.engineUpdateMd = OpensslEngineUpdateMd;
164 returnSpiImpl->base.engineDoFinalMd = OpensslEngineDoFinalMd;
165 returnSpiImpl->base.engineGetMdLength = OpensslEngineGetMdLength;
166 *spiObj = (HcfMdSpi *)returnSpiImpl;
167 return HCF_SUCCESS;
168 }