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 <stdint.h>
18 #include "securec.h"
19 #include "tls_binlog_id.h"
20 #include "bsl_log_internal.h"
21 #include "bsl_log.h"
22 #include "bsl_err_internal.h"
23 #include "hitls_error.h"
24 #include "tls.h"
25 #include "hs_ctx.h"
26 #include "hs_common.h"
27 #include "hs_verify.h"
28 #include "hs_msg.h"
29 #include "hs_kx.h"
30 #include "session.h"
31
UpdateTicket(TLS_Ctx * ctx,NewSessionTicketMsg * msg,uint8_t * psk,uint32_t pskSize)32 static int32_t UpdateTicket(TLS_Ctx *ctx, NewSessionTicketMsg *msg, uint8_t *psk, uint32_t pskSize)
33 {
34 HITLS_Session *newSession = SESS_Copy(ctx->session);
35 if (newSession == NULL) {
36 BSL_ERR_PUSH_ERROR(HITLS_MEMALLOC_FAIL);
37 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16016, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
38 "copy session info failed.", 0, 0, 0, 0);
39 return HITLS_MEMALLOC_FAIL;
40 }
41
42 SESS_SetStartTime(newSession, (uint64_t)BSL_SAL_CurrentSysTimeGet());
43 HITLS_SESS_SetTimeout(newSession, msg->ticketLifetimeHint);
44
45 if (ctx->negotiatedInfo.version == HITLS_VERSION_TLS13) {
46 SESS_SetTicketAgeAdd(newSession, msg->ticketAgeAdd);
47 HITLS_SESS_SetMasterKey(newSession, psk, pskSize);
48 }
49
50 int32_t ret = SESS_SetTicket(newSession, msg->ticket, msg->ticketSize);
51 if (ret != HITLS_SUCCESS) {
52 HITLS_SESS_Free(newSession);
53 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16017, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
54 "set ticket failed.", 0, 0, 0, 0);
55 return ret;
56 }
57
58 HITLS_SESS_Free(ctx->session);
59 ctx->session = newSession;
60
61 /* The server may send multiple tickets. In this case, each ticket received will be notified to the user through
62 * this callback, so that the client can obtain multiple sessions */
63 if (ctx->globalConfig != NULL && ctx->globalConfig->newSessionCb != NULL) {
64 HITLS_SESS_UpRef(newSession); // It is convenient for users to take away and needs to be released by users
65 if (ctx->globalConfig->newSessionCb(ctx, newSession) == 0) {
66 /* If the user does not reference the session, the number of reference times decreases by 1 */
67 HITLS_SESS_Free(newSession);
68 }
69 }
70
71 return HITLS_SUCCESS;
72 }
73 #ifdef HITLS_TLS_PROTO_TLS_BASIC
Tls12ClientRecvNewSeesionTicketProcess(TLS_Ctx * ctx,HS_Msg * hsMsg)74 int32_t Tls12ClientRecvNewSeesionTicketProcess(TLS_Ctx *ctx, HS_Msg *hsMsg)
75 {
76 int32_t ret = HITLS_SUCCESS;
77 HS_Ctx *hsCtx = ctx->hsCtx;
78 /* The processing of the msg is complete when the NewSeesionTick operation is performed */
79 NewSessionTicketMsg *newSessionTicket = &hsMsg->body.newSessionTicket;
80
81 if (newSessionTicket->ticketLifetimeHint != 0 && newSessionTicket->ticketSize != 0) {
82 if (ctx->negotiatedInfo.isResume == true) {
83 ret = UpdateTicket(ctx, newSessionTicket, NULL, 0);
84 if (ret != HITLS_SUCCESS) {
85 ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_INTERNAL_ERROR);
86 return ret;
87 }
88 } else {
89 /* Saved in the context */
90 hsCtx->ticketLifetimeHint = newSessionTicket->ticketLifetimeHint;
91 hsCtx->ticketSize = newSessionTicket->ticketSize;
92 hsCtx->ticket = newSessionTicket->ticket;
93
94 newSessionTicket->ticket = NULL;
95 newSessionTicket->ticketSize = 0;
96 }
97 }
98
99 /* The server verify data needs to be calculated in advance */
100 ret = VERIFY_CalcVerifyData(ctx, false, hsCtx->masterKey, MASTER_SECRET_LEN);
101 if (ret != HITLS_SUCCESS) {
102 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15971, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
103 "client Calculate server finished data error.", 0, 0, 0, 0);
104 ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_INTERNAL_ERROR);
105 return ret;
106 }
107
108 ctx->method.ctrlCCS(ctx, CCS_CMD_RECV_READY);
109 ctx->method.ctrlCCS(ctx, CCS_CMD_RECV_ACTIVE_CIPHER_SPEC);
110
111 return HS_ChangeState(ctx, TRY_RECV_FINISH);
112 }
113 #endif /* HITLS_TLS_PROTO_TLS_BASIC */
114 #ifdef HITLS_TLS_PROTO_TLS13
Tls13ClientRecvNewSessionTicketProcess(TLS_Ctx * ctx,HS_Msg * hsMsg)115 int32_t Tls13ClientRecvNewSessionTicketProcess(TLS_Ctx *ctx, HS_Msg *hsMsg)
116 {
117 if (!ctx->isClient) {
118 BSL_ERR_PUSH_ERROR(HITLS_MSG_HANDLE_UNEXPECTED_MESSAGE);
119 BSL_LOG_BINLOG_VARLEN(BINLOG_ID16018, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
120 "Unexpected msg: server recv new session ticket", HS_GetMsgTypeStr(hsMsg->type));
121 ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_UNEXPECTED_MESSAGE);
122 return HITLS_MSG_HANDLE_UNEXPECTED_MESSAGE;
123 }
124
125 int32_t ret = HITLS_SUCCESS;
126 NewSessionTicketMsg *msg = &hsMsg->body.newSessionTicket;
127
128 /* If the value is 0, the ticket should be discarded immediately. After the TTO is backed up, the ctx->session field
129 * is empty */
130 if (msg->ticketLifetimeHint == 0 || ctx->session == NULL) {
131 return HS_ChangeState(ctx, TLS_CONNECTED);
132 }
133
134 uint8_t resumePsk[MAX_DIGEST_SIZE] = {0};
135 uint32_t hashLen = SAL_CRYPT_DigestSize(ctx->negotiatedInfo.cipherSuiteInfo.hashAlg);
136 if (hashLen == 0) {
137 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17081, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN, "DigestSize err", 0, 0, 0, 0);
138 return HITLS_CRYPT_ERR_DIGEST;
139 }
140 ret = HS_TLS13DeriveResumePsk(ctx, msg->ticketNonce, msg->ticketNonceSize, resumePsk, hashLen);
141 if (ret != HITLS_SUCCESS) {
142 (void)memset_s(resumePsk, MAX_DIGEST_SIZE, 0, MAX_DIGEST_SIZE);
143 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16015, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
144 "Derive resume psk failed.", 0, 0, 0, 0);
145 return ret;
146 }
147
148 ret = UpdateTicket(ctx, msg, resumePsk, hashLen);
149 (void)memset_s(resumePsk, MAX_DIGEST_SIZE, 0, MAX_DIGEST_SIZE);
150 if (ret != HITLS_SUCCESS) {
151 ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_INTERNAL_ERROR);
152 return ret;
153 }
154
155 return HS_ChangeState(ctx, TLS_CONNECTED);
156 }
157 #endif /* HITLS_TLS_PROTO_TLS13 */
158 #endif /* HITLS_TLS_FEATURE_SESSION_TICKET */