• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 Huawei Technologies Co., Ltd.
3  * Licensed under the Mulan PSL v2.
4  * You can use this software according to the terms and conditions of the Mulan PSL v2.
5  * You may obtain a copy of Mulan PSL v2 at:
6  *     http://license.coscl.org.cn/MulanPSL2
7  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
8  * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
9  * PURPOSE.
10  * See the Mulan PSL v2 for more details.
11  */
12 #include "soft_hmac.h"
13 #include <openssl/hmac.h>
14 #ifdef OPENSSL_ENABLE
15 #include <crypto/siphash.h>
16 #include <siphash/siphash_local.h>
17 #elif defined OPENSSL3_ENABLE
18 #include <crypto/siphash.h>
19 #endif
20 #include <tee_log.h>
21 #include "soft_gmssl.h"
22 #include "soft_common_api.h"
23 #include "soft_err.h"
24 #include "crypto_inner_defines.h"
25 
26 static const uint32_t g_algorithm_hmac[] = {
27     CRYPTO_TYPE_HMAC_MD5,
28     CRYPTO_TYPE_HMAC_SHA1,
29     CRYPTO_TYPE_HMAC_SHA224,
30     CRYPTO_TYPE_HMAC_SHA256,
31     CRYPTO_TYPE_HMAC_SHA384,
32     CRYPTO_TYPE_HMAC_SHA512,
33     CRYPTO_TYPE_HMAC_SM3,
34     CRYPTO_TYPE_SIP_HASH,
35 };
36 
37 struct hamc_evp {
38     uint32_t algorithm;
39     const EVP_MD *(*hmac_api)(void);
40 };
get_hmac_evp(uint32_t algorithm)41 static const EVP_MD *get_hmac_evp(uint32_t algorithm)
42 {
43     struct hamc_evp g_hmac_config[] = {
44         { CRYPTO_TYPE_HMAC_MD5, EVP_md5 },
45         { CRYPTO_TYPE_HMAC_SHA1, EVP_sha1 },
46         { CRYPTO_TYPE_HMAC_SHA224, EVP_sha224 },
47         { CRYPTO_TYPE_HMAC_SHA256, EVP_sha256 },
48         { CRYPTO_TYPE_HMAC_SHA384, EVP_sha384 },
49         { CRYPTO_TYPE_HMAC_SHA512, EVP_sha512 },
50     };
51 
52     for (size_t i = 0; i < sizeof(g_hmac_config) / sizeof(g_hmac_config[0]); i++) {
53         if (algorithm == g_hmac_config[i].algorithm)
54             return g_hmac_config[i].hmac_api();
55     }
56 
57     return NULL;
58 }
59 
sip_hash_mac_init(struct ctx_handle_t * ctx,const struct symmerit_key_t * key)60 static int32_t sip_hash_mac_init(struct ctx_handle_t *ctx, const struct symmerit_key_t *key)
61 {
62     if (key->key_size != SIPHASH_KEY_SIZE) {
63         tloge("key_size error! key_size = %d", key->key_size);
64         return CRYPTO_BAD_PARAMETERS;
65     }
66 
67     SIPHASH *siphash_ctx = TEE_Malloc(sizeof(*siphash_ctx), 0);
68     if (siphash_ctx == NULL) {
69         tloge("siphash_ctx malloc failed!");
70         return CRYPTO_ERROR_SECURITY;
71     }
72 
73     int ret = SipHash_set_hash_size(siphash_ctx, SIP_HASH_OUTPUT_LEN);
74     if (ret != BORINGSSL_OK) {
75         tloge("hash size invalid! hash size = %d", SIP_HASH_OUTPUT_LEN);
76         TEE_Free((void *)siphash_ctx);
77         return CRYPTO_BAD_PARAMETERS;
78     }
79 
80     ret = SipHash_Init(siphash_ctx, (const uint8_t *)(uintptr_t)(key->key_buffer), 0, 0);
81     if (ret != BORINGSSL_OK) {
82         tloge("sip hash initialize failed!");
83         TEE_Free((void *)siphash_ctx);
84         return get_soft_crypto_error(CRYPTO_BAD_STATE);
85     }
86     ctx->ctx_buffer = (uint64_t)(uintptr_t)siphash_ctx;
87     ctx->ctx_size = sizeof(*siphash_ctx);
88 
89     return CRYPTO_SUCCESS;
90 }
91 
soft_crypto_hmac_init(struct ctx_handle_t * ctx,const struct symmerit_key_t * key)92 int32_t soft_crypto_hmac_init(struct ctx_handle_t *ctx, const struct symmerit_key_t *key)
93 {
94     bool check = (ctx == NULL || key == NULL || key->key_buffer == 0 || key->key_size == 0);
95     if (check) {
96         tloge("invalid params");
97         return CRYPTO_BAD_PARAMETERS;
98     }
99 
100     if (ctx->alg_type == CRYPTO_TYPE_HMAC_SM3)
101         return sm3_mac_init(ctx, key);
102 
103     if (ctx->alg_type == CRYPTO_TYPE_SIP_HASH)
104         return sip_hash_mac_init(ctx, key);
105 
106     int32_t rc = check_valid_algorithm(ctx->alg_type, g_algorithm_hmac, ARRAY_NUM(g_algorithm_hmac));
107     if (rc != CRYPTO_SUCCESS) {
108         tloge("algorithm 0x%x is incorrect", ctx->alg_type);
109         return rc;
110     }
111 
112     const EVP_MD *md = get_hmac_evp(ctx->alg_type);
113     if (md == NULL) {
114         tloge("hmac md is NULL");
115         return CRYPTO_BAD_PARAMETERS;
116     }
117 
118     void *hmac_ctx = HMAC_CTX_new();
119     if (hmac_ctx == NULL) {
120         tloge("hmac ctx is NULL");
121         return CRYPTO_BAD_PARAMETERS;
122     }
123 
124     uint8_t *key_buffer = (uint8_t *)(uintptr_t)key->key_buffer;
125     rc = HMAC_Init(hmac_ctx, key_buffer, key->key_size, md);
126     if (rc != BORINGSSL_OK) {
127         tloge("hmac init failed! ret = %d\n", rc);
128         HMAC_CTX_free(hmac_ctx);
129         return get_soft_crypto_error(CRYPTO_MAC_INVALID);
130     }
131 
132     ctx->ctx_buffer = (uint64_t)(uintptr_t)hmac_ctx;
133     ctx->free_context = free_hmac_context;
134     return CRYPTO_SUCCESS;
135 }
136 
sip_hash_mac_update(struct ctx_handle_t * ctx,const struct memref_t * data_in)137 static int32_t sip_hash_mac_update(struct ctx_handle_t *ctx, const struct memref_t *data_in)
138 {
139     if (data_in->size == 0) {
140         tloge("invalid params. data_in size is 0");
141         TEE_Free((void *)(uintptr_t)ctx->ctx_buffer);
142         ctx->ctx_buffer = 0;
143         return CRYPTO_BAD_PARAMETERS;
144     }
145 
146     SipHash_Update((SIPHASH *)(uintptr_t)ctx->ctx_buffer, (const uint8_t *)(uintptr_t)data_in->buffer, data_in->size);
147 
148     return CRYPTO_SUCCESS;
149 }
150 
soft_crypto_hmac_update(struct ctx_handle_t * ctx,const struct memref_t * data_in)151 int32_t soft_crypto_hmac_update(struct ctx_handle_t *ctx, const struct memref_t *data_in)
152 {
153     bool check = (ctx == NULL || ctx->ctx_buffer == 0 || data_in == NULL || data_in->buffer == 0);
154     if (check) {
155         tloge("invalid params");
156         return CRYPTO_BAD_PARAMETERS;
157     }
158 
159     if (ctx->alg_type == CRYPTO_TYPE_HMAC_SM3)
160         return sm3_mac_update(ctx, data_in);
161 
162     if (ctx->alg_type == CRYPTO_TYPE_SIP_HASH)
163         return sip_hash_mac_update(ctx, data_in);
164 
165     uint8_t *in_buffer = (uint8_t *)(uintptr_t)data_in->buffer;
166     int32_t rc = HMAC_Update((HMAC_CTX *)(uintptr_t)(ctx->ctx_buffer), in_buffer, data_in->size);
167     if (rc != BORINGSSL_OK) {
168         tloge("HMAC_Update failed!");
169         return CRYPTO_BAD_PARAMETERS;
170     }
171     return CRYPTO_SUCCESS;
172 }
173 
sip_hash_mac_computefinal(struct ctx_handle_t * ctx,struct memref_t * data_out)174 static int32_t sip_hash_mac_computefinal(struct ctx_handle_t *ctx, struct memref_t *data_out)
175 {
176     if (data_out->size < SIP_HASH_OUTPUT_LEN) {
177         tloge("data out size is too short");
178         TEE_Free((void *)(uintptr_t)ctx->ctx_buffer);
179         ctx->ctx_buffer = 0;
180         return CRYPTO_BAD_PARAMETERS;
181     }
182 
183     SIPHASH *siphash_ctx = (SIPHASH *)(uintptr_t)ctx->ctx_buffer;
184     uint8_t *out_buffer = (uint8_t *)(uintptr_t)data_out->buffer;
185     uint32_t mac_len_temp = SIP_HASH_OUTPUT_LEN;
186 
187     int32_t rc = SipHash_Final(siphash_ctx, out_buffer, mac_len_temp);
188     if (rc != BORINGSSL_OK) {
189         tloge("sip hash mac final failed!");
190         TEE_Free((void *)(uintptr_t)ctx->ctx_buffer);
191         ctx->ctx_buffer = 0;
192         return get_soft_crypto_error(CRYPTO_BAD_PARAMETERS);
193     }
194 
195     data_out->size = mac_len_temp;
196     TEE_Free((void *)(uintptr_t)ctx->ctx_buffer);
197     ctx->ctx_buffer = 0;
198     return CRYPTO_SUCCESS;
199 }
200 
soft_crypto_hmac_dofinal(struct ctx_handle_t * ctx,struct memref_t * data_out)201 int32_t soft_crypto_hmac_dofinal(struct ctx_handle_t *ctx, struct memref_t *data_out)
202 {
203     bool check = (ctx == NULL || ctx->ctx_buffer == 0);
204     if (check) {
205         tloge("invalid params");
206         return CRYPTO_BAD_PARAMETERS;
207     }
208 
209     check = (data_out == NULL || data_out->buffer == 0);
210     if (check) {
211         tloge("invalid params");
212         free_hmac_context(&(ctx->ctx_buffer));
213         return CRYPTO_BAD_PARAMETERS;
214     }
215 
216     if (ctx->alg_type == CRYPTO_TYPE_HMAC_SM3)
217         return sm3_mac_computefinal(ctx, data_out);
218 
219     if (ctx->alg_type == CRYPTO_TYPE_SIP_HASH)
220         return sip_hash_mac_computefinal(ctx, data_out);
221 
222     uint32_t mac_len_temp = data_out->size;
223     uint8_t *out_buffer = (uint8_t *)(uintptr_t)data_out->buffer;
224 
225     int32_t rc = HMAC_Final((HMAC_CTX *)(uintptr_t)(ctx->ctx_buffer), out_buffer, &mac_len_temp);
226     if (rc != BORINGSSL_OK) {
227         tloge("hmac final failed!");
228         free_hmac_context(&(ctx->ctx_buffer));
229         return get_soft_crypto_error(CRYPTO_BAD_PARAMETERS);
230     }
231 
232     data_out->size = mac_len_temp;
233     free_hmac_context(&(ctx->ctx_buffer));
234     return CRYPTO_SUCCESS;
235 }
236 
soft_crypto_hmac(uint32_t alg_type,const struct symmerit_key_t * key,const struct memref_t * data_in,struct memref_t * data_out)237 int32_t soft_crypto_hmac(uint32_t alg_type, const struct symmerit_key_t *key,
238     const struct memref_t *data_in, struct memref_t *data_out)
239 {
240     if (alg_type == CRYPTO_TYPE_HMAC_SM3)
241         return crypto_sm3_hmac(key, data_in, data_out);
242 
243     bool check = (key == NULL || data_in == NULL || data_out == NULL || data_in->buffer == 0 || data_out->buffer == 0);
244     if (check) {
245         tloge("param is Invalid");
246         return CRYPTO_BAD_PARAMETERS;
247     }
248 
249     uint32_t out_len = data_out->size;
250     const EVP_MD *md = get_hmac_evp(alg_type);
251     uint8_t *in_buffer = (uint8_t *)(uintptr_t)data_in->buffer;
252     uint8_t *out_buffer = (uint8_t *)(uintptr_t)data_out->buffer;
253     uint8_t *key_buffer = (uint8_t *)(uintptr_t)key->key_buffer;
254 
255     out_buffer = HMAC(md, key_buffer, key->key_size, in_buffer,
256         data_in->size, out_buffer, &out_len);
257     if (data_out->buffer == 0) {
258         tloge("hmac failed");
259         return get_soft_crypto_error(CRYPTO_BAD_PARAMETERS);
260     }
261     data_out->size = out_len;
262     return CRYPTO_SUCCESS;
263 }
264