2009-01-03 22:22:43 +01:00
|
|
|
/*
|
2020-02-03 10:40:36 +01:00
|
|
|
* Shared handshake reading/writing functions
|
|
|
|
* for TLS versions <= 1.2.
|
2009-01-03 22:22:43 +01:00
|
|
|
*
|
2015-07-27 11:11:48 +02:00
|
|
|
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
|
2015-09-04 14:21:07 +02:00
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
2010-07-18 22:36:00 +02:00
|
|
|
*
|
2015-09-04 14:21:07 +02:00
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
|
|
* not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
2009-01-04 17:27:10 +01:00
|
|
|
*
|
2015-09-04 14:21:07 +02:00
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
2009-01-03 22:22:43 +01:00
|
|
|
*
|
2015-09-04 14:21:07 +02:00
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
2009-01-03 22:22:43 +01:00
|
|
|
*
|
2015-09-04 14:21:07 +02:00
|
|
|
* This file is part of mbed TLS (https://tls.mbed.org)
|
2009-01-03 22:22:43 +01:00
|
|
|
*/
|
|
|
|
|
2015-04-08 12:49:31 +02:00
|
|
|
#if !defined(MBEDTLS_CONFIG_FILE)
|
2015-03-09 18:05:11 +01:00
|
|
|
#include "mbedtls/config.h"
|
2014-04-29 12:39:06 +02:00
|
|
|
#else
|
2015-04-08 12:49:31 +02:00
|
|
|
#include MBEDTLS_CONFIG_FILE
|
2014-04-29 12:39:06 +02:00
|
|
|
#endif
|
2009-01-03 22:22:43 +01:00
|
|
|
|
2016-04-26 08:43:27 +02:00
|
|
|
#if defined(MBEDTLS_PLATFORM_C)
|
|
|
|
#include "mbedtls/platform.h"
|
|
|
|
#else
|
|
|
|
#include <stdlib.h>
|
|
|
|
#define mbedtls_calloc calloc
|
|
|
|
#define mbedtls_free free
|
|
|
|
#endif
|
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
#if defined(MBEDTLS_SSL_TLS_C)
|
|
|
|
|
2015-03-09 18:05:11 +01:00
|
|
|
#include "mbedtls/ssl.h"
|
2015-05-26 11:57:05 +02:00
|
|
|
#include "mbedtls/ssl_internal.h"
|
2019-12-18 16:07:04 +01:00
|
|
|
#include "mbedtls/debug.h"
|
|
|
|
#include "mbedtls/error.h"
|
2018-04-17 16:51:09 +02:00
|
|
|
#include "mbedtls/platform_util.h"
|
2019-05-16 13:39:07 +02:00
|
|
|
#include "mbedtls/version.h"
|
2013-08-27 21:55:01 +02:00
|
|
|
|
2015-02-06 14:43:58 +01:00
|
|
|
#include <string.h>
|
|
|
|
|
2019-01-10 11:27:10 +01:00
|
|
|
#if defined(MBEDTLS_USE_PSA_CRYPTO)
|
|
|
|
#include "mbedtls/psa_util.h"
|
|
|
|
#include "psa/crypto.h"
|
|
|
|
#endif
|
|
|
|
|
2016-10-07 15:47:14 +02:00
|
|
|
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
2015-03-09 18:05:11 +01:00
|
|
|
#include "mbedtls/oid.h"
|
2014-04-11 11:06:22 +02:00
|
|
|
#endif
|
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
/*
|
|
|
|
* HANDSHAKE STATE: Outgoing `Certificate`
|
|
|
|
*/
|
2018-08-06 12:19:13 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
#if !defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED)
|
2019-04-09 16:22:03 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl )
|
Add CID configuration API
Context:
The CID draft does not require that the length of CIDs used for incoming
records must not change in the course of a connection. Since the record
header does not contain a length field for the CID, this means that if
CIDs of varying lengths are used, the CID length must be inferred from
other aspects of the record header (such as the epoch) and/or by means
outside of the protocol, e.g. by coding its length in the CID itself.
Inferring the CID length from the record's epoch is theoretically possible
in DTLS 1.2, but it requires the information about the epoch to be present
even if the epoch is no longer used: That's because one should silently drop
records from old epochs, but not the entire datagrams to which they belong
(there might be entire flights in a single datagram, including a change of
epoch); however, in order to do so, one needs to parse the record's content
length, the position of which is only known once the CID length for the epoch
is known. In conclusion, it puts a significant burden on the implementation
to infer the CID length from the record epoch, which moreover mangles record
processing with the high-level logic of the protocol (determining which epochs
are in use in which flights, when they are changed, etc. -- this would normally
determine when we drop epochs).
Moreover, with DTLS 1.3, CIDs are no longer uniquely associated to epochs,
but every epoch may use a set of CIDs of varying lengths -- in that case,
it's even theoretically impossible to do record header parsing based on
the epoch configuration only.
We must therefore seek a way for standalone record header parsing, which
means that we must either (a) fix the CID lengths for incoming records,
or (b) allow the application-code to configure a callback to implement
an application-specific CID parsing which would somehow infer the length
of the CID from the CID itself.
Supporting multiple lengths for incoming CIDs significantly increases
complexity while, on the other hand, the restriction to a fixed CID length
for incoming CIDs (which the application controls - in contrast to the
lengths of the CIDs used when writing messages to the peer) doesn't
appear to severely limit the usefulness of the CID extension.
Therefore, the initial implementation of the CID feature will require
a fixed length for incoming CIDs, which is what this commit enforces,
in the following way:
In order to avoid a change of API in case support for variable lengths
CIDs shall be added at some point, we keep mbedtls_ssl_set_cid(), which
includes a CID length parameter, but add a new API mbedtls_ssl_conf_cid_len()
which applies to an SSL configuration, and which fixes the CID length that
any call to mbetls_ssl_set_cid() which applies to an SSL context that is bound
to the given SSL configuration must use.
While this creates a slight redundancy of parameters, it allows to
potentially add an API like mbedtls_ssl_conf_cid_len_cb() later which
could allow users to register a callback which dynamically infers the
length of a CID at record header parsing time, without changing the
rest of the API.
2019-05-03 14:06:44 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
|
|
|
|
ssl->handshake->ciphersuite_info;
|
Add CID configuration API
Context:
The CID draft does not require that the length of CIDs used for incoming
records must not change in the course of a connection. Since the record
header does not contain a length field for the CID, this means that if
CIDs of varying lengths are used, the CID length must be inferred from
other aspects of the record header (such as the epoch) and/or by means
outside of the protocol, e.g. by coding its length in the CID itself.
Inferring the CID length from the record's epoch is theoretically possible
in DTLS 1.2, but it requires the information about the epoch to be present
even if the epoch is no longer used: That's because one should silently drop
records from old epochs, but not the entire datagrams to which they belong
(there might be entire flights in a single datagram, including a change of
epoch); however, in order to do so, one needs to parse the record's content
length, the position of which is only known once the CID length for the epoch
is known. In conclusion, it puts a significant burden on the implementation
to infer the CID length from the record epoch, which moreover mangles record
processing with the high-level logic of the protocol (determining which epochs
are in use in which flights, when they are changed, etc. -- this would normally
determine when we drop epochs).
Moreover, with DTLS 1.3, CIDs are no longer uniquely associated to epochs,
but every epoch may use a set of CIDs of varying lengths -- in that case,
it's even theoretically impossible to do record header parsing based on
the epoch configuration only.
We must therefore seek a way for standalone record header parsing, which
means that we must either (a) fix the CID lengths for incoming records,
or (b) allow the application-code to configure a callback to implement
an application-specific CID parsing which would somehow infer the length
of the CID from the CID itself.
Supporting multiple lengths for incoming CIDs significantly increases
complexity while, on the other hand, the restriction to a fixed CID length
for incoming CIDs (which the application controls - in contrast to the
lengths of the CIDs used when writing messages to the peer) doesn't
appear to severely limit the usefulness of the CID extension.
Therefore, the initial implementation of the CID feature will require
a fixed length for incoming CIDs, which is what this commit enforces,
in the following way:
In order to avoid a change of API in case support for variable lengths
CIDs shall be added at some point, we keep mbedtls_ssl_set_cid(), which
includes a CID length parameter, but add a new API mbedtls_ssl_conf_cid_len()
which applies to an SSL configuration, and which fixes the CID length that
any call to mbetls_ssl_set_cid() which applies to an SSL context that is bound
to the given SSL configuration must use.
While this creates a slight redundancy of parameters, it allows to
potentially add an API like mbedtls_ssl_conf_cid_len_cb() later which
could allow users to register a callback which dynamically infers the
length of a CID at record header parsing time, without changing the
rest of the API.
2019-05-03 14:06:44 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate" ) );
|
2019-05-03 15:38:32 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
if( !mbedtls_ssl_ciphersuite_uses_srv_cert( ciphersuite_info ) )
|
2019-04-25 17:01:49 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) );
|
|
|
|
ssl->state++;
|
2019-04-25 17:01:49 +02:00
|
|
|
return( 0 );
|
|
|
|
}
|
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
|
|
|
|
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
|
2019-04-09 16:22:03 +02:00
|
|
|
}
|
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
#else /* MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */
|
|
|
|
|
|
|
|
int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl )
|
2019-04-09 16:22:03 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
|
|
|
|
size_t i, n;
|
|
|
|
const mbedtls_x509_crt *crt;
|
|
|
|
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
|
|
|
|
ssl->handshake->ciphersuite_info;
|
2019-04-26 18:08:02 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate" ) );
|
2019-04-26 18:08:02 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
if( !mbedtls_ssl_ciphersuite_uses_srv_cert( ciphersuite_info ) )
|
2019-04-26 18:08:02 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) );
|
|
|
|
ssl->state++;
|
2019-04-26 18:08:02 +02:00
|
|
|
return( 0 );
|
|
|
|
}
|
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
#if defined(MBEDTLS_SSL_CLI_C)
|
|
|
|
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT )
|
2019-05-22 17:50:35 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
if( ssl->client_auth == 0 )
|
2019-05-22 17:50:35 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) );
|
|
|
|
ssl->state++;
|
|
|
|
return( 0 );
|
2019-05-22 17:50:35 +02:00
|
|
|
}
|
2019-04-09 16:22:03 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
#if defined(MBEDTLS_SSL_PROTO_SSL3)
|
|
|
|
/*
|
|
|
|
* If using SSLv3 and got no cert, send an Alert message
|
|
|
|
* (otherwise an empty Certificate message will be sent).
|
|
|
|
*/
|
|
|
|
if( mbedtls_ssl_own_cert( ssl ) == NULL &&
|
|
|
|
ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
|
|
|
|
{
|
|
|
|
ssl->out_msglen = 2;
|
|
|
|
ssl->out_msgtype = MBEDTLS_SSL_MSG_ALERT;
|
|
|
|
ssl->out_msg[0] = MBEDTLS_SSL_ALERT_LEVEL_WARNING;
|
|
|
|
ssl->out_msg[1] = MBEDTLS_SSL_ALERT_MSG_NO_CERT;
|
2014-09-30 22:21:31 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 2, ( "got no certificate to send" ) );
|
|
|
|
goto write_msg;
|
|
|
|
}
|
|
|
|
#endif /* MBEDTLS_SSL_PROTO_SSL3 */
|
|
|
|
}
|
|
|
|
#endif /* MBEDTLS_SSL_CLI_C */
|
|
|
|
#if defined(MBEDTLS_SSL_SRV_C)
|
|
|
|
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER )
|
2016-05-25 12:56:48 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
if( mbedtls_ssl_own_cert( ssl ) == NULL )
|
|
|
|
{
|
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no certificate to send" ) );
|
|
|
|
return( MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED );
|
|
|
|
}
|
2016-05-25 12:56:48 +02:00
|
|
|
}
|
2020-02-03 10:40:36 +01:00
|
|
|
#endif
|
2013-07-18 12:32:27 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_CRT( 3, "own certificate", mbedtls_ssl_own_cert( ssl ) );
|
2013-08-02 15:34:52 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
/*
|
|
|
|
* 0 . 0 handshake type
|
|
|
|
* 1 . 3 handshake length
|
|
|
|
* 4 . 6 length of all certs
|
|
|
|
* 7 . 9 length of cert. 1
|
|
|
|
* 10 . n-1 peer certificate
|
|
|
|
* n . n+2 length of cert. 2
|
|
|
|
* n+3 . ... upper level cert, etc.
|
|
|
|
*/
|
|
|
|
i = 7;
|
|
|
|
crt = mbedtls_ssl_own_cert( ssl );
|
2019-02-07 13:27:42 +01:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
while( crt != NULL )
|
2013-08-02 15:34:52 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
n = crt->raw.len;
|
|
|
|
if( n > MBEDTLS_SSL_OUT_CONTENT_LEN - 3 - i )
|
2013-08-02 15:34:52 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 1, ( "certificate too large, %d > %d",
|
|
|
|
i + 3 + n, MBEDTLS_SSL_OUT_CONTENT_LEN ) );
|
|
|
|
return( MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE );
|
2013-08-02 15:34:52 +02:00
|
|
|
}
|
2020-02-03 10:40:36 +01:00
|
|
|
|
|
|
|
ssl->out_msg[i ] = (unsigned char)( n >> 16 );
|
|
|
|
ssl->out_msg[i + 1] = (unsigned char)( n >> 8 );
|
|
|
|
ssl->out_msg[i + 2] = (unsigned char)( n );
|
|
|
|
|
|
|
|
i += 3; memcpy( ssl->out_msg + i, crt->raw.p, n );
|
|
|
|
i += n; crt = crt->next;
|
2013-08-02 15:34:52 +02:00
|
|
|
}
|
2019-02-05 18:00:50 +01:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
ssl->out_msg[4] = (unsigned char)( ( i - 7 ) >> 16 );
|
|
|
|
ssl->out_msg[5] = (unsigned char)( ( i - 7 ) >> 8 );
|
|
|
|
ssl->out_msg[6] = (unsigned char)( ( i - 7 ) );
|
2013-08-02 15:34:52 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
ssl->out_msglen = i;
|
|
|
|
ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
|
|
|
|
ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE;
|
|
|
|
|
|
|
|
#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_CLI_C)
|
|
|
|
write_msg:
|
|
|
|
#endif
|
|
|
|
|
|
|
|
ssl->state++;
|
2013-08-02 15:34:52 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
|
|
|
|
{
|
|
|
|
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
|
|
|
|
return( ret );
|
2013-08-02 15:34:52 +02:00
|
|
|
}
|
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate" ) );
|
|
|
|
|
|
|
|
return( ret );
|
2013-08-02 15:34:52 +02:00
|
|
|
}
|
2020-02-03 10:40:36 +01:00
|
|
|
#endif /* MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */
|
2013-08-02 15:34:52 +02:00
|
|
|
|
2009-01-03 22:22:43 +01:00
|
|
|
/*
|
2020-02-03 10:40:36 +01:00
|
|
|
* HANDSHAKE STATE: Incoming `Certificate`
|
2009-01-03 22:22:43 +01:00
|
|
|
*/
|
2020-02-03 10:40:36 +01:00
|
|
|
|
|
|
|
#if !defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED)
|
|
|
|
|
|
|
|
int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
|
2012-09-13 16:23:06 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
|
|
|
|
ssl->handshake->ciphersuite_info;
|
2012-09-13 16:23:06 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) );
|
2014-06-26 12:09:34 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
if( !mbedtls_ssl_ciphersuite_uses_srv_cert( ciphersuite_info ) )
|
2012-09-13 16:23:06 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
|
|
|
|
ssl->state++;
|
|
|
|
return( 0 );
|
|
|
|
}
|
2012-09-13 16:23:06 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
|
|
|
|
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
|
|
|
|
}
|
2017-06-29 18:09:42 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
#else /* MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */
|
2017-06-29 18:09:42 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
/* Check if a certificate message is expected.
|
|
|
|
* Return either
|
|
|
|
* - SSL_CERTIFICATE_EXPECTED, or
|
|
|
|
* - SSL_CERTIFICATE_SKIP
|
|
|
|
* indicating whether a Certificate message is expected or not.
|
|
|
|
*/
|
|
|
|
#define SSL_CERTIFICATE_EXPECTED 0
|
|
|
|
#define SSL_CERTIFICATE_SKIP 1
|
|
|
|
static int ssl_parse_certificate_coordinate( mbedtls_ssl_context *ssl,
|
|
|
|
int authmode );
|
|
|
|
static int ssl_parse_certificate_chain( mbedtls_ssl_context *ssl,
|
|
|
|
mbedtls_x509_crt *chain );
|
|
|
|
static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl,
|
|
|
|
int authmode,
|
|
|
|
mbedtls_x509_crt *chain,
|
|
|
|
void *rs_ctx );
|
2012-09-13 16:23:06 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
#if defined(MBEDTLS_SSL_SRV_C)
|
|
|
|
static int ssl_srv_check_client_no_crt_notification( mbedtls_ssl_context *ssl );
|
|
|
|
#endif /* MBEDTLS_SSL_SRV_C */
|
2012-09-13 16:23:06 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
|
|
|
static int ssl_remember_peer_crt_digest( mbedtls_ssl_context *ssl,
|
|
|
|
unsigned char *start, size_t len );
|
|
|
|
static int ssl_remember_peer_pubkey( mbedtls_ssl_context *ssl,
|
|
|
|
unsigned char *start, size_t len );
|
|
|
|
#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
2012-09-13 16:23:06 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
|
2009-01-03 22:22:43 +01:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
int ret = 0;
|
|
|
|
int crt_expected;
|
|
|
|
#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
|
|
|
|
const int authmode = ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET
|
|
|
|
? ssl->handshake->sni_authmode
|
|
|
|
: ssl->conf->authmode;
|
|
|
|
#else
|
|
|
|
const int authmode = ssl->conf->authmode;
|
|
|
|
#endif
|
|
|
|
void *rs_ctx = NULL;
|
|
|
|
mbedtls_x509_crt *chain = NULL;
|
2015-03-26 11:41:28 +01:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) );
|
2009-01-03 22:22:43 +01:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
crt_expected = ssl_parse_certificate_coordinate( ssl, authmode );
|
|
|
|
if( crt_expected == SSL_CERTIFICATE_SKIP )
|
2019-05-07 17:31:49 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
|
2019-05-07 17:31:49 +02:00
|
|
|
goto exit;
|
|
|
|
}
|
2009-01-03 22:22:43 +01:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
|
|
|
|
if( ssl->handshake->ecrs_enabled &&
|
|
|
|
ssl->handshake->ecrs_state == ssl_ecrs_crt_verify )
|
2019-05-07 17:31:49 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
chain = ssl->handshake->ecrs_peer_cert;
|
|
|
|
ssl->handshake->ecrs_peer_cert = NULL;
|
|
|
|
goto crt_verify;
|
2019-05-07 17:31:49 +02:00
|
|
|
}
|
2020-02-03 10:40:36 +01:00
|
|
|
#endif
|
2015-03-24 18:08:19 +01:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
|
2019-05-07 17:31:49 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
/* mbedtls_ssl_read_record may have sent an alert already. We
|
|
|
|
let it decide whether to alert. */
|
|
|
|
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
|
2019-05-07 17:31:49 +02:00
|
|
|
goto exit;
|
|
|
|
}
|
2015-03-26 11:41:28 +01:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
#if defined(MBEDTLS_SSL_SRV_C)
|
|
|
|
if( ssl_srv_check_client_no_crt_notification( ssl ) == 0 )
|
2009-01-03 22:22:43 +01:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING;
|
2009-01-03 22:22:43 +01:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL )
|
|
|
|
ret = 0;
|
|
|
|
else
|
|
|
|
ret = MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE;
|
2009-01-03 22:22:43 +01:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
goto exit;
|
2009-01-03 22:22:43 +01:00
|
|
|
}
|
2020-02-03 10:40:36 +01:00
|
|
|
#endif /* MBEDTLS_SSL_SRV_C */
|
2009-01-03 22:22:43 +01:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
/* Clear existing peer CRT structure in case we tried to
|
|
|
|
* reuse a session but it failed, and allocate a new one. */
|
|
|
|
mbedtls_ssl_clear_peer_cert( ssl->session_negotiate );
|
2015-03-26 11:41:28 +01:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
chain = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) );
|
|
|
|
if( chain == NULL )
|
2019-05-07 17:31:49 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed",
|
|
|
|
sizeof( mbedtls_x509_crt ) ) );
|
|
|
|
mbedtls_ssl_send_alert_message( ssl,
|
|
|
|
MBEDTLS_SSL_ALERT_LEVEL_FATAL,
|
|
|
|
MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
|
|
|
|
|
|
|
|
ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
|
2019-05-07 17:31:49 +02:00
|
|
|
goto exit;
|
|
|
|
}
|
2020-02-03 10:40:36 +01:00
|
|
|
mbedtls_x509_crt_init( chain );
|
2015-03-24 18:08:19 +01:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
ret = ssl_parse_certificate_chain( ssl, chain );
|
|
|
|
if( ret != 0 )
|
2019-05-07 17:31:49 +02:00
|
|
|
goto exit;
|
2019-08-17 10:30:28 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
|
|
|
|
if( ssl->handshake->ecrs_enabled)
|
|
|
|
ssl->handshake->ecrs_state = ssl_ecrs_crt_verify;
|
2019-08-17 10:30:28 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
crt_verify:
|
|
|
|
if( ssl->handshake->ecrs_enabled)
|
|
|
|
rs_ctx = &ssl->handshake->ecrs_ctx;
|
|
|
|
#endif
|
2019-08-17 10:30:28 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
ret = ssl_parse_certificate_verify( ssl, authmode,
|
|
|
|
chain, rs_ctx );
|
|
|
|
if( ret != 0 )
|
|
|
|
goto exit;
|
2019-08-17 10:30:28 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
2019-08-17 10:30:28 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
unsigned char *crt_start, *pk_start;
|
|
|
|
size_t crt_len, pk_len;
|
2019-08-17 10:30:28 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
/* We parse the CRT chain without copying, so
|
|
|
|
* these pointers point into the input buffer,
|
|
|
|
* and are hence still valid after freeing the
|
|
|
|
* CRT chain. */
|
2019-08-17 10:30:28 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
crt_start = chain->raw.p;
|
|
|
|
crt_len = chain->raw.len;
|
2019-01-14 09:51:11 +01:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
pk_start = chain->pk_raw.p;
|
|
|
|
pk_len = chain->pk_raw.len;
|
2019-01-14 09:51:11 +01:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
/* Free the CRT structures before computing
|
|
|
|
* digest and copying the peer's public key. */
|
|
|
|
mbedtls_x509_crt_free( chain );
|
|
|
|
mbedtls_free( chain );
|
|
|
|
chain = NULL;
|
2019-01-14 09:51:11 +01:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
ret = ssl_remember_peer_crt_digest( ssl, crt_start, crt_len );
|
|
|
|
if( ret != 0 )
|
|
|
|
goto exit;
|
2019-01-14 09:51:11 +01:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
ret = ssl_remember_peer_pubkey( ssl, pk_start, pk_len );
|
|
|
|
if( ret != 0 )
|
|
|
|
goto exit;
|
2019-01-14 11:37:13 +01:00
|
|
|
}
|
2020-02-03 10:40:36 +01:00
|
|
|
#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
|
|
|
/* Pass ownership to session structure. */
|
|
|
|
ssl->session_negotiate->peer_cert = chain;
|
|
|
|
chain = NULL;
|
|
|
|
#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
2019-01-14 09:51:11 +01:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) );
|
2012-04-11 14:09:53 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
exit:
|
2015-03-26 11:11:49 +01:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
if( ret == 0 )
|
|
|
|
ssl->state++;
|
2015-03-26 11:11:49 +01:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
|
|
|
|
if( ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS )
|
2019-05-07 17:31:49 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
ssl->handshake->ecrs_peer_cert = chain;
|
|
|
|
chain = NULL;
|
2019-05-07 17:31:49 +02:00
|
|
|
}
|
2020-02-03 10:40:36 +01:00
|
|
|
#endif
|
2012-04-11 14:09:53 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
if( chain != NULL )
|
2012-04-11 14:09:53 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
mbedtls_x509_crt_free( chain );
|
|
|
|
mbedtls_free( chain );
|
2012-04-11 14:09:53 +02:00
|
|
|
}
|
|
|
|
|
2019-05-07 17:31:49 +02:00
|
|
|
return( ret );
|
2012-04-11 14:09:53 +02:00
|
|
|
}
|
2012-11-24 11:26:46 +01:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C)
|
2012-04-11 14:09:53 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
|
|
|
static int ssl_check_peer_crt_unchanged( mbedtls_ssl_context *ssl,
|
|
|
|
unsigned char *crt_buf,
|
|
|
|
size_t crt_buf_len )
|
2018-10-23 16:26:22 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
mbedtls_x509_crt const * const peer_crt = ssl->session->peer_cert;
|
2018-10-23 16:26:22 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
if( peer_crt == NULL )
|
|
|
|
return( -1 );
|
2018-10-23 16:26:22 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
if( peer_crt->raw.len != crt_buf_len )
|
|
|
|
return( -1 );
|
2018-10-23 16:26:22 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
return( memcmp( peer_crt->raw.p, crt_buf, peer_crt->raw.len ) );
|
2018-10-23 16:26:22 +02:00
|
|
|
}
|
2020-02-03 10:40:36 +01:00
|
|
|
#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
|
|
|
static int ssl_check_peer_crt_unchanged( mbedtls_ssl_context *ssl,
|
|
|
|
unsigned char *crt_buf,
|
|
|
|
size_t crt_buf_len )
|
2019-05-14 19:19:13 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
|
|
|
unsigned char const * const peer_cert_digest =
|
|
|
|
ssl->session->peer_cert_digest;
|
|
|
|
mbedtls_md_type_t const peer_cert_digest_type =
|
|
|
|
ssl->session->peer_cert_digest_type;
|
|
|
|
mbedtls_md_info_t const * const digest_info =
|
|
|
|
mbedtls_md_info_from_type( peer_cert_digest_type );
|
|
|
|
unsigned char tmp_digest[MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN];
|
|
|
|
size_t digest_len;
|
2019-05-14 19:19:13 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
if( peer_cert_digest == NULL || digest_info == NULL )
|
|
|
|
return( -1 );
|
2019-05-12 13:54:30 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
digest_len = mbedtls_md_get_size( digest_info );
|
|
|
|
if( digest_len > MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN )
|
|
|
|
return( -1 );
|
2019-05-12 13:54:30 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
ret = mbedtls_md( digest_info, crt_buf, crt_buf_len, tmp_digest );
|
|
|
|
if( ret != 0 )
|
|
|
|
return( -1 );
|
2019-05-12 13:54:30 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
return( memcmp( tmp_digest, peer_cert_digest, digest_len ) );
|
|
|
|
}
|
|
|
|
#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
|
|
|
#endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */
|
2019-05-06 13:32:17 +02:00
|
|
|
|
2019-04-30 11:41:40 +02:00
|
|
|
/*
|
2020-02-03 10:40:36 +01:00
|
|
|
* Once the certificate message is read, parse it into a cert chain and
|
|
|
|
* perform basic checks, but leave actual verification to the caller
|
2019-04-30 11:41:40 +02:00
|
|
|
*/
|
2020-02-03 10:40:36 +01:00
|
|
|
static int ssl_parse_certificate_chain( mbedtls_ssl_context *ssl,
|
|
|
|
mbedtls_x509_crt *chain )
|
2009-01-03 22:22:43 +01:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
|
|
|
#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C)
|
|
|
|
int crt_cnt=0;
|
2019-07-09 12:54:17 +02:00
|
|
|
#endif
|
2020-02-03 10:40:36 +01:00
|
|
|
size_t i, n;
|
|
|
|
uint8_t alert;
|
2019-07-09 12:54:17 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE )
|
2013-01-07 18:20:04 +01:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
|
|
|
|
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
|
|
|
|
MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
|
|
|
|
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
|
2013-01-07 18:20:04 +01:00
|
|
|
}
|
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
if( ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE ||
|
|
|
|
ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 3 + 3 )
|
2013-01-07 18:20:04 +01:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
|
|
|
|
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
|
|
|
|
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
|
|
|
|
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE );
|
2013-01-07 18:20:04 +01:00
|
|
|
}
|
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
i = mbedtls_ssl_hs_hdr_len( ssl );
|
2019-04-26 17:22:27 +02:00
|
|
|
|
2009-01-03 22:22:43 +01:00
|
|
|
/*
|
2020-02-03 10:40:36 +01:00
|
|
|
* Same message structure as in mbedtls_ssl_write_certificate()
|
2009-01-03 22:22:43 +01:00
|
|
|
*/
|
2020-02-03 10:40:36 +01:00
|
|
|
n = ( ssl->in_msg[i+1] << 8 ) | ssl->in_msg[i+2];
|
|
|
|
|
|
|
|
if( ssl->in_msg[i] != 0 ||
|
|
|
|
ssl->in_hslen != n + 3 + mbedtls_ssl_hs_hdr_len( ssl ) )
|
2015-03-26 11:47:47 +01:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
|
|
|
|
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
|
|
|
|
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
|
|
|
|
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE );
|
2015-03-26 11:47:47 +01:00
|
|
|
}
|
2009-01-03 22:22:43 +01:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
/* Make &ssl->in_msg[i] point to the beginning of the CRT chain. */
|
|
|
|
i += 3;
|
2014-06-18 15:34:40 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
/* Iterate through and parse the CRTs in the provided chain. */
|
|
|
|
while( i < ssl->in_hslen )
|
2013-01-07 18:20:04 +01:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
/* Check that there's room for the next CRT's length fields. */
|
|
|
|
if ( i + 3 > ssl->in_hslen ) {
|
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
|
|
|
|
mbedtls_ssl_send_alert_message( ssl,
|
|
|
|
MBEDTLS_SSL_ALERT_LEVEL_FATAL,
|
|
|
|
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
|
|
|
|
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE );
|
|
|
|
}
|
|
|
|
/* In theory, the CRT can be up to 2**24 Bytes, but we don't support
|
|
|
|
* anything beyond 2**16 ~ 64K. */
|
|
|
|
if( ssl->in_msg[i] != 0 )
|
2014-06-18 15:34:40 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
|
|
|
|
mbedtls_ssl_send_alert_message( ssl,
|
|
|
|
MBEDTLS_SSL_ALERT_LEVEL_FATAL,
|
|
|
|
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
|
|
|
|
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE );
|
2014-06-18 15:34:40 +02:00
|
|
|
}
|
2012-02-06 17:45:10 +01:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
/* Read length of the next CRT in the chain. */
|
|
|
|
n = ( (unsigned int) ssl->in_msg[i + 1] << 8 )
|
|
|
|
| (unsigned int) ssl->in_msg[i + 2];
|
|
|
|
i += 3;
|
2013-07-19 12:19:21 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
if( n < 128 || i + n > ssl->in_hslen )
|
2017-11-20 17:36:41 +01:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
|
|
|
|
mbedtls_ssl_send_alert_message( ssl,
|
|
|
|
MBEDTLS_SSL_ALERT_LEVEL_FATAL,
|
|
|
|
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
|
|
|
|
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE );
|
2017-11-20 17:36:41 +01:00
|
|
|
}
|
2012-02-06 17:45:10 +01:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
/* Check if we're handling the first CRT in the chain. */
|
|
|
|
#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C)
|
|
|
|
if( crt_cnt++ == 0 &&
|
|
|
|
ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&
|
|
|
|
ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS )
|
2013-01-07 18:20:04 +01:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
/* During client-side renegotiation, check that the server's
|
|
|
|
* end-CRTs hasn't changed compared to the initial handshake,
|
|
|
|
* mitigating the triple handshake attack. On success, reuse
|
|
|
|
* the original end-CRT instead of parsing it again. */
|
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 3, ( "Check that peer CRT hasn't changed during renegotiation" ) );
|
|
|
|
if( ssl_check_peer_crt_unchanged( ssl,
|
|
|
|
&ssl->in_msg[i],
|
|
|
|
n ) != 0 )
|
2014-06-18 16:06:02 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 1, ( "new server cert during renegotiation" ) );
|
|
|
|
mbedtls_ssl_send_alert_message( ssl,
|
|
|
|
MBEDTLS_SSL_ALERT_LEVEL_FATAL,
|
|
|
|
MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED );
|
|
|
|
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE );
|
2014-06-18 16:06:02 +02:00
|
|
|
}
|
2009-01-03 22:22:43 +01:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
/* Now we can safely free the original chain. */
|
|
|
|
mbedtls_ssl_clear_peer_cert( ssl->session );
|
2018-03-19 19:06:08 +01:00
|
|
|
}
|
2020-02-03 10:40:36 +01:00
|
|
|
#endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */
|
2012-05-08 11:17:57 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
/* Parse the next certificate in the chain. */
|
|
|
|
#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
|
|
|
ret = mbedtls_x509_crt_parse_der( chain, ssl->in_msg + i, n );
|
2018-01-03 16:32:51 +01:00
|
|
|
#else
|
2020-02-03 10:40:36 +01:00
|
|
|
/* If we don't need to store the CRT chain permanently, parse
|
|
|
|
* it in-place from the input buffer instead of making a copy. */
|
|
|
|
ret = mbedtls_x509_crt_parse_der_nocopy( chain, ssl->in_msg + i, n );
|
|
|
|
#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
|
|
|
switch( ret )
|
2018-11-17 23:27:38 +01:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
case 0: /*ok*/
|
|
|
|
case MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + MBEDTLS_ERR_OID_NOT_FOUND:
|
|
|
|
/* Ignore certificate with an unknown algorithm: maybe a
|
|
|
|
prior certificate was already trusted. */
|
|
|
|
break;
|
2018-11-16 16:21:18 +01:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
case MBEDTLS_ERR_X509_ALLOC_FAILED:
|
|
|
|
alert = MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR;
|
|
|
|
goto crt_parse_der_failed;
|
2013-08-31 17:25:14 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
case MBEDTLS_ERR_X509_UNKNOWN_VERSION:
|
|
|
|
alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
|
|
|
|
goto crt_parse_der_failed;
|
2018-11-16 16:21:18 +01:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
default:
|
|
|
|
alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT;
|
|
|
|
crt_parse_der_failed:
|
|
|
|
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, alert );
|
|
|
|
MBEDTLS_SSL_DEBUG_RET( 1, " mbedtls_x509_crt_parse_der", ret );
|
|
|
|
return( ret );
|
2018-11-17 23:27:38 +01:00
|
|
|
}
|
2013-08-31 17:25:14 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
i += n;
|
2013-10-25 18:42:44 +02:00
|
|
|
}
|
2013-10-25 18:33:32 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_CRT( 3, "peer certificate", chain );
|
|
|
|
return( 0 );
|
|
|
|
}
|
2013-10-25 18:42:44 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
|
|
|
static int ssl_remember_peer_crt_digest( mbedtls_ssl_context *ssl,
|
|
|
|
unsigned char *start, size_t len )
|
|
|
|
{
|
|
|
|
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
|
|
|
/* Remember digest of the peer's end-CRT. */
|
|
|
|
ssl->session_negotiate->peer_cert_digest =
|
|
|
|
mbedtls_calloc( 1, MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN );
|
|
|
|
if( ssl->session_negotiate->peer_cert_digest == NULL )
|
2013-10-25 18:42:44 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed",
|
|
|
|
MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN ) );
|
|
|
|
mbedtls_ssl_send_alert_message( ssl,
|
|
|
|
MBEDTLS_SSL_ALERT_LEVEL_FATAL,
|
|
|
|
MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
|
2013-09-02 14:57:01 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
|
2009-01-03 22:22:43 +01:00
|
|
|
}
|
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
ret = mbedtls_md( mbedtls_md_info_from_type(
|
|
|
|
MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE ),
|
|
|
|
start, len,
|
|
|
|
ssl->session_negotiate->peer_cert_digest );
|
2009-01-03 22:22:43 +01:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
ssl->session_negotiate->peer_cert_digest_type =
|
|
|
|
MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE;
|
|
|
|
ssl->session_negotiate->peer_cert_digest_len =
|
|
|
|
MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN;
|
2012-07-03 15:30:23 +02:00
|
|
|
|
2019-05-07 17:27:13 +02:00
|
|
|
return( ret );
|
2009-01-03 22:22:43 +01:00
|
|
|
}
|
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
static int ssl_remember_peer_pubkey( mbedtls_ssl_context *ssl,
|
|
|
|
unsigned char *start, size_t len )
|
2019-04-30 11:54:22 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
unsigned char *end = start + len;
|
|
|
|
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
2019-07-11 12:50:53 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
/* Make a copy of the peer's raw public key. */
|
|
|
|
mbedtls_pk_init( &ssl->handshake->peer_pubkey );
|
|
|
|
ret = mbedtls_pk_parse_subpubkey( &start, end,
|
|
|
|
&ssl->handshake->peer_pubkey );
|
2019-07-11 12:50:53 +02:00
|
|
|
if( ret != 0 )
|
2020-02-03 10:40:36 +01:00
|
|
|
{
|
|
|
|
/* We should have parsed the public key before. */
|
|
|
|
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
|
2015-06-17 13:53:47 +02:00
|
|
|
}
|
|
|
|
|
2015-05-04 13:35:39 +02:00
|
|
|
return( 0 );
|
|
|
|
}
|
2020-02-03 10:40:36 +01:00
|
|
|
#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
2015-05-04 13:35:39 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
#if defined(MBEDTLS_SSL_SRV_C)
|
|
|
|
static int ssl_srv_check_client_no_crt_notification( mbedtls_ssl_context *ssl )
|
2015-05-04 13:35:39 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT )
|
|
|
|
return( -1 );
|
2015-05-04 13:35:39 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
#if defined(MBEDTLS_SSL_PROTO_SSL3)
|
|
|
|
/*
|
|
|
|
* Check if the client sent an empty certificate
|
|
|
|
*/
|
|
|
|
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
|
2015-05-04 13:35:39 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
if( ssl->in_msglen == 2 &&
|
|
|
|
ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT &&
|
|
|
|
ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING &&
|
|
|
|
ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_CERT )
|
|
|
|
{
|
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 1, ( "SSLv3 client has no certificate" ) );
|
|
|
|
return( 0 );
|
|
|
|
}
|
|
|
|
|
|
|
|
return( -1 );
|
2017-12-20 08:29:30 +01:00
|
|
|
}
|
2020-02-03 10:40:36 +01:00
|
|
|
#endif /* MBEDTLS_SSL_PROTO_SSL3 */
|
2017-12-20 08:29:30 +01:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
|
|
|
|
defined(MBEDTLS_SSL_PROTO_TLS1_2)
|
|
|
|
if( ssl->in_hslen == 3 + mbedtls_ssl_hs_hdr_len( ssl ) &&
|
|
|
|
ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
|
|
|
|
ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE &&
|
|
|
|
memcmp( ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ), "\0\0\0", 3 ) == 0 )
|
2017-12-20 08:29:30 +01:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLSv1 client has no certificate" ) );
|
|
|
|
return( 0 );
|
2015-05-04 13:35:39 +02:00
|
|
|
}
|
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
return( -1 );
|
|
|
|
#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \
|
|
|
|
MBEDTLS_SSL_PROTO_TLS1_2 */
|
2015-05-04 13:35:39 +02:00
|
|
|
}
|
2020-02-03 10:40:36 +01:00
|
|
|
#endif /* MBEDTLS_SSL_SRV_C */
|
2015-05-04 13:35:39 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
static int ssl_parse_certificate_coordinate( mbedtls_ssl_context *ssl,
|
|
|
|
int authmode )
|
2013-08-21 16:14:26 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
|
|
|
|
ssl->handshake->ciphersuite_info;
|
2013-08-21 16:14:26 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
if( !mbedtls_ssl_ciphersuite_uses_srv_cert( ciphersuite_info ) )
|
|
|
|
return( SSL_CERTIFICATE_SKIP );
|
2017-04-28 18:15:26 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
#if defined(MBEDTLS_SSL_SRV_C)
|
|
|
|
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER )
|
2013-08-22 13:52:48 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK )
|
|
|
|
return( SSL_CERTIFICATE_SKIP );
|
2017-04-28 18:15:26 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
if( authmode == MBEDTLS_SSL_VERIFY_NONE )
|
|
|
|
{
|
|
|
|
ssl->session_negotiate->verify_result =
|
|
|
|
MBEDTLS_X509_BADCERT_SKIP_VERIFY;
|
|
|
|
return( SSL_CERTIFICATE_SKIP );
|
|
|
|
}
|
2017-04-28 18:15:26 +02:00
|
|
|
}
|
2020-02-03 10:40:36 +01:00
|
|
|
#else
|
|
|
|
((void) authmode);
|
|
|
|
#endif /* MBEDTLS_SSL_SRV_C */
|
2017-04-28 18:15:26 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
return( SSL_CERTIFICATE_EXPECTED );
|
2017-04-28 18:15:26 +02:00
|
|
|
}
|
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl,
|
|
|
|
int authmode,
|
|
|
|
mbedtls_x509_crt *chain,
|
|
|
|
void *rs_ctx )
|
2017-04-28 18:15:26 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
int ret = 0;
|
|
|
|
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
|
|
|
|
ssl->handshake->ciphersuite_info;
|
|
|
|
int have_ca_chain = 0;
|
2017-04-28 18:15:26 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *);
|
|
|
|
void *p_vrfy;
|
2017-04-28 18:15:26 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
if( authmode == MBEDTLS_SSL_VERIFY_NONE )
|
|
|
|
return( 0 );
|
|
|
|
|
|
|
|
if( ssl->f_vrfy != NULL )
|
2013-08-22 13:52:48 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 3, ( "Use context-specific verification callback" ) );
|
|
|
|
f_vrfy = ssl->f_vrfy;
|
|
|
|
p_vrfy = ssl->p_vrfy;
|
2013-08-22 13:52:48 +02:00
|
|
|
}
|
2020-02-03 10:40:36 +01:00
|
|
|
else
|
2015-06-17 14:34:48 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 3, ( "Use configuration-specific verification callback" ) );
|
|
|
|
f_vrfy = ssl->conf->f_vrfy;
|
|
|
|
p_vrfy = ssl->conf->p_vrfy;
|
2015-06-17 14:34:48 +02:00
|
|
|
}
|
2015-06-17 12:10:46 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
/*
|
|
|
|
* Main check: verify certificate
|
|
|
|
*/
|
|
|
|
#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
|
|
|
|
if( ssl->conf->f_ca_cb != NULL )
|
|
|
|
{
|
|
|
|
((void) rs_ctx);
|
|
|
|
have_ca_chain = 1;
|
2014-02-04 16:18:07 +01:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 3, ( "use CA callback for X.509 CRT verification" ) );
|
|
|
|
ret = mbedtls_x509_crt_verify_with_ca_cb(
|
|
|
|
chain,
|
|
|
|
ssl->conf->f_ca_cb,
|
|
|
|
ssl->conf->p_ca_cb,
|
|
|
|
ssl->conf->cert_profile,
|
|
|
|
ssl->hostname,
|
|
|
|
&ssl->session_negotiate->verify_result,
|
|
|
|
f_vrfy, p_vrfy );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
|
|
|
|
{
|
|
|
|
mbedtls_x509_crt *ca_chain;
|
|
|
|
mbedtls_x509_crl *ca_crl;
|
2014-04-09 09:50:57 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
|
|
|
|
if( ssl->handshake->sni_ca_chain != NULL )
|
|
|
|
{
|
|
|
|
ca_chain = ssl->handshake->sni_ca_chain;
|
|
|
|
ca_crl = ssl->handshake->sni_ca_crl;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
ca_chain = ssl->conf->ca_chain;
|
|
|
|
ca_crl = ssl->conf->ca_crl;
|
|
|
|
}
|
2015-06-17 14:34:48 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
if( ca_chain != NULL )
|
|
|
|
have_ca_chain = 1;
|
2015-06-17 14:34:48 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
ret = mbedtls_x509_crt_verify_restartable(
|
|
|
|
chain,
|
|
|
|
ca_chain, ca_crl,
|
|
|
|
ssl->conf->cert_profile,
|
|
|
|
ssl->hostname,
|
|
|
|
&ssl->session_negotiate->verify_result,
|
|
|
|
f_vrfy, p_vrfy, rs_ctx );
|
|
|
|
}
|
2015-06-17 14:34:48 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
if( ret != 0 )
|
|
|
|
{
|
|
|
|
MBEDTLS_SSL_DEBUG_RET( 1, "x509_verify_cert", ret );
|
|
|
|
}
|
2015-06-17 14:34:48 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
|
|
|
|
if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
|
|
|
|
return( MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS );
|
2014-04-11 11:06:22 +02:00
|
|
|
#endif
|
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
/*
|
|
|
|
* Secondary checks: always done, but change 'ret' only if it was 0
|
|
|
|
*/
|
2014-04-09 09:50:57 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
#if defined(MBEDTLS_ECP_C)
|
2014-04-09 09:50:57 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
const mbedtls_pk_context *pk = &chain->pk;
|
|
|
|
|
|
|
|
/* If certificate uses an EC key, make sure the curve is OK */
|
|
|
|
if( mbedtls_pk_can_do( pk, MBEDTLS_PK_ECKEY ) &&
|
|
|
|
mbedtls_ssl_check_curve( ssl, mbedtls_pk_ec( *pk )->grp.id ) != 0 )
|
2014-04-09 09:50:57 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
ssl->session_negotiate->verify_result |= MBEDTLS_X509_BADCERT_BAD_KEY;
|
2014-04-09 09:50:57 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate (EC key curve)" ) );
|
|
|
|
if( ret == 0 )
|
|
|
|
ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* MBEDTLS_ECP_C */
|
2014-04-09 09:50:57 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
if( mbedtls_ssl_check_cert_usage( chain,
|
|
|
|
ciphersuite_info,
|
|
|
|
! ssl->conf->endpoint,
|
|
|
|
&ssl->session_negotiate->verify_result ) != 0 )
|
|
|
|
{
|
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate (usage extensions)" ) );
|
|
|
|
if( ret == 0 )
|
|
|
|
ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE;
|
|
|
|
}
|
2014-04-09 09:50:57 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
/* mbedtls_x509_crt_verify_with_profile is supposed to report a
|
|
|
|
* verification failure through MBEDTLS_ERR_X509_CERT_VERIFY_FAILED,
|
|
|
|
* with details encoded in the verification flags. All other kinds
|
|
|
|
* of error codes, including those from the user provided f_vrfy
|
|
|
|
* functions, are treated as fatal and lead to a failure of
|
|
|
|
* ssl_parse_certificate even if verification was optional. */
|
|
|
|
if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL &&
|
|
|
|
( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ||
|
|
|
|
ret == MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ) )
|
|
|
|
{
|
|
|
|
ret = 0;
|
2014-04-09 09:50:57 +02:00
|
|
|
}
|
2020-02-03 10:40:36 +01:00
|
|
|
|
|
|
|
if( have_ca_chain == 0 && authmode == MBEDTLS_SSL_VERIFY_REQUIRED )
|
2014-04-09 09:50:57 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no CA chain" ) );
|
|
|
|
ret = MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED;
|
2014-04-09 09:50:57 +02:00
|
|
|
}
|
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
if( ret != 0 )
|
2015-04-20 12:01:48 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
uint8_t alert;
|
|
|
|
|
|
|
|
/* The certificate may have been rejected for several reasons.
|
|
|
|
Pick one and send the corresponding alert. Which alert to send
|
|
|
|
may be a subject of debate in some cases. */
|
|
|
|
if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_OTHER )
|
|
|
|
alert = MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED;
|
|
|
|
else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_CN_MISMATCH )
|
|
|
|
alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT;
|
|
|
|
else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_KEY_USAGE )
|
|
|
|
alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
|
|
|
|
else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXT_KEY_USAGE )
|
|
|
|
alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
|
|
|
|
else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NS_CERT_TYPE )
|
|
|
|
alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
|
|
|
|
else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_PK )
|
|
|
|
alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
|
|
|
|
else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_KEY )
|
|
|
|
alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
|
|
|
|
else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXPIRED )
|
|
|
|
alert = MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED;
|
|
|
|
else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_REVOKED )
|
|
|
|
alert = MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED;
|
|
|
|
else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NOT_TRUSTED )
|
|
|
|
alert = MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA;
|
|
|
|
else
|
|
|
|
alert = MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN;
|
|
|
|
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
|
|
|
|
alert );
|
2015-04-20 12:01:48 +02:00
|
|
|
}
|
2014-04-09 09:50:57 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
#if defined(MBEDTLS_DEBUG_C)
|
|
|
|
if( ssl->session_negotiate->verify_result != 0 )
|
2014-04-11 11:06:22 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 3, ( "! Certificate verification flags %x",
|
|
|
|
ssl->session_negotiate->verify_result ) );
|
2014-04-11 11:06:22 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 3, ( "Certificate verification flags clear" ) );
|
2015-04-20 12:01:48 +02:00
|
|
|
}
|
2020-02-03 10:40:36 +01:00
|
|
|
#endif /* MBEDTLS_DEBUG_C */
|
2014-04-11 11:06:22 +02:00
|
|
|
|
2015-04-20 12:01:48 +02:00
|
|
|
return( ret );
|
2014-04-09 09:50:57 +02:00
|
|
|
}
|
2014-04-29 15:11:17 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
#endif /* MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */
|
2016-10-13 18:21:01 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
/*
|
|
|
|
* HANDSHAKE STATE: Outgoing `Finished`
|
|
|
|
*/
|
2016-10-13 18:21:01 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl )
|
|
|
|
{
|
|
|
|
int ret, hash_len;
|
2016-10-13 18:21:01 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write finished" ) );
|
2016-10-13 18:21:01 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
mbedtls_ssl_update_out_pointers( ssl, ssl->transform_negotiate );
|
2017-07-20 17:17:51 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
ssl->handshake->calc_finished( ssl, ssl->out_msg + 4, ssl->conf->endpoint );
|
2017-07-20 17:17:51 +02:00
|
|
|
|
|
|
|
/*
|
2020-02-03 10:40:36 +01:00
|
|
|
* RFC 5246 7.4.9 (Page 63) says 12 is the default length and ciphersuites
|
|
|
|
* may define some other value. Currently (early 2016), no defined
|
|
|
|
* ciphersuite does this (and this is unlikely to change as activity has
|
|
|
|
* moved to TLS 1.3 now) so we can keep the hardcoded 12 here.
|
2017-07-20 17:17:51 +02:00
|
|
|
*/
|
2020-02-03 10:40:36 +01:00
|
|
|
hash_len = ( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) ? 36 : 12;
|
2017-07-20 17:17:51 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
#if defined(MBEDTLS_SSL_RENEGOTIATION)
|
|
|
|
ssl->verify_data_len = hash_len;
|
|
|
|
memcpy( ssl->own_verify_data, ssl->out_msg + 4, hash_len );
|
|
|
|
#endif
|
|
|
|
|
|
|
|
ssl->out_msglen = 4 + hash_len;
|
|
|
|
ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
|
|
|
|
ssl->out_msg[0] = MBEDTLS_SSL_HS_FINISHED;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* In case of session resuming, invert the client and server
|
|
|
|
* ChangeCipherSpec messages order.
|
|
|
|
*/
|
|
|
|
if( ssl->handshake->resume != 0 )
|
2017-07-20 17:17:51 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
#if defined(MBEDTLS_SSL_CLI_C)
|
|
|
|
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT )
|
|
|
|
ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP;
|
|
|
|
#endif
|
|
|
|
#if defined(MBEDTLS_SSL_SRV_C)
|
|
|
|
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER )
|
|
|
|
ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC;
|
|
|
|
#endif
|
2017-07-20 17:17:51 +02:00
|
|
|
}
|
2020-02-03 10:40:36 +01:00
|
|
|
else
|
|
|
|
ssl->state++;
|
2017-07-20 17:17:51 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
/*
|
|
|
|
* Switch to our negotiated transform and session parameters for outbound
|
|
|
|
* data.
|
|
|
|
*/
|
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 3, ( "switching to new transform spec for outbound data" ) );
|
2017-07-20 17:17:51 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
|
|
|
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
|
|
|
|
{
|
|
|
|
unsigned char i;
|
2017-07-20 17:17:51 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
/* Remember current epoch settings for resending */
|
|
|
|
ssl->handshake->alt_transform_out = ssl->transform_out;
|
|
|
|
memcpy( ssl->handshake->alt_out_ctr, ssl->cur_out_ctr, 8 );
|
2017-07-20 17:17:51 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
/* Set sequence_number to zero */
|
|
|
|
memset( ssl->cur_out_ctr + 2, 0, 6 );
|
2017-07-20 17:17:51 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
/* Increment epoch */
|
|
|
|
for( i = 2; i > 0; i-- )
|
|
|
|
if( ++ssl->cur_out_ctr[i - 1] != 0 )
|
|
|
|
break;
|
2019-01-10 11:27:10 +01:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
/* The loop goes to its end iff the counter is wrapping */
|
|
|
|
if( i == 0 )
|
|
|
|
{
|
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS epoch would wrap" ) );
|
|
|
|
return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif /* MBEDTLS_SSL_PROTO_DTLS */
|
|
|
|
memset( ssl->cur_out_ctr, 0, 8 );
|
2019-01-10 11:27:10 +01:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
ssl->transform_out = ssl->transform_negotiate;
|
|
|
|
ssl->session_out = ssl->session_negotiate;
|
2019-01-14 10:35:19 +01:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
|
|
|
|
if( mbedtls_ssl_hw_record_activate != NULL )
|
2019-01-10 11:27:10 +01:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
if( ( ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_OUTBOUND ) ) != 0 )
|
|
|
|
{
|
|
|
|
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret );
|
|
|
|
return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
|
|
|
|
}
|
2019-01-10 11:27:10 +01:00
|
|
|
}
|
2020-02-03 10:40:36 +01:00
|
|
|
#endif
|
2019-01-10 11:27:10 +01:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
|
|
|
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
|
|
|
|
mbedtls_ssl_send_flight_completed( ssl );
|
|
|
|
#endif
|
2019-01-10 11:27:10 +01:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
|
2019-01-10 11:27:10 +01:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
|
|
|
|
return( ret );
|
2019-01-10 11:27:10 +01:00
|
|
|
}
|
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
|
|
|
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
|
|
|
|
( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
|
2019-01-10 11:27:10 +01:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret );
|
|
|
|
return( ret );
|
2019-01-10 11:27:10 +01:00
|
|
|
}
|
2020-02-03 10:40:36 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write finished" ) );
|
2019-01-10 11:27:10 +01:00
|
|
|
|
|
|
|
return( 0 );
|
|
|
|
}
|
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
#if defined(MBEDTLS_SSL_PROTO_SSL3)
|
|
|
|
#define SSL_MAX_HASH_LEN 36
|
2019-01-10 11:27:10 +01:00
|
|
|
#else
|
2020-02-03 10:40:36 +01:00
|
|
|
#define SSL_MAX_HASH_LEN 12
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* HANDSHAKE STATE: Incoming `Finished`
|
|
|
|
*/
|
2019-01-10 11:27:10 +01:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl )
|
2017-07-20 17:17:51 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
|
|
|
unsigned int hash_len;
|
|
|
|
unsigned char buf[SSL_MAX_HASH_LEN];
|
2017-07-20 17:17:51 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse finished" ) );
|
2019-01-14 10:35:19 +01:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
ssl->handshake->calc_finished( ssl, buf, ssl->conf->endpoint ^ 1 );
|
2017-07-20 17:17:51 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
|
2017-07-20 17:17:51 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
|
|
|
|
return( ret );
|
2017-07-20 17:17:51 +02:00
|
|
|
}
|
2020-02-03 10:40:36 +01:00
|
|
|
|
|
|
|
if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE )
|
2017-07-20 17:17:51 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) );
|
|
|
|
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
|
|
|
|
MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
|
|
|
|
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
|
2017-07-20 17:17:51 +02:00
|
|
|
}
|
2020-02-03 10:40:36 +01:00
|
|
|
|
|
|
|
/* There is currently no ciphersuite using another length with TLS 1.2 */
|
|
|
|
#if defined(MBEDTLS_SSL_PROTO_SSL3)
|
|
|
|
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
|
|
|
|
hash_len = 36;
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
hash_len = 12;
|
|
|
|
|
|
|
|
if( ssl->in_msg[0] != MBEDTLS_SSL_HS_FINISHED ||
|
|
|
|
ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + hash_len )
|
2017-07-20 17:17:51 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) );
|
|
|
|
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
|
|
|
|
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
|
|
|
|
return( MBEDTLS_ERR_SSL_BAD_HS_FINISHED );
|
2017-07-20 17:17:51 +02:00
|
|
|
}
|
2020-02-03 10:40:36 +01:00
|
|
|
|
|
|
|
if( mbedtls_ssl_safer_memcmp( ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ),
|
|
|
|
buf, hash_len ) != 0 )
|
2017-07-20 17:17:51 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) );
|
|
|
|
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
|
|
|
|
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
|
|
|
|
return( MBEDTLS_ERR_SSL_BAD_HS_FINISHED );
|
2017-07-20 17:17:51 +02:00
|
|
|
}
|
2020-02-03 10:40:36 +01:00
|
|
|
|
|
|
|
#if defined(MBEDTLS_SSL_RENEGOTIATION)
|
|
|
|
ssl->verify_data_len = hash_len;
|
|
|
|
memcpy( ssl->peer_verify_data, buf, hash_len );
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if( ssl->handshake->resume != 0 )
|
2017-07-20 17:17:51 +02:00
|
|
|
{
|
2020-02-03 10:40:36 +01:00
|
|
|
#if defined(MBEDTLS_SSL_CLI_C)
|
|
|
|
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT )
|
|
|
|
ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC;
|
|
|
|
#endif
|
|
|
|
#if defined(MBEDTLS_SSL_SRV_C)
|
|
|
|
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER )
|
|
|
|
ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP;
|
|
|
|
#endif
|
2017-07-20 17:17:51 +02:00
|
|
|
}
|
2020-02-03 10:40:36 +01:00
|
|
|
else
|
|
|
|
ssl->state++;
|
2017-07-20 17:17:51 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
|
|
|
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
|
|
|
|
mbedtls_ssl_recv_flight_completed( ssl );
|
|
|
|
#endif
|
2017-07-20 17:17:51 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse finished" ) );
|
2017-07-20 17:17:51 +02:00
|
|
|
|
2020-02-03 10:40:36 +01:00
|
|
|
return( 0 );
|
2017-07-20 17:17:51 +02:00
|
|
|
}
|
|
|
|
|
2015-04-08 12:49:31 +02:00
|
|
|
#endif /* MBEDTLS_SSL_TLS_C */
|