1 /*
2 * Copyright (c) 2021-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 #ifdef HKS_CONFIG_FILE
17 #include HKS_CONFIG_FILE
18 #else
19 #include "hks_config.h"
20 #endif
21
22 #ifdef HKS_SUPPORT_HMAC_C
23
24 #include "hks_openssl_hmac.h"
25
26 #include <openssl/evp.h>
27 #include <openssl/hmac.h>
28 #include <openssl/ossl_typ.h>
29 #include <stddef.h>
30
31 #include "hks_common_check.h"
32 #include "hks_log.h"
33 #include "hks_mem.h"
34 #include "hks_openssl_common.h"
35 #include "hks_openssl_engine.h"
36 #include "hks_template.h"
37
38 struct HksOpensslHmacCtx {
39 uint32_t digestLen;
40 void *append;
41 };
42
HmacCheckBuffer(const struct HksBlob * key,const struct HksBlob * msg,const struct HksBlob * mac)43 static int32_t HmacCheckBuffer(const struct HksBlob *key, const struct HksBlob *msg, const struct HksBlob *mac)
44 {
45 HKS_IF_NOT_SUCC_LOGE_RETURN(HksOpensslCheckBlob(key), HKS_ERROR_INVALID_ARGUMENT, "Invalid key point")
46 HKS_IF_NOT_SUCC_LOGE_RETURN(HksOpensslCheckBlob(msg), HKS_ERROR_INVALID_ARGUMENT, "Invalid msg")
47 HKS_IF_NOT_SUCC_LOGE_RETURN(HksOpensslCheckBlob(mac), HKS_ERROR_INVALID_ARGUMENT, "Invalid mac")
48 return HKS_SUCCESS;
49 }
50
HmacGenKeyCheckParam(const struct HksKeySpec * spec)51 static int32_t HmacGenKeyCheckParam(const struct HksKeySpec *spec)
52 {
53 if ((spec->keyLen == 0) || (spec->keyLen % BIT_NUM_OF_UINT8 != 0)) {
54 HKS_LOG_E("keyLen is wrong, len = %" LOG_PUBLIC "u", spec->keyLen);
55 return HKS_ERROR_INVALID_ARGUMENT;
56 }
57 return HKS_SUCCESS;
58 }
59
60 #ifdef HKS_SUPPORT_HMAC_GENERATE_KEY
HksOpensslHmacGenerateKey(const struct HksKeySpec * spec,struct HksBlob * key)61 int32_t HksOpensslHmacGenerateKey(const struct HksKeySpec *spec, struct HksBlob *key)
62 {
63 HKS_IF_NOT_SUCC_LOGE_RETURN(HmacGenKeyCheckParam(spec),
64 HKS_ERROR_INVALID_ARGUMENT, "aes generate key invalid params!")
65
66 return HksOpensslGenerateRandomKey(spec->keyLen, key);
67 }
68 #endif /* HKS_SUPPORT_HMAC_GENERATE_KEY */
69
HmacCheckParam(const struct HksBlob * key,uint32_t alg,const struct HksBlob * msg,const struct HksBlob * mac)70 static int32_t HmacCheckParam(
71 const struct HksBlob *key, uint32_t alg, const struct HksBlob *msg, const struct HksBlob *mac)
72 {
73 HKS_IF_NOT_SUCC_LOGE_RETURN(HmacCheckBuffer(key, msg, mac), HKS_ERROR_INVALID_ARGUMENT, "Invalid Buffer Info")
74
75 if ((alg != HKS_DIGEST_SHA1) && (alg != HKS_DIGEST_SHA224) && (alg != HKS_DIGEST_SHA256) &&
76 (alg != HKS_DIGEST_SHA384) && (alg != HKS_DIGEST_SHA512) && (alg != HKS_DIGEST_SM3)) {
77 HKS_LOG_E("Invalid alg(0x%" LOG_PUBLIC "x)", alg);
78 return HKS_ERROR_INVALID_ARGUMENT;
79 }
80
81 uint32_t digestLen;
82 HKS_IF_NOT_SUCC_LOGE_RETURN(HksGetDigestLen(alg, &digestLen),
83 HKS_ERROR_INVALID_ARGUMENT, "Invalid alg(0x%" LOG_PUBLIC "x)", alg)
84
85 if (mac->size < digestLen) {
86 HKS_LOG_E("invalid mac->size(0x%" LOG_PUBLIC "x) for digestLen(0x%" LOG_PUBLIC "x)", mac->size, digestLen);
87 return HKS_ERROR_INVALID_ARGUMENT;
88 }
89 return HKS_SUCCESS;
90 }
91
92 #if defined(HKS_SUPPORT_HMAC_SHA1) || defined(HKS_SUPPORT_HMAC_SHA224) || defined(HKS_SUPPORT_HMAC_SHA256) || \
93 defined(HKS_SUPPORT_HMAC_SHA384) || defined(HKS_SUPPORT_HMAC_SHA512) || defined(HKS_SUPPORT_HMAC_SM3)
HksOpensslHmac(const struct HksBlob * key,uint32_t digestAlg,const struct HksBlob * msg,struct HksBlob * mac)94 int32_t HksOpensslHmac(const struct HksBlob *key, uint32_t digestAlg, const struct HksBlob *msg, struct HksBlob *mac)
95 {
96 HKS_IF_NOT_SUCC_RETURN(HmacCheckParam(key, digestAlg, msg, mac), HKS_ERROR_INVALID_ARGUMENT)
97
98 const EVP_MD *opensslAlg = NULL;
99 if (digestAlg == HKS_DIGEST_SM3) {
100 opensslAlg = EVP_sm3();
101 } else {
102 opensslAlg = GetOpensslAlg(digestAlg);
103 }
104
105 HKS_IF_NULL_LOGE_RETURN(opensslAlg, HKS_ERROR_CRYPTO_ENGINE_ERROR, "hmac get openssl algorithm failed")
106
107 uint8_t *hmacData = HMAC(opensslAlg, key->data, (int32_t)key->size, msg->data, msg->size, mac->data, &mac->size);
108 HKS_IF_NULL_LOGE_RETURN(hmacData, HKS_ERROR_CRYPTO_ENGINE_ERROR, "hmac process failed.")
109 return HKS_SUCCESS;
110 }
111
HksOpensslHmacInit(void ** cryptoCtx,const struct HksBlob * key,uint32_t digestAlg)112 int32_t HksOpensslHmacInit(void **cryptoCtx, const struct HksBlob *key, uint32_t digestAlg)
113 {
114 HKS_IF_NOT_SUCC_LOGE_RETURN(HksOpensslCheckBlob(key), HKS_ERROR_INVALID_ARGUMENT, "Invalid key point")
115
116 if ((digestAlg != HKS_DIGEST_SHA1) && (digestAlg != HKS_DIGEST_SHA224) && (digestAlg != HKS_DIGEST_SHA256) &&
117 (digestAlg != HKS_DIGEST_SHA384) && (digestAlg != HKS_DIGEST_SHA512) && (digestAlg != HKS_DIGEST_SM3)) {
118 HKS_LOG_E("Invalid alg(0x%" LOG_PUBLIC "x)", digestAlg);
119 return HKS_ERROR_INVALID_ARGUMENT;
120 }
121
122 const EVP_MD *opensslAlg = NULL;
123 if (digestAlg == HKS_DIGEST_SM3) {
124 opensslAlg = EVP_sm3();
125 } else {
126 opensslAlg = GetOpensslAlg(digestAlg);
127 }
128
129 HKS_IF_NULL_LOGE_RETURN(opensslAlg, HKS_ERROR_CRYPTO_ENGINE_ERROR, "hmac_init get openssl algorithm fail")
130
131 uint32_t digestLen;
132 HKS_IF_NOT_SUCC_LOGE_RETURN(HksGetDigestLen(digestAlg, &digestLen),
133 HKS_ERROR_INVALID_ARGUMENT, "Invalid alg(0x%" LOG_PUBLIC "x)", digestAlg)
134
135 HMAC_CTX *tmpCtx = NULL;
136 HKS_IF_NULL_LOGE_RETURN((tmpCtx = HMAC_CTX_new()),
137 HKS_ERROR_CRYPTO_ENGINE_ERROR, "initialize HksOpensslHmacCtx failed")
138
139 if (!HMAC_Init_ex(tmpCtx, key->data, (int32_t)key->size, opensslAlg, NULL)) {
140 HKS_LOG_E("openssl hmac init failed.");
141 HMAC_CTX_free(tmpCtx);
142 return HKS_ERROR_CRYPTO_ENGINE_ERROR;
143 }
144
145 struct HksOpensslHmacCtx *outCtx = (struct HksOpensslHmacCtx *)HksMalloc(
146 sizeof(struct HksOpensslHmacCtx));
147
148 if (outCtx == NULL) {
149 HKS_LOG_E("initialize HksOpensslHmacCtx failed");
150 HMAC_CTX_free(tmpCtx);
151 return HKS_ERROR_MALLOC_FAIL;
152 }
153
154 outCtx->digestLen = digestLen;
155 outCtx->append = (void *)tmpCtx;
156 *cryptoCtx = (void *)outCtx;
157
158 return HKS_SUCCESS;
159 }
160
HksOpensslHmacUpdate(void * cryptoCtx,const struct HksBlob * msg)161 int32_t HksOpensslHmacUpdate(void *cryptoCtx, const struct HksBlob *msg)
162 {
163 HKS_IF_NOT_SUCC_LOGE_RETURN(HksOpensslCheckBlob(msg), HKS_ERROR_INVALID_ARGUMENT, "Invalid key point")
164
165 struct HksOpensslHmacCtx *hmacCtx = (struct HksOpensslHmacCtx *)cryptoCtx;
166 HKS_IF_NULL_LOGE_RETURN(hmacCtx, HKS_ERROR_NULL_POINTER, "hmacCtx invalid")
167
168 HMAC_CTX *context = (HMAC_CTX *)hmacCtx->append;
169 HKS_IF_NULL_LOGE_RETURN(context, HKS_FAILURE, "context is null")
170
171 int hmacData = HMAC_Update(context, msg->data, msg->size);
172 if (!hmacData) {
173 HKS_LOG_E("hmac update failed.");
174 return HKS_ERROR_CRYPTO_ENGINE_ERROR;
175 }
176 return HKS_SUCCESS;
177 }
178
HksOpensslHmacFinal(void ** cryptoCtx,struct HksBlob * msg,struct HksBlob * mac)179 int32_t HksOpensslHmacFinal(void **cryptoCtx, struct HksBlob *msg, struct HksBlob *mac)
180 {
181 if ((cryptoCtx == NULL) || (*cryptoCtx == NULL)) {
182 return HKS_ERROR_NULL_POINTER;
183 }
184
185 struct HksOpensslHmacCtx *hmacCtx = (struct HksOpensslHmacCtx *)*cryptoCtx;
186 if (hmacCtx == NULL) {
187 HKS_LOG_E("hmacCtx invalid");
188 HKS_FREE(*cryptoCtx);
189 return HKS_ERROR_NULL_POINTER;
190 }
191
192 HMAC_CTX *context = (HMAC_CTX *)hmacCtx->append;
193 if (context == NULL) {
194 HKS_LOG_E("context is null");
195 HKS_FREE(*cryptoCtx);
196 return HKS_FAILURE;
197 }
198
199 if (msg == NULL || HksOpensslCheckBlob(mac) != HKS_SUCCESS) {
200 HKS_LOG_E("Invalid msg or mac point");
201 HksOpensslHmacHalFreeCtx(cryptoCtx);
202 return HKS_ERROR_INVALID_ARGUMENT;
203 }
204
205 int hmacData;
206 if (msg->size != 0) {
207 hmacData = HMAC_Update(context, msg->data, msg->size);
208 if (!hmacData) {
209 HKS_LOG_E("hmac final update failed.");
210 HksOpensslHmacHalFreeCtx(cryptoCtx);
211 return HKS_ERROR_CRYPTO_ENGINE_ERROR;
212 }
213 }
214
215 hmacData = HMAC_Final(context, mac->data, &mac->size);
216 if (!hmacData) {
217 HKS_LOG_E("hmac final failed.");
218 HksOpensslHmacHalFreeCtx(cryptoCtx);
219 return HKS_ERROR_CRYPTO_ENGINE_ERROR;
220 }
221
222 HksOpensslHmacHalFreeCtx(cryptoCtx);
223 return HKS_SUCCESS;
224 }
225
HksOpensslHmacHalFreeCtx(void ** cryptoCtx)226 void HksOpensslHmacHalFreeCtx(void **cryptoCtx)
227 {
228 if (cryptoCtx == NULL || *cryptoCtx == NULL) {
229 HKS_LOG_E("Openssl hmac free ctx is null");
230 return;
231 }
232
233 struct HksOpensslHmacCtx *opensslHmacCtx = (struct HksOpensslHmacCtx *)*cryptoCtx;
234 if (opensslHmacCtx->append != NULL) {
235 HMAC_CTX_free((HMAC_CTX *)opensslHmacCtx->append);
236 opensslHmacCtx->append = NULL;
237 }
238
239 HKS_FREE(*cryptoCtx);
240 }
241 #endif /* HKS_SUPPORT_HMAC_SHA1 */
242 #endif /* HKS_SUPPORT_HMAC_C */