• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * This file is part of the openHiTLS project.
3  *
4  * openHiTLS is licensed under the Mulan PSL v2.
5  * You can use this software according to the terms and conditions of the Mulan PSL v2.
6  * You may obtain a copy of Mulan PSL v2 at:
7  *
8  *     http://license.coscl.org.cn/MulanPSL2
9  *
10  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11  * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12  * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13  * See the Mulan PSL v2 for more details.
14  */
15 #include "hitls_build.h"
16 #ifdef HITLS_TLS_FEATURE_SESSION_TICKET
17 #include <stdbool.h>
18 #include <string.h>
19 #include "securec.h"
20 #include "tlv.h"
21 #include "bsl_log_internal.h"
22 #include "bsl_log.h"
23 #include "bsl_err_internal.h"
24 #include "tls_binlog_id.h"
25 #include "bsl_bytes.h"
26 #include "bsl_sal.h"
27 #include "crypt.h"
28 #include "hitls_error.h"
29 #include "session_type.h"
30 #include "session_enc.h"
31 
32 typedef struct {
33     uint8_t keyName[HITLS_TICKET_KEY_NAME_SIZE];
34     uint8_t iv[HITLS_TICKET_IV_SIZE];
35     uint32_t encryptedStateSize;
36     uint8_t *encryptedState;
37     uint8_t mac[HITLS_TICKET_KEY_SIZE];
38 } Ticket;
39 
40 #define DEFAULT_SESSION_ENCRYPT_TYPE HITLS_AEAD_CIPHER
41 #define DEFAULT_SESSION_ENCRYPT_ALGO HITLS_CIPHER_AES_256_GCM
42 #ifdef HITLS_TLS_SUITE_CIPHER_CBC
43 #define AES_CBC_BLOCK_LEN 16u
44 #endif
45 
SetCipherInfo(const TLS_SessionMgr * sessMgr,Ticket * ticket,HITLS_CipherParameters * cipher)46 static void SetCipherInfo(const TLS_SessionMgr *sessMgr, Ticket *ticket, HITLS_CipherParameters *cipher)
47 {
48     cipher->type = DEFAULT_SESSION_ENCRYPT_TYPE;
49     cipher->algo = DEFAULT_SESSION_ENCRYPT_ALGO;
50     cipher->key = sessMgr->ticketAesKey;
51     cipher->keyLen = HITLS_TICKET_KEY_SIZE;
52     cipher->iv = ticket->iv;
53     cipher->ivLen = HITLS_TICKET_IV_SIZE;
54     cipher->aad = ticket->iv;
55     cipher->aadLen = HITLS_TICKET_IV_SIZE;
56     return;
57 }
58 
GetSessEncryptInfo(TLS_Ctx * ctx,const TLS_SessionMgr * sessMgr,Ticket * ticket,HITLS_CipherParameters * cipher)59 static int32_t GetSessEncryptInfo(TLS_Ctx *ctx, const TLS_SessionMgr *sessMgr, Ticket *ticket, HITLS_CipherParameters *cipher)
60 {
61     int32_t ret;
62 #ifdef HITLS_TLS_FEATURE_SESSION
63     HITLS_TicketKeyCb cb = sessMgr->ticketKeyCb;
64     if (cb != NULL) {
65         ret = cb(ticket->keyName, HITLS_TICKET_KEY_NAME_SIZE, cipher, true);
66         if (memcpy_s(ticket->iv, HITLS_TICKET_IV_SIZE, cipher->iv, cipher->ivLen) != EOK) {
67             BSL_ERR_PUSH_ERROR(HITLS_TICKET_KEY_RET_FAIL);
68             BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16069, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
69                 "iv copy fail when GetSessEncryptInfo.", 0, 0, 0, 0);
70             return HITLS_TICKET_KEY_RET_FAIL;
71         }
72         return ret;
73     }
74 #endif
75     /* The user does not register the callback. The default ticket key is used. */
76     (void)memcpy_s(ticket->keyName, HITLS_TICKET_KEY_NAME_SIZE, sessMgr->ticketKeyName, HITLS_TICKET_KEY_NAME_SIZE);
77 
78     ret = SAL_CRYPT_Rand(LIBCTX_FROM_CTX(ctx), ticket->iv, HITLS_TICKET_IV_SIZE);
79     if (ret != HITLS_SUCCESS) {
80         BSL_ERR_PUSH_ERROR(HITLS_TICKET_KEY_RET_FAIL);
81         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16021, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN, "Rand fail", 0, 0, 0, 0);
82         return HITLS_TICKET_KEY_RET_FAIL;
83     }
84 
85     SetCipherInfo(sessMgr, ticket, cipher);
86 
87     return HITLS_TICKET_KEY_RET_SUCCESS;
88 }
89 
PackKeyNameAndIv(const Ticket * ticket,uint8_t * data,uint32_t len,uint32_t * usedLen)90 static int32_t PackKeyNameAndIv(const Ticket *ticket, uint8_t *data, uint32_t len, uint32_t *usedLen)
91 {
92     uint32_t offset = 0;
93     if (memcpy_s(&data[0], len, ticket->keyName, HITLS_TICKET_KEY_NAME_SIZE) != EOK) {
94         BSL_ERR_PUSH_ERROR(HITLS_MEMCPY_FAIL);
95         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16022, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
96             "copy keyName fail when encrypt session ticket.", 0, 0, 0, 0);
97         return HITLS_MEMCPY_FAIL;
98     }
99     offset += HITLS_TICKET_KEY_NAME_SIZE;
100 
101     if (memcpy_s(&data[offset], len - offset, ticket->iv, HITLS_TICKET_IV_SIZE) != EOK) {
102         BSL_ERR_PUSH_ERROR(HITLS_MEMCPY_FAIL);
103         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16023, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
104             "copy iv fail when encrypt session ticket.", 0, 0, 0, 0);
105         return HITLS_MEMCPY_FAIL;
106     }
107     offset += HITLS_TICKET_IV_SIZE;
108 
109     *usedLen = offset;
110     return HITLS_SUCCESS;
111 }
112 #ifdef HITLS_TLS_SUITE_CIPHER_CBC
GetCbcPendingLen(uint32_t encodeLen,uint8_t * paddingLen)113 static uint32_t GetCbcPendingLen(uint32_t encodeLen, uint8_t *paddingLen)
114 {
115     *paddingLen = (encodeLen + sizeof(uint8_t)) % AES_CBC_BLOCK_LEN;
116     if (*paddingLen != 0) {
117         *paddingLen = AES_CBC_BLOCK_LEN - *paddingLen;
118     }
119     return *paddingLen + sizeof(uint8_t);
120 }
121 #endif
PackEncryptTicket(HITLS_Lib_Ctx * libCtx,const char * attrName,const HITLS_Session * sess,HITLS_CipherParameters * cipher,uint8_t * data,uint32_t len,uint32_t * usedLen)122 static int32_t PackEncryptTicket(HITLS_Lib_Ctx *libCtx, const char *attrName,
123     const HITLS_Session *sess, HITLS_CipherParameters *cipher, uint8_t *data, uint32_t len, uint32_t *usedLen)
124 {
125     int32_t ret = 0;
126     /* Encode the session. */
127     uint32_t encodeLen = SESS_GetTotalEncodeSize(sess);
128     uint32_t plaintextLen = encodeLen;
129 #ifdef HITLS_TLS_SUITE_CIPHER_CBC
130     uint8_t paddingLen = 0;
131     if (cipher->type == HITLS_CBC_CIPHER) {
132         /* In CBC mode, the padding needs to be calculated. */
133         /* Plain text length plus padding length */
134         plaintextLen += GetCbcPendingLen(encodeLen, &paddingLen);
135     }
136 #endif
137 
138     uint8_t *plaintext = BSL_SAL_Calloc(1u, plaintextLen);
139     if (plaintext == NULL) {
140         BSL_ERR_PUSH_ERROR(HITLS_MEMALLOC_FAIL);
141         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16024, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
142             "encData malloc fail when encrypt session ticket.", 0, 0, 0, 0);
143         return HITLS_MEMALLOC_FAIL;
144     }
145     ret = SESS_Encode(sess, plaintext, plaintextLen, &plaintextLen);
146     if (ret != HITLS_SUCCESS) {
147         BSL_SAL_CleanseData(plaintext, plaintextLen);
148         BSL_SAL_FREE(plaintext);
149         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16025, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
150             "SESS_Encode fail when encrypt session ticket.", 0, 0, 0, 0);
151         return ret;
152     }
153 
154 #ifdef HITLS_TLS_SUITE_CIPHER_CBC
155     /* Padding is required in CBC mode. */
156     if (cipher->type == HITLS_CBC_CIPHER) {
157         /* The last byte is the padding length field, and the padding content is the length value. */
158         uint32_t count = paddingLen + sizeof(uint8_t);
159         /* The calculation is accurate when the memory is applied for the plaintext. Therefore, the
160          * return value does not need to be checked. */
161         (void)memset_s(&plaintext[encodeLen], count, paddingLen, count);
162         plaintextLen += count;
163     }
164 #endif
165     uint32_t offset = 0;
166     /* reserved length field */
167     offset += sizeof(uint32_t);
168     /* Encrypt and fill the ticket. */
169     uint32_t encryptLen = len - offset;
170     ret = SAL_CRYPT_Encrypt(libCtx, attrName, cipher, plaintext, plaintextLen, &data[offset], &encryptLen);
171     BSL_SAL_CleanseData(plaintext, plaintextLen);
172     BSL_SAL_FREE(plaintext);
173     if (ret != HITLS_SUCCESS) {
174         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16026, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
175             "SAL_CRYPT_Encrypt fail when encrypt session ticket.", 0, 0, 0, 0);
176         return ret;
177     }
178     /* padding length */
179     BSL_Uint32ToByte(encryptLen, &data[offset - sizeof(uint32_t)]);
180     offset += encryptLen;
181 
182     *usedLen = offset;
183     return HITLS_SUCCESS;
184 }
185 
186 #ifdef HITLS_TLS_SUITE_CIPHER_CBC
PackTicketHmac(HITLS_Lib_Ctx * libCtx,const char * attrName,HITLS_CipherParameters * cipher,uint8_t * data,uint32_t len,uint32_t offset,uint32_t * usedLen)187 static int32_t PackTicketHmac(HITLS_Lib_Ctx *libCtx, const char *attrName,
188     HITLS_CipherParameters *cipher, uint8_t *data, uint32_t len, uint32_t offset,
189     uint32_t *usedLen)
190 {
191     /* The HMAC field is filled only in CBC mode. In other modes, the HMAC field is returned. */
192     if (cipher->type != HITLS_CBC_CIPHER) {
193         *usedLen = 0;
194         return HITLS_SUCCESS;
195     }
196 
197     int32_t ret;
198     uint8_t mac[HITLS_TICKET_KEY_SIZE] = {0};
199     uint32_t macLen = HITLS_TICKET_KEY_SIZE;
200     ret = SAL_CRYPT_Hmac(libCtx, attrName,
201         HITLS_HASH_SHA_256, cipher->hmacKey, cipher->hmacKeyLen, data, offset, mac, &macLen);
202     if (ret != HITLS_SUCCESS) {
203         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16027, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
204             "TicketHmac fail when encrypt session ticket.", 0, 0, 0, 0);
205         return ret;
206     }
207     if (memcpy_s(&data[offset], len - offset, mac, macLen) != EOK) {
208         BSL_ERR_PUSH_ERROR(HITLS_MEMCPY_FAIL);
209         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16028, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
210             "copy mac fail when encrypt session ticket.", 0, 0, 0, 0);
211         return HITLS_MEMCPY_FAIL;
212     }
213     *usedLen = macLen;
214     return HITLS_SUCCESS;
215 }
216 #endif /* HITLS_TLS_SUITE_CIPHER_CBC */
217 
NewTicketBuf(const HITLS_Session * sess,HITLS_CipherParameters * cipher,uint32_t * ticketBufSize)218 static uint8_t *NewTicketBuf(const HITLS_Session *sess, HITLS_CipherParameters *cipher, uint32_t *ticketBufSize)
219 {
220     (void)cipher;
221     uint32_t encodeLen = SESS_GetTotalEncodeSize(sess);
222     uint32_t plaintextLen = encodeLen;
223 #ifdef HITLS_TLS_SUITE_CIPHER_CBC
224     if (cipher->type == HITLS_CBC_CIPHER) {
225         /* In CBC mode, the padding needs to be calculated. */
226         uint8_t paddingLen = (encodeLen + sizeof(uint8_t)) % AES_CBC_BLOCK_LEN;
227         if (paddingLen != 0) {
228             paddingLen = AES_CBC_BLOCK_LEN - paddingLen;
229         }
230         /* Plain text length plus padding length */
231         plaintextLen += paddingLen + sizeof(uint8_t);
232     }
233 #endif
234     /* Plain text length plus key name, iv, encrypted data length, and MAC length. */
235     plaintextLen += HITLS_TICKET_KEY_NAME_SIZE + HITLS_TICKET_IV_SIZE + sizeof(uint32_t) + HITLS_TICKET_KEY_SIZE;
236 
237     uint8_t *ticketBuf = BSL_SAL_Calloc(1u, plaintextLen);
238     if (ticketBuf == NULL) {
239         BSL_ERR_PUSH_ERROR(HITLS_MEMALLOC_FAIL);
240         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16029, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
241             "ticketBuf malloc fail when encrypt session ticket.", 0, 0, 0, 0);
242         return NULL;
243     }
244 
245     *ticketBufSize = plaintextLen;
246     return ticketBuf;
247 }
248 
SESSMGR_EncryptSessionTicket(TLS_Ctx * ctx,const TLS_SessionMgr * sessMgr,const HITLS_Session * sess,uint8_t ** ticketBuf,uint32_t * ticketBufSize)249 int32_t SESSMGR_EncryptSessionTicket(TLS_Ctx *ctx,
250     const TLS_SessionMgr *sessMgr, const HITLS_Session *sess, uint8_t **ticketBuf, uint32_t *ticketBufSize)
251 {
252     if (sessMgr == NULL || sess == NULL || ticketBuf == NULL) {
253         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16713, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN, "input null", 0, 0, 0, 0);
254         return HITLS_INTERNAL_EXCEPTION;
255     }
256 
257     Ticket ticket = {0};
258     HITLS_CipherParameters cipher = {0};
259     int32_t retVal = GetSessEncryptInfo(ctx, sessMgr, &ticket, &cipher);
260     if (retVal < 0) {
261         BSL_ERR_PUSH_ERROR(HITLS_SESS_ERR_SESSION_TICKET_KEY_FAIL);
262         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16030, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
263             "GetSessEncryptInfo fail when encrypt session ticket.", 0, 0, 0, 0);
264         return HITLS_SESS_ERR_SESSION_TICKET_KEY_FAIL;
265     }
266     if (retVal == HITLS_TICKET_KEY_RET_FAIL) {
267         /* Failed to obtain the encryption information. An empty ticket is returned. */
268         *ticketBufSize = 0;
269         return HITLS_SUCCESS;
270     }
271 
272     uint32_t dataLen = 0;
273     uint8_t *data = NewTicketBuf(sess, &cipher, &dataLen);
274     if (data == NULL) {
275         return HITLS_MEMALLOC_FAIL;
276     }
277     /* Fill in the key name and iv. */
278     int32_t ret;
279     uint32_t packLen = 0;
280     uint32_t offset = 0;
281     ret = PackKeyNameAndIv(&ticket, &data[0], dataLen, &packLen);
282     if (ret != HITLS_SUCCESS) {
283         BSL_SAL_FREE(data);
284         return ret;
285     }
286     offset += packLen;
287     /* Encrypt and fill the ticket. */
288     ret = PackEncryptTicket(LIBCTX_FROM_CTX(ctx), ATTRIBUTE_FROM_CTX(ctx),
289         sess, &cipher, &data[offset], dataLen - offset, &packLen);
290     if (ret != HITLS_SUCCESS) {
291         BSL_SAL_FREE(data);
292         return ret;
293     }
294     offset += packLen;
295 
296 #ifdef HITLS_TLS_SUITE_CIPHER_CBC
297     /* fill HMAC */
298     ret = PackTicketHmac(LIBCTX_FROM_CTX(ctx), ATTRIBUTE_FROM_CTX(ctx),
299         &cipher, data, dataLen, offset, &packLen);
300     if (ret != HITLS_SUCCESS) {
301         BSL_SAL_FREE(data);
302         return ret;
303     }
304     offset += packLen;
305 #endif
306     *ticketBufSize = offset;
307     *ticketBuf = data;
308     return HITLS_SUCCESS;
309 }
ParseSessionTicket(Ticket * ticket,const uint8_t * ticketBuf,uint32_t ticketBufSize)310 static int32_t ParseSessionTicket(Ticket *ticket, const uint8_t *ticketBuf, uint32_t ticketBufSize)
311 {
312     uint32_t offset = 0;
313     if (ticketBufSize < HITLS_TICKET_KEY_NAME_SIZE + HITLS_TICKET_IV_SIZE + sizeof(uint32_t)) {
314         BSL_ERR_PUSH_ERROR(HITLS_SESS_ERR_SESSION_TICKET_SIZE_INCORRECT);
315         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16044, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
316             "ticketBufSize is incorrect when parse session ticket.", 0, 0, 0, 0);
317         return HITLS_SESS_ERR_SESSION_TICKET_SIZE_INCORRECT;
318     }
319 
320     (void)memcpy_s(ticket->keyName, HITLS_TICKET_KEY_NAME_SIZE, ticketBuf, HITLS_TICKET_KEY_NAME_SIZE);
321     offset += HITLS_TICKET_KEY_NAME_SIZE;
322 
323     (void)memcpy_s(ticket->iv, HITLS_TICKET_IV_SIZE, &ticketBuf[offset], HITLS_TICKET_IV_SIZE);
324     offset += HITLS_TICKET_IV_SIZE;
325 
326     ticket->encryptedStateSize = BSL_ByteToUint32(&ticketBuf[offset]);
327     offset += sizeof(uint32_t);
328 
329     if ((ticketBufSize - offset) < ticket->encryptedStateSize) {
330         BSL_ERR_PUSH_ERROR(HITLS_SESS_ERR_SESSION_TICKET_SIZE_INCORRECT);
331         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16032, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
332             "ticketBufSize is incorrect when parse session ticket encryptedStateSize.", 0, 0, 0, 0);
333         return HITLS_SESS_ERR_SESSION_TICKET_SIZE_INCORRECT;
334     }
335 
336     ticket->encryptedState = (uint8_t *)(uintptr_t)&ticketBuf[offset];
337     offset += ticket->encryptedStateSize;
338 
339     if (ticketBufSize != offset) {
340         if ((ticketBufSize - offset) != HITLS_TICKET_KEY_SIZE) {
341             BSL_ERR_PUSH_ERROR(HITLS_SESS_ERR_SESSION_TICKET_SIZE_INCORRECT);
342             BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16033, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
343                 "ticketBufSize is incorrect when parse session ticket hmac.", 0, 0, 0, 0);
344             return HITLS_SESS_ERR_SESSION_TICKET_SIZE_INCORRECT;
345         }
346         (void)memcpy_s(ticket->mac, HITLS_TICKET_KEY_SIZE, &ticketBuf[offset], HITLS_TICKET_KEY_SIZE);
347     }
348 
349     return HITLS_SUCCESS;
350 }
351 
GetSessDecryptInfo(const TLS_SessionMgr * sessMgr,Ticket * ticket,HITLS_CipherParameters * cipher)352 static int32_t GetSessDecryptInfo(const TLS_SessionMgr *sessMgr, Ticket *ticket, HITLS_CipherParameters *cipher)
353 {
354 #ifdef HITLS_TLS_FEATURE_SESSION
355     HITLS_TicketKeyCb cb = sessMgr->ticketKeyCb;
356     if (cb != NULL) {
357         return cb(ticket->keyName, HITLS_TICKET_KEY_NAME_SIZE, cipher, false);
358     }
359 #endif
360     /* The user does not register the callback. Use the default ticket key. */
361     if (memcmp(ticket->keyName, sessMgr->ticketKeyName, HITLS_TICKET_KEY_NAME_SIZE) != 0) {
362         /* Failed to match the key name. */
363         return HITLS_TICKET_KEY_RET_FAIL;
364     }
365     SetCipherInfo(sessMgr, ticket, cipher);
366     return HITLS_TICKET_KEY_RET_SUCCESS;
367 }
368 
369 #ifdef HITLS_TLS_SUITE_CIPHER_CBC
CheckTicketHmac(HITLS_Lib_Ctx * libCtx,const char * attrName,HITLS_CipherParameters * cipher,Ticket * ticket,const uint8_t * data,uint32_t len,bool * isPass)370 static int32_t CheckTicketHmac(HITLS_Lib_Ctx *libCtx, const char *attrName,
371     HITLS_CipherParameters *cipher, Ticket *ticket, const uint8_t *data, uint32_t len, bool *isPass)
372 {
373     /* The HMAC check is required only in CBC mode. In other modes, the HMAC check is returned. */
374     if (cipher->type != HITLS_CBC_CIPHER) {
375         *isPass = true;
376         return HITLS_SUCCESS;
377     }
378 
379     int32_t ret;
380     uint8_t mac[HITLS_TICKET_KEY_SIZE] = {0};
381     uint32_t macLen = HITLS_TICKET_KEY_SIZE;
382     ret = SAL_CRYPT_Hmac(libCtx, attrName,
383         HITLS_HASH_SHA_256, cipher->hmacKey, cipher->hmacKeyLen, data, len - HITLS_TICKET_KEY_SIZE, mac, &macLen);
384     if (ret != HITLS_SUCCESS) {
385         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16035, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
386             "TicketHmac fail when decrypt session ticket.", 0, 0, 0, 0);
387         return ret;
388     }
389 
390     if (memcmp(ticket->mac, mac, macLen) != 0) {
391         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16036, BSL_LOG_LEVEL_INFO, BSL_LOG_BINLOG_TYPE_RUN,
392             "compare mac fail when decrypt session ticket.", 0, 0, 0, 0);
393         /* The HMAC check fails, but the complete link establishment can be continued. Therefore, HITLS_SUCCESS is
394          * returned. */
395         *isPass = false;
396         return HITLS_SUCCESS;
397     }
398     *isPass = true;
399     return HITLS_SUCCESS;
400 }
401 #endif /* HITLS_TLS_SUITE_CIPHER_CBC */
402 
GenerateSessFromTicket(HITLS_Lib_Ctx * libCtx,const char * attrName,HITLS_CipherParameters * cipher,Ticket * ticket,uint32_t ticketBufSize,HITLS_Session ** sess)403 static int32_t GenerateSessFromTicket(HITLS_Lib_Ctx *libCtx, const char *attrName,
404     HITLS_CipherParameters *cipher, Ticket *ticket, uint32_t ticketBufSize, HITLS_Session **sess)
405 {
406     /* Decrypt the ticket. */
407     uint32_t plaintextLen = ticketBufSize;
408     uint8_t *plaintext = BSL_SAL_Calloc(1u, ticketBufSize);
409     if (plaintext == NULL) {
410         BSL_ERR_PUSH_ERROR(HITLS_MEMALLOC_FAIL);
411         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16037, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
412             "plaintext malloc fail when decrypt session ticket.", 0, 0, 0, 0);
413         return HITLS_MEMALLOC_FAIL;
414     }
415     int32_t ret;
416     ret = SAL_CRYPT_Decrypt(libCtx, attrName,
417         cipher, ticket->encryptedState, ticket->encryptedStateSize, plaintext, &plaintextLen);
418     if (ret != HITLS_SUCCESS) {
419         BSL_SAL_FREE(plaintext);
420         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16038, BSL_LOG_LEVEL_INFO, BSL_LOG_BINLOG_TYPE_RUN,
421             "SAL_CRYPT_Decrypt fail when decrypt session ticket.", 0, 0, 0, 0);
422         /* The ticket fails to be decrypted, but the complete connection can be established. Therefore, HITLS_SUCCESS is
423          * returned. */
424         return HITLS_SUCCESS;
425     }
426 
427 #ifdef HITLS_TLS_SUITE_CIPHER_CBC
428     /* Padding needs to be verified in CBC mode. */
429     if (cipher->type == HITLS_CBC_CIPHER) {
430         /* The last byte is the padding length field, and the padding content is the length value. */
431         uint8_t paddingLen = plaintext[plaintextLen - 1];
432         for (uint32_t i = 1; i <= paddingLen; i++) {
433             if (plaintext[plaintextLen - 1 - i] != paddingLen) {
434                 BSL_SAL_FREE(plaintext);
435                 return HITLS_SUCCESS;
436             }
437         }
438         plaintextLen -= paddingLen + sizeof(uint8_t);
439     }
440 #endif
441 
442     /* Parse the ticket content to the SESS. */
443     HITLS_Session *session = HITLS_SESS_New();
444     if (session == NULL) {
445         BSL_SAL_FREE(plaintext);
446         BSL_ERR_PUSH_ERROR(HITLS_MEMALLOC_FAIL);
447         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16039, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
448             "HITLS_SESS_New fail when decrypt session ticket.", 0, 0, 0, 0);
449         return HITLS_MEMALLOC_FAIL;
450     }
451     ret = SESS_Decode(session, plaintext, plaintextLen);
452     BSL_SAL_FREE(plaintext);
453     if (ret != HITLS_SUCCESS) {
454         HITLS_SESS_Free(session);
455         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16040, BSL_LOG_LEVEL_INFO, BSL_LOG_BINLOG_TYPE_RUN,
456             "SESS_Decode fail when decrypt session ticket.", 0, 0, 0, 0);
457         /* The ticket content fails to be parsed, but the complete connection can be established. Therefore,
458          * HITLS_SUCCESS is returned. */
459         return HITLS_SUCCESS;
460     }
461 
462     *sess = session;
463     return HITLS_SUCCESS;
464 }
465 
SESSMGR_DecryptSessionTicket(HITLS_Lib_Ctx * libCtx,const char * attrName,const TLS_SessionMgr * sessMgr,HITLS_Session ** sess,const uint8_t * ticketBuf,uint32_t ticketBufSize,bool * isTicketExpect)466 int32_t SESSMGR_DecryptSessionTicket(HITLS_Lib_Ctx *libCtx, const char *attrName,
467     const TLS_SessionMgr *sessMgr, HITLS_Session **sess, const uint8_t *ticketBuf,
468     uint32_t ticketBufSize, bool *isTicketExpect)
469 {
470     if (sessMgr == NULL || sess == NULL || ticketBuf == NULL || isTicketExpect == NULL) {
471         BSL_ERR_PUSH_ERROR(HITLS_INTERNAL_EXCEPTION);
472         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16041, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
473             "SESSMGR_DecryptSessionTicket input parameter is NULL.", 0, 0, 0, 0);
474         return HITLS_INTERNAL_EXCEPTION;
475     }
476 
477     int32_t ret;
478     Ticket ticket = {0};
479     /* Parse the data into the ticket structure. */
480     ret = ParseSessionTicket(&ticket, ticketBuf, ticketBufSize);
481     if (ret != HITLS_SUCCESS) {
482         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16042, BSL_LOG_LEVEL_INFO, BSL_LOG_BINLOG_TYPE_RUN,
483             "ParseSessionTicket fail when decrypt session ticket.", 0, 0, 0, 0);
484         /* If the ticket fails to be parsed, the session is not resumption and the complete connection is established.
485          * Therefore, HITLS_SUCCESS is returned. */
486         *isTicketExpect = true;
487         return HITLS_SUCCESS;
488     }
489 
490     /* Obtain decryption information. */
491     HITLS_CipherParameters cipher = {0};
492     int32_t retVal = GetSessDecryptInfo(sessMgr, &ticket, &cipher);
493     if (retVal < 0) {
494         BSL_ERR_PUSH_ERROR(HITLS_SESS_ERR_SESSION_TICKET_KEY_FAIL);
495         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16043, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
496             "GetSessDecryptInfo fail when decrypt session ticket.", 0, 0, 0, 0);
497         return HITLS_SESS_ERR_SESSION_TICKET_KEY_FAIL;
498     }
499     switch (retVal) {
500         case HITLS_TICKET_KEY_RET_FAIL:
501             /* If no corresponding key is found, the system directly returns a message and complete link establishment
502              * is performed. */
503             *isTicketExpect = true;
504             return HITLS_SUCCESS;
505         case HITLS_TICKET_KEY_RET_SUCCESS_RENEW:
506             *isTicketExpect = true;
507             break;
508         case HITLS_TICKET_KEY_RET_SUCCESS:
509         default:
510             *isTicketExpect = false;
511             break;
512     }
513 #ifdef HITLS_TLS_SUITE_CIPHER_CBC
514     /* Verify the MAC address. */
515     bool isPass = true;
516     ret = CheckTicketHmac(libCtx, attrName, &cipher, &ticket, ticketBuf, ticketBufSize, &isPass);
517     if ((ret != HITLS_SUCCESS) || (!isPass)) {
518         /* If the HMAC check fails, the session is not restored and complete link establishment is performed. */
519         return ret;
520     }
521 #endif
522     /* Parse the ticket content to the SESS. */
523     return GenerateSessFromTicket(libCtx, attrName, &cipher, &ticket, ticketBufSize, sess);
524 }
525 #endif /* HITLS_TLS_FEATURE_SESSION_TICKET */