• 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 #if defined(HITLS_TLS_HOST_SERVER) || defined(HITLS_TLS_PROTO_TLS13)
17 #include "tls_binlog_id.h"
18 #include "bsl_log.h"
19 #include "bsl_log_internal.h"
20 #include "bsl_err_internal.h"
21 #include "bsl_sal.h"
22 #include "bsl_bytes.h"
23 #include "crypt_algid.h"
24 #include "hitls_error.h"
25 #include "cert_method.h"
26 #include "hs_msg.h"
27 #include "hs_ctx.h"
28 #include "hs_verify.h"
29 #include "parse_msg.h"
30 #include "parse_common.h"
31 #include "config_type.h"
32 
CheckSignHashAlg(TLS_Ctx * ctx,uint16_t signHashAlg)33 static int32_t CheckSignHashAlg(TLS_Ctx *ctx, uint16_t signHashAlg)
34 {
35     int32_t ret = CheckPeerSignScheme(ctx, ctx->hsCtx->peerCert, signHashAlg);
36     if (ret != HITLS_SUCCESS) {
37         return ParseErrorProcess(ctx, ret, 0, NULL, ALERT_ILLEGAL_PARAMETER);
38     }
39 
40     TLS_Config *config = &ctx->config.tlsConfig;
41 #ifdef HITLS_TLS_PROTO_TLS13
42     if (ctx->negotiatedInfo.version == HITLS_VERSION_TLS13) {
43         const TLS_SigSchemeInfo *schemeInfo = ConfigGetSignatureSchemeInfo(config, signHashAlg);
44         if (schemeInfo == NULL || ((schemeInfo->certVersionBits & TLS13_VERSION_BIT) == 0)) {
45             BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16195, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
46                 "not allowed to use 0x%X signAlg tls1.3.", signHashAlg, 0, 0, 0);
47             return ParseErrorProcess(ctx, HITLS_PARSE_UNSUPPORT_SIGN_ALG, 0, NULL, ALERT_HANDSHAKE_FAILURE);
48         }
49     }
50 #endif /* HITLS_TLS_PROTO_TLS13 */
51     uint32_t i = 0;
52     for (i = 0; i < config->signAlgorithmsSize; i++) {
53         if (signHashAlg == config->signAlgorithms[i]) {
54             break;
55         }
56     }
57 
58     if (i == config->signAlgorithmsSize) {
59         return ParseErrorProcess(ctx, HITLS_PARSE_UNSUPPORT_SIGN_ALG, BINLOG_ID15865,
60             BINGLOG_STR("the signHashAlg match failed"), ALERT_HANDSHAKE_FAILURE);
61     }
62 
63 #ifdef HITLS_TLS_FEATURE_SECURITY
64     if (SECURITY_SslCheck(ctx, HITLS_SECURITY_SECOP_SIGALG_CHECK, 0, signHashAlg, NULL) != SECURITY_SUCCESS) {
65         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17159, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
66             "signHashAlg 0x%x SslCheck fail", signHashAlg, 0, 0, 0);
67         return ParseErrorProcess(ctx, HITLS_PARSE_UNSUPPORT_SIGN_ALG, 0, NULL, ALERT_HANDSHAKE_FAILURE);
68     }
69 #endif
70 
71     return HITLS_SUCCESS;
72 }
73 
ParseCertificateVerifyPre(ParsePacket * pkt,uint16_t * signHashAlg)74 static int32_t ParseCertificateVerifyPre(ParsePacket *pkt, uint16_t *signHashAlg)
75 {
76     const char *logStr = BINGLOG_STR("parse cert verifypre fail");
77     /* 2-byte signature hash algorithm + 2-byte signature data length.
78        If the message length is less than 4 bytes, a failure message is returned. */
79     if (pkt->bufLen < 4u) {
80         return ParseErrorProcess(pkt->ctx, HITLS_PARSE_INVALID_MSG_LEN, BINLOG_ID16964, logStr, ALERT_DECODE_ERROR);
81     }
82     if (pkt->ctx->negotiatedInfo.version >= HITLS_VERSION_TLS12) {
83         int32_t ret = ParseBytesToUint16(pkt, signHashAlg);
84         if (ret != HITLS_SUCCESS) {
85             return ParseErrorProcess(pkt->ctx, HITLS_PARSE_INVALID_MSG_LEN, BINLOG_ID16965, logStr, ALERT_DECODE_ERROR);
86         }
87 
88         if (CheckSignHashAlg(pkt->ctx, *signHashAlg) != HITLS_SUCCESS) {
89             BSL_ERR_PUSH_ERROR(HITLS_PARSE_UNSUPPORT_SIGN_ALG);
90             return HITLS_PARSE_UNSUPPORT_SIGN_ALG;
91         }
92     }
93     return HITLS_SUCCESS;
94 }
95 
KeyMatchSignAlg(TLS_Ctx * ctx,HITLS_SignHashAlgo signScheme,HITLS_CERT_KeyType keyType,HITLS_CERT_Key * key)96 static int32_t KeyMatchSignAlg(TLS_Ctx *ctx, HITLS_SignHashAlgo signScheme, HITLS_CERT_KeyType keyType,
97     HITLS_CERT_Key *key)
98 {
99     (void)key;
100     HITLS_CERT_KeyType certKeyType = SAL_CERT_SignScheme2CertKeyType(ctx, signScheme);
101     if (certKeyType != keyType) {
102         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16197, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
103             "signScheme not matche key, signScheme is 0x%X, certKeyType is %u, keyType is %u", signScheme, certKeyType,
104             keyType, 0);
105         return ParseErrorProcess(ctx, HITLS_PARSE_UNSUPPORT_SIGN_ALG, 0, NULL, ALERT_ILLEGAL_PARAMETER);
106     }
107 
108     /* check curve matches signature algorithm, only check ec key for tls1.3 */
109     if (ctx->negotiatedInfo.version != HITLS_VERSION_TLS13) {
110         return HITLS_SUCCESS;
111     }
112 #ifdef HITLS_TLS_PROTO_TLS13
113     HITLS_Config *config = &ctx->config.tlsConfig;
114     const TLS_SigSchemeInfo *schemeInfo = ConfigGetSignatureSchemeInfo(config, signScheme);
115     if (schemeInfo == NULL) {
116         return ParseErrorProcess(ctx, HITLS_PARSE_UNSUPPORT_SIGN_ALG, 0, NULL, ALERT_ILLEGAL_PARAMETER);
117     }
118     if (schemeInfo->paraId == CRYPT_PKEY_PARAID_MAX) {
119         return HITLS_SUCCESS;
120     }
121     int32_t paramId = CRYPT_PKEY_PARAID_MAX;
122     int32_t ret = SAL_CERT_KeyCtrl(config, key, CERT_KEY_CTRL_GET_PARAM_ID, NULL, (void *)&paramId);
123     if (ret != HITLS_SUCCESS || paramId != schemeInfo->paraId) {
124         return ParseErrorProcess(ctx, HITLS_PARSE_INVALID_MSG_LEN, BINLOG_ID16198,
125             BINGLOG_STR("paramId mismatch sigScheme"), ALERT_INTERNAL_ERROR);
126     }
127 #endif /* HITLS_TLS_PROTO_TLS13 */
128     return HITLS_SUCCESS;
129 }
130 
VerifySignData(TLS_Ctx * ctx,uint16_t signHashAlg,const uint8_t * sign,uint16_t signSize)131 static int VerifySignData(TLS_Ctx *ctx, uint16_t signHashAlg, const uint8_t *sign, uint16_t signSize)
132 {
133     CERT_MgrCtx *mgrCtx = ctx->config.tlsConfig.certMgrCtx;
134     if (ctx->hsCtx == NULL || ctx->hsCtx->peerCert == NULL) {
135         return ParseErrorProcess(ctx, HITLS_PARSE_VERIFY_SIGN_FAIL, BINLOG_ID15866,
136             BINGLOG_STR("no peer certificate"), ALERT_CERTIFICATE_REQUIRED);
137     }
138 
139     HITLS_CERT_X509 *cert = SAL_CERT_PairGetX509(ctx->hsCtx->peerCert);
140     HITLS_CERT_Key *pubkey = NULL;
141     int32_t ret = SAL_CERT_X509Ctrl(&ctx->config.tlsConfig, cert, CERT_CTRL_GET_PUB_KEY, NULL, (void *)&pubkey);
142     if (ret != HITLS_SUCCESS) {
143         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16966, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
144             "GET_PUB_KEY fail", 0, 0, 0, 0);
145         ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_INTERNAL_ERROR);
146         return ret;
147     }
148 
149     HITLS_SignHashAlgo signScheme = signHashAlg;
150     HITLS_CERT_KeyType keyType = TLS_CERT_KEY_TYPE_UNKNOWN;
151     ret = SAL_CERT_KeyCtrl(&ctx->config.tlsConfig, pubkey, CERT_KEY_CTRL_GET_TYPE, NULL, (void *)&keyType);
152     if (ret != HITLS_SUCCESS) {
153         SAL_CERT_KeyFree(mgrCtx, pubkey);
154         return ParseErrorProcess(ctx, ret, BINLOG_ID16072,
155             BINGLOG_STR("SAL_CERT_KeyCtrl fails"), ALERT_INTERNAL_ERROR);
156     }
157 
158     if (signScheme == 0) {
159         /** If the value of the signature hash algorithm is 0, the peer does not send the signature algorithm.
160             In this case, we need to obtain the default signature algorithm through the certificate. */
161         signScheme = SAL_CERT_GetDefaultSignHashAlgo(keyType);
162         if (signScheme == CERT_SIG_SCHEME_UNKNOWN) {
163             BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16073, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
164                 "no available signature scheme, key type = %u.", keyType, 0, 0, 0);
165             SAL_CERT_KeyFree(mgrCtx, pubkey);
166             return ParseErrorProcess(ctx, HITLS_PARSE_VERIFY_SIGN_FAIL, 0, NULL, ALERT_INTERNAL_ERROR);
167         }
168     }
169 
170     /* check whether the signature scheme matches the certificate key */
171     if (KeyMatchSignAlg(ctx, signScheme, keyType, pubkey) != HITLS_SUCCESS) {
172         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID16967, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
173             "KeyMatchSignAlg fail", 0, 0, 0, 0);
174         SAL_CERT_KeyFree(mgrCtx, pubkey);
175         return HITLS_PARSE_VERIFY_SIGN_FAIL;
176     }
177 
178     /** verifying certificate data */
179     ret = VERIFY_VerifySignData(ctx, pubkey, signScheme, sign, signSize);
180     SAL_CERT_KeyFree(mgrCtx, pubkey);
181     return ret;
182 }
183 
ParseCertificateVerify(TLS_Ctx * ctx,const uint8_t * buf,uint32_t bufLen,HS_Msg * hsMsg)184 int32_t ParseCertificateVerify(TLS_Ctx *ctx, const uint8_t *buf, uint32_t bufLen, HS_Msg *hsMsg)
185 {
186     uint16_t signHashAlg = 0;
187     uint32_t offset = 0;
188     ParsePacket pkt = {.ctx = ctx, .buf = buf, .bufLen = bufLen, .bufOffset = &offset};
189 
190     int32_t ret = ParseCertificateVerifyPre(&pkt, &signHashAlg);
191     if (ret != HITLS_SUCCESS) {
192         return ret;
193     }
194     const char *logStr = BINGLOG_STR("parse cert verify fail");
195     uint16_t signSize = 0;
196     ret = ParseBytesToUint16(&pkt, &signSize);
197     if (ret != HITLS_SUCCESS) {
198         return ParseErrorProcess(pkt.ctx, HITLS_PARSE_INVALID_MSG_LEN, BINLOG_ID16968, logStr, ALERT_DECODE_ERROR);
199     }
200 
201     if ((signSize != (pkt.bufLen - *pkt.bufOffset)) || (signSize == 0)) {
202         return ParseErrorProcess(pkt.ctx, HITLS_PARSE_INVALID_MSG_LEN, BINLOG_ID16969, logStr, ALERT_DECODE_ERROR);
203     }
204 
205     const uint8_t *sign = &pkt.buf[*pkt.bufOffset];
206 
207     ret = VerifySignData(pkt.ctx, signHashAlg, sign, signSize);
208     if (ret != HITLS_SUCCESS) {
209         return ret;
210     }
211 
212     CertificateVerifyMsg *msg = &hsMsg->body.certificateVerify;
213     msg->signHashAlg = signHashAlg;
214     msg->signSize = signSize;
215     BSL_SAL_FREE(msg->sign);
216     msg->sign = BSL_SAL_Dump(sign, signSize);
217     if (msg->sign == NULL) {
218         return ParseErrorProcess(pkt.ctx, HITLS_MEMALLOC_FAIL, BINLOG_ID16970,
219             BINGLOG_STR("Dump fail"), ALERT_INTERNAL_ERROR);
220     }
221     pkt.ctx->peerInfo.peerSignHashAlg = signHashAlg;
222     return HITLS_SUCCESS;
223 }
224 
CleanCertificateVerify(CertificateVerifyMsg * msg)225 void CleanCertificateVerify(CertificateVerifyMsg *msg)
226 {
227     if (msg == NULL) {
228         return;
229     }
230 
231     BSL_SAL_FREE(msg->sign);
232 
233     return;
234 }
235 #endif /* HITLS_TLS_HOST_CLIENT || HITLS_TLS_PROTO_TLS13 */