mirror of
https://github.com/yuzu-emu/mbedtls.git
synced 2024-12-23 10:05:37 +00:00
Merge remote-tracking branch 'origin/pr/562' into baremetal
This commit is contained in:
commit
724a695534
|
@ -262,4 +262,3 @@ void mbedtls_debug_printf_ecdh( const mbedtls_ssl_context *ssl, int level,
|
|||
#endif
|
||||
|
||||
#endif /* debug.h */
|
||||
|
||||
|
|
|
@ -74,6 +74,12 @@ typedef enum {
|
|||
#define MBEDTLS_MD_MAX_SIZE 32 /* longest known is SHA256 or less */
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_SHA512_C)
|
||||
#define MBEDTLS_MD_MAX_BLOCK_SIZE 128
|
||||
#else
|
||||
#define MBEDTLS_MD_MAX_BLOCK_SIZE 64
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Opaque struct defined in md_internal.h.
|
||||
*/
|
||||
|
|
|
@ -137,7 +137,16 @@
|
|||
#define MBEDTLS_SSL_COMPRESSION_ADD 0
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_MODE_CBC)
|
||||
#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) || \
|
||||
( defined(MBEDTLS_CIPHER_MODE_CBC) && \
|
||||
( defined(MBEDTLS_AES_C) || \
|
||||
defined(MBEDTLS_CAMELLIA_C) || \
|
||||
defined(MBEDTLS_ARIA_C) || \
|
||||
defined(MBEDTLS_DES_C) ) )
|
||||
#define MBEDTLS_SSL_SOME_MODES_USE_MAC
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
|
||||
/* Ciphersuites using HMAC */
|
||||
#if defined(MBEDTLS_SHA512_C)
|
||||
#define MBEDTLS_SSL_MAC_ADD 48 /* SHA-384 used for HMAC */
|
||||
|
@ -146,7 +155,7 @@
|
|||
#else
|
||||
#define MBEDTLS_SSL_MAC_ADD 20 /* SHA-1 used for HMAC */
|
||||
#endif
|
||||
#else
|
||||
#else /* MBEDTLS_SSL_SOME_MODES_USE_MAC */
|
||||
/* AEAD ciphersuites: GCM and CCM use a 128 bits tag */
|
||||
#define MBEDTLS_SSL_MAC_ADD 16
|
||||
#endif
|
||||
|
@ -387,6 +396,8 @@ struct mbedtls_ssl_handshake_params
|
|||
const unsigned char *, size_t,
|
||||
unsigned char *, size_t);
|
||||
|
||||
mbedtls_ssl_ciphersuite_t const *ciphersuite_info;
|
||||
|
||||
size_t pmslen; /*!< premaster length */
|
||||
|
||||
unsigned char randbytes[64]; /*!< random bytes */
|
||||
|
@ -422,25 +433,116 @@ struct mbedtls_ssl_handshake_params
|
|||
typedef struct mbedtls_ssl_hs_buffer mbedtls_ssl_hs_buffer;
|
||||
|
||||
/*
|
||||
* This structure contains a full set of runtime transform parameters
|
||||
* either in negotiation or active.
|
||||
* Representation of decryption/encryption transformations on records
|
||||
*
|
||||
* There are the following general types of record transformations:
|
||||
* - Stream transformations (TLS versions <= 1.2 only)
|
||||
* Transformation adding a MAC and applying a stream-cipher
|
||||
* to the authenticated message.
|
||||
* - CBC block cipher transformations ([D]TLS versions <= 1.2 only)
|
||||
* In addition to the distinction of the order of encryption and
|
||||
* authentication, there's a fundamental difference between the
|
||||
* handling in SSL3 & TLS 1.0 and TLS 1.1 and TLS 1.2: For SSL3
|
||||
* and TLS 1.0, the final IV after processing a record is used
|
||||
* as the IV for the next record. No explicit IV is contained
|
||||
* in an encrypted record. The IV for the first record is extracted
|
||||
* at key extraction time. In contrast, for TLS 1.1 and 1.2, no
|
||||
* IV is generated at key extraction time, but every encrypted
|
||||
* record is explicitly prefixed by the IV with which it was encrypted.
|
||||
* - AEAD transformations ([D]TLS versions >= 1.2 only)
|
||||
* These come in two fundamentally different versions, the first one
|
||||
* used in TLS 1.2, excluding ChaChaPoly ciphersuites, and the second
|
||||
* one used for ChaChaPoly ciphersuites in TLS 1.2 as well as for TLS 1.3.
|
||||
* In the first transformation, the IV to be used for a record is obtained
|
||||
* as the concatenation of an explicit, static 4-byte IV and the 8-byte
|
||||
* record sequence number, and explicitly prepending this sequence number
|
||||
* to the encrypted record. In contrast, in the second transformation
|
||||
* the IV is obtained by XOR'ing a static IV obtained at key extraction
|
||||
* time with the 8-byte record sequence number, without prepending the
|
||||
* latter to the encrypted record.
|
||||
*
|
||||
* In addition to type and version, the following parameters are relevant:
|
||||
* - The symmetric cipher algorithm to be used.
|
||||
* - The (static) encryption/decryption keys for the cipher.
|
||||
* - For stream/CBC, the type of message digest to be used.
|
||||
* - For stream/CBC, (static) encryption/decryption keys for the digest.
|
||||
* - For AEAD transformations, the size (potentially 0) of an explicit,
|
||||
* random initialization vector placed in encrypted records.
|
||||
* - For some transformations (currently AEAD and CBC in SSL3 and TLS 1.0)
|
||||
* an implicit IV. It may be static (e.g. AEAD) or dynamic (e.g. CBC)
|
||||
* and (if present) is combined with the explicit IV in a transformation-
|
||||
* dependent way (e.g. appending in TLS 1.2 and XOR'ing in TLS 1.3).
|
||||
* - For stream/CBC, a flag determining the order of encryption and MAC.
|
||||
* - The details of the transformation depend on the SSL/TLS version.
|
||||
* - The length of the authentication tag.
|
||||
*
|
||||
* Note: Except for CBC in SSL3 and TLS 1.0, these parameters are
|
||||
* constant across multiple encryption/decryption operations.
|
||||
* For CBC, the implicit IV needs to be updated after each
|
||||
* operation.
|
||||
*
|
||||
* The struct below refines this abstract view as follows:
|
||||
* - The cipher underlying the transformation is managed in
|
||||
* cipher contexts cipher_ctx_{enc/dec}, which must have the
|
||||
* same cipher type. The mode of these cipher contexts determines
|
||||
* the type of the transformation in the sense above: e.g., if
|
||||
* the type is MBEDTLS_CIPHER_AES_256_CBC resp. MBEDTLS_CIPHER_AES_192_GCM
|
||||
* then the transformation has type CBC resp. AEAD.
|
||||
* - The cipher keys are never stored explicitly but
|
||||
* are maintained within cipher_ctx_{enc/dec}.
|
||||
* - For stream/CBC transformations, the message digest contexts
|
||||
* used for the MAC's are stored in md_ctx_{enc/dec}. These contexts
|
||||
* are unused for AEAD transformations.
|
||||
* - For stream/CBC transformations and versions > SSL3, the
|
||||
* MAC keys are not stored explicitly but maintained within
|
||||
* md_ctx_{enc/dec}.
|
||||
* - For stream/CBC transformations and version SSL3, the MAC
|
||||
* keys are stored explicitly in mac_enc, mac_dec and have
|
||||
* a fixed size of 20 bytes. These fields are unused for
|
||||
* AEAD transformations or transformations >= TLS 1.0.
|
||||
* - For transformations using an implicit IV maintained within
|
||||
* the transformation context, its contents are stored within
|
||||
* iv_{enc/dec}.
|
||||
* - The value of ivlen indicates the length of the IV.
|
||||
* This is redundant in case of stream/CBC transformations
|
||||
* which always use 0 resp. the cipher's block length as the
|
||||
* IV length, but is needed for AEAD ciphers and may be
|
||||
* different from the underlying cipher's block length
|
||||
* in this case.
|
||||
* - The field fixed_ivlen is nonzero for AEAD transformations only
|
||||
* and indicates the length of the static part of the IV which is
|
||||
* constant throughout the communication, and which is stored in
|
||||
* the first fixed_ivlen bytes of the iv_{enc/dec} arrays.
|
||||
* Note: For CBC in SSL3 and TLS 1.0, the fields iv_{enc/dec}
|
||||
* still store IV's for continued use across multiple transformations,
|
||||
* so it is not true that fixed_ivlen == 0 means that iv_{enc/dec} are
|
||||
* not being used!
|
||||
* - minor_ver denotes the SSL/TLS version
|
||||
* - For stream/CBC transformations, maclen denotes the length of the
|
||||
* authentication tag, while taglen is unused and 0.
|
||||
* - For AEAD transformations, taglen denotes the length of the
|
||||
* authentication tag, while maclen is unused and 0.
|
||||
* - For CBC transformations, encrypt_then_mac determines the
|
||||
* order of encryption and authentication. This field is unused
|
||||
* in other transformations.
|
||||
*
|
||||
*/
|
||||
struct mbedtls_ssl_transform
|
||||
{
|
||||
/*
|
||||
* Session specific crypto layer
|
||||
*/
|
||||
const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
|
||||
/*!< Chosen cipersuite_info */
|
||||
unsigned int keylen; /*!< symmetric key length (bytes) */
|
||||
size_t minlen; /*!< min. ciphertext length */
|
||||
size_t ivlen; /*!< IV length */
|
||||
size_t fixed_ivlen; /*!< Fixed part of IV (AEAD) */
|
||||
size_t maclen; /*!< MAC length */
|
||||
size_t maclen; /*!< MAC(CBC) len */
|
||||
size_t taglen; /*!< TAG(AEAD) len */
|
||||
|
||||
unsigned char iv_enc[16]; /*!< IV (encryption) */
|
||||
unsigned char iv_dec[16]; /*!< IV (decryption) */
|
||||
|
||||
#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
|
||||
|
||||
#if defined(MBEDTLS_SSL_PROTO_SSL3)
|
||||
/* Needed only for SSL v3.0 secret */
|
||||
unsigned char mac_enc[20]; /*!< SSL v3.0 secret (enc) */
|
||||
|
@ -450,8 +552,15 @@ struct mbedtls_ssl_transform
|
|||
mbedtls_md_context_t md_ctx_enc; /*!< MAC (encryption) */
|
||||
mbedtls_md_context_t md_ctx_dec; /*!< MAC (decryption) */
|
||||
|
||||
#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
|
||||
int encrypt_then_mac; /*!< flag for EtM activation */
|
||||
#endif
|
||||
|
||||
#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */
|
||||
|
||||
mbedtls_cipher_context_t cipher_ctx_enc; /*!< encryption context */
|
||||
mbedtls_cipher_context_t cipher_ctx_dec; /*!< decryption context */
|
||||
int minor_ver;
|
||||
|
||||
/*
|
||||
* Session specific compression layer
|
||||
|
@ -462,6 +571,39 @@ struct mbedtls_ssl_transform
|
|||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* Internal representation of record frames
|
||||
*
|
||||
* Instances come in two flavors:
|
||||
* (1) Encrypted
|
||||
* These always have data_offset = 0
|
||||
* (2) Unencrypted
|
||||
* These have data_offset set to the amount of
|
||||
* pre-expansion during record protection. Concretely,
|
||||
* this is the length of the fixed part of the explicit IV
|
||||
* used for encryption, or 0 if no explicit IV is used
|
||||
* (e.g. for CBC in TLS 1.0, or stream ciphers).
|
||||
*
|
||||
* The reason for the data_offset in the unencrypted case
|
||||
* is to allow for in-place conversion of an unencrypted to
|
||||
* an encrypted record. If the offset wasn't included, the
|
||||
* encrypted content would need to be shifted afterwards to
|
||||
* make space for the fixed IV.
|
||||
*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t ctr[8]; /*!< Record sequence number */
|
||||
uint8_t type; /*!< Record type */
|
||||
uint8_t ver[2]; /*!< SSL/TLS version */
|
||||
|
||||
unsigned char *buf; /*!< Memory buffer enclosing the record content */
|
||||
size_t buf_len; /*!< Buffer length */
|
||||
size_t data_offset; /*!< Offset of record content */
|
||||
size_t data_len; /*!< Length of record content */
|
||||
|
||||
} mbedtls_record;
|
||||
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
/*
|
||||
* List of certificate + private key pairs
|
||||
|
@ -779,4 +921,14 @@ int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl,
|
|||
}
|
||||
#endif
|
||||
|
||||
void mbedtls_ssl_transform_init( mbedtls_ssl_transform *transform );
|
||||
int mbedtls_ssl_encrypt_buf( mbedtls_ssl_context *ssl,
|
||||
mbedtls_ssl_transform *transform,
|
||||
mbedtls_record *rec,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng );
|
||||
int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context *ssl,
|
||||
mbedtls_ssl_transform *transform,
|
||||
mbedtls_record *rec );
|
||||
|
||||
#endif /* ssl_internal.h */
|
||||
|
|
|
@ -1312,7 +1312,7 @@ static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl,
|
|||
{
|
||||
int ret;
|
||||
|
||||
if( ssl->transform_negotiate->ciphersuite_info->key_exchange !=
|
||||
if( ssl->handshake->ciphersuite_info->key_exchange !=
|
||||
MBEDTLS_KEY_EXCHANGE_ECJPAKE )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip ecjpake kkpp extension" ) );
|
||||
|
@ -1675,9 +1675,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
|
|||
/*
|
||||
* Initialize update checksum functions
|
||||
*/
|
||||
ssl->transform_negotiate->ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( i );
|
||||
|
||||
if( ssl->transform_negotiate->ciphersuite_info == NULL )
|
||||
ssl->handshake->ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( i );
|
||||
if( ssl->handshake->ciphersuite_info == NULL )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "ciphersuite info for %04x not found", i ) );
|
||||
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
|
||||
|
@ -1685,7 +1684,7 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
|
|||
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
|
||||
}
|
||||
|
||||
mbedtls_ssl_optimize_checksum( ssl, ssl->transform_negotiate->ciphersuite_info );
|
||||
mbedtls_ssl_optimize_checksum( ssl, ssl->handshake->ciphersuite_info );
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) );
|
||||
MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, session id", buf + 35, n );
|
||||
|
@ -2330,7 +2329,7 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
|
|||
{
|
||||
int ret;
|
||||
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
|
||||
ssl->transform_negotiate->ciphersuite_info;
|
||||
ssl->handshake->ciphersuite_info;
|
||||
unsigned char *p = NULL, *end = NULL;
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server key exchange" ) );
|
||||
|
@ -2670,7 +2669,7 @@ exit:
|
|||
static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl )
|
||||
{
|
||||
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
|
||||
ssl->transform_negotiate->ciphersuite_info;
|
||||
ssl->handshake->ciphersuite_info;
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) );
|
||||
|
||||
|
@ -2692,7 +2691,7 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl )
|
|||
size_t n = 0;
|
||||
size_t cert_type_len = 0, dn_len = 0;
|
||||
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
|
||||
ssl->transform_negotiate->ciphersuite_info;
|
||||
ssl->handshake->ciphersuite_info;
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) );
|
||||
|
||||
|
@ -2893,7 +2892,7 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
|
|||
int ret;
|
||||
size_t i, n;
|
||||
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
|
||||
ssl->transform_negotiate->ciphersuite_info;
|
||||
ssl->handshake->ciphersuite_info;
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write client key exchange" ) );
|
||||
|
||||
|
@ -3183,7 +3182,7 @@ ecdh_calc_secret:
|
|||
static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl )
|
||||
{
|
||||
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
|
||||
ssl->transform_negotiate->ciphersuite_info;
|
||||
ssl->handshake->ciphersuite_info;
|
||||
int ret;
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) );
|
||||
|
@ -3213,7 +3212,7 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl )
|
|||
{
|
||||
int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
|
||||
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
|
||||
ssl->transform_negotiate->ciphersuite_info;
|
||||
ssl->handshake->ciphersuite_info;
|
||||
size_t n = 0, offset = 0;
|
||||
unsigned char hash[48];
|
||||
unsigned char *hash_start = hash;
|
||||
|
@ -3323,8 +3322,7 @@ sign:
|
|||
* Reason: Otherwise we should have running hashes for SHA512 and SHA224
|
||||
* in order to satisfy 'weird' needs from the server side.
|
||||
*/
|
||||
if( ssl->transform_negotiate->ciphersuite_info->mac ==
|
||||
MBEDTLS_MD_SHA384 )
|
||||
if( ssl->handshake->ciphersuite_info->mac == MBEDTLS_MD_SHA384 )
|
||||
{
|
||||
md_alg = MBEDTLS_MD_SHA384;
|
||||
ssl->out_msg[4] = MBEDTLS_SSL_HASH_SHA384;
|
||||
|
|
|
@ -1155,7 +1155,7 @@ have_ciphersuite_v2:
|
|||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "selected ciphersuite: %s", ciphersuite_info->name ) );
|
||||
|
||||
ssl->session_negotiate->ciphersuite = ciphersuites[i];
|
||||
ssl->transform_negotiate->ciphersuite_info = ciphersuite_info;
|
||||
ssl->handshake->ciphersuite_info = ciphersuite_info;
|
||||
|
||||
/*
|
||||
* SSLv2 Client Hello relevant renegotiation security checks
|
||||
|
@ -1999,7 +1999,7 @@ have_ciphersuite:
|
|||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "selected ciphersuite: %s", ciphersuite_info->name ) );
|
||||
|
||||
ssl->session_negotiate->ciphersuite = ciphersuites[i];
|
||||
ssl->transform_negotiate->ciphersuite_info = ciphersuite_info;
|
||||
ssl->handshake->ciphersuite_info = ciphersuite_info;
|
||||
|
||||
ssl->state++;
|
||||
|
||||
|
@ -2266,7 +2266,7 @@ static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl,
|
|||
*olen = 0;
|
||||
|
||||
/* Skip costly computation if not needed */
|
||||
if( ssl->transform_negotiate->ciphersuite_info->key_exchange !=
|
||||
if( ssl->handshake->ciphersuite_info->key_exchange !=
|
||||
MBEDTLS_KEY_EXCHANGE_ECJPAKE )
|
||||
return;
|
||||
|
||||
|
@ -2649,7 +2649,7 @@ static int ssl_write_server_hello( mbedtls_ssl_context *ssl )
|
|||
static int ssl_write_certificate_request( mbedtls_ssl_context *ssl )
|
||||
{
|
||||
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
|
||||
ssl->transform_negotiate->ciphersuite_info;
|
||||
ssl->handshake->ciphersuite_info;
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) );
|
||||
|
||||
|
@ -2672,7 +2672,7 @@ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl )
|
|||
{
|
||||
int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
|
||||
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
|
||||
ssl->transform_negotiate->ciphersuite_info;
|
||||
ssl->handshake->ciphersuite_info;
|
||||
size_t dn_size, total_dn_size; /* excluding length bytes */
|
||||
size_t ct_len, sa_len; /* including length bytes */
|
||||
unsigned char *buf, *p;
|
||||
|
@ -2899,7 +2899,8 @@ static int ssl_prepare_server_key_exchange( mbedtls_ssl_context *ssl,
|
|||
size_t *signature_len )
|
||||
{
|
||||
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
|
||||
ssl->transform_negotiate->ciphersuite_info;
|
||||
ssl->handshake->ciphersuite_info;
|
||||
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED)
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED)
|
||||
unsigned char *dig_signed = NULL;
|
||||
|
@ -3265,7 +3266,7 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
|
|||
size_t signature_len = 0;
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED)
|
||||
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
|
||||
ssl->transform_negotiate->ciphersuite_info;
|
||||
ssl->handshake->ciphersuite_info;
|
||||
#endif /* MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED */
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) );
|
||||
|
@ -3711,7 +3712,7 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
|
|||
const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
|
||||
unsigned char *p, *end;
|
||||
|
||||
ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
|
||||
ciphersuite_info = ssl->handshake->ciphersuite_info;
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client key exchange" ) );
|
||||
|
||||
|
@ -3994,7 +3995,7 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
|
|||
static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
|
||||
{
|
||||
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
|
||||
ssl->transform_negotiate->ciphersuite_info;
|
||||
ssl->handshake->ciphersuite_info;
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) );
|
||||
|
||||
|
@ -4025,7 +4026,7 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
|
|||
#endif
|
||||
mbedtls_md_type_t md_alg;
|
||||
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
|
||||
ssl->transform_negotiate->ciphersuite_info;
|
||||
ssl->handshake->ciphersuite_info;
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) );
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,241 @@
|
|||
/* BEGIN_HEADER */
|
||||
#include <mbedtls/ssl.h>
|
||||
#include <mbedtls/ssl_internal.h>
|
||||
|
||||
/*
|
||||
* Helper function setting up inverse record transformations
|
||||
* using given cipher, hash, EtM mode, authentication tag length,
|
||||
* and version.
|
||||
*/
|
||||
|
||||
#define CHK( x ) \
|
||||
do \
|
||||
{ \
|
||||
if( !( x ) ) \
|
||||
{ \
|
||||
ret = -1; \
|
||||
goto cleanup; \
|
||||
} \
|
||||
} while( 0 )
|
||||
|
||||
|
||||
static int build_transforms( mbedtls_ssl_transform *t_in,
|
||||
mbedtls_ssl_transform *t_out,
|
||||
int cipher_type, int hash_id,
|
||||
int etm, int tag_mode, int ver )
|
||||
{
|
||||
mbedtls_cipher_info_t const *cipher_info;
|
||||
int ret = 0;
|
||||
|
||||
size_t keylen, maclen, ivlen;
|
||||
unsigned char *key0 = NULL, *key1 = NULL;
|
||||
unsigned char iv_enc[16], iv_dec[16];
|
||||
|
||||
maclen = 0;
|
||||
|
||||
/* Pick cipher */
|
||||
cipher_info = mbedtls_cipher_info_from_type( cipher_type );
|
||||
CHK( cipher_info != NULL );
|
||||
CHK( cipher_info->iv_size <= 16 );
|
||||
CHK( cipher_info->key_bitlen % 8 == 0 );
|
||||
|
||||
/* Pick keys */
|
||||
keylen = cipher_info->key_bitlen / 8;
|
||||
/* Allocate `keylen + 1` bytes to ensure that we get
|
||||
* a non-NULL pointers from `mbedtls_calloc` even if
|
||||
* `keylen == 0` in the case of the NULL cipher. */
|
||||
CHK( ( key0 = mbedtls_calloc( 1, keylen + 1 ) ) != NULL );
|
||||
CHK( ( key1 = mbedtls_calloc( 1, keylen + 1 ) ) != NULL );
|
||||
memset( key0, 0x1, keylen );
|
||||
memset( key1, 0x2, keylen );
|
||||
|
||||
/* Setup cipher contexts */
|
||||
CHK( mbedtls_cipher_setup( &t_in->cipher_ctx_enc, cipher_info ) == 0 );
|
||||
CHK( mbedtls_cipher_setup( &t_in->cipher_ctx_dec, cipher_info ) == 0 );
|
||||
CHK( mbedtls_cipher_setup( &t_out->cipher_ctx_enc, cipher_info ) == 0 );
|
||||
CHK( mbedtls_cipher_setup( &t_out->cipher_ctx_dec, cipher_info ) == 0 );
|
||||
|
||||
#if defined(MBEDTLS_CIPHER_MODE_CBC)
|
||||
if( cipher_info->mode == MBEDTLS_MODE_CBC )
|
||||
{
|
||||
CHK( mbedtls_cipher_set_padding_mode( &t_in->cipher_ctx_enc,
|
||||
MBEDTLS_PADDING_NONE ) == 0 );
|
||||
CHK( mbedtls_cipher_set_padding_mode( &t_in->cipher_ctx_dec,
|
||||
MBEDTLS_PADDING_NONE ) == 0 );
|
||||
CHK( mbedtls_cipher_set_padding_mode( &t_out->cipher_ctx_enc,
|
||||
MBEDTLS_PADDING_NONE ) == 0 );
|
||||
CHK( mbedtls_cipher_set_padding_mode( &t_out->cipher_ctx_dec,
|
||||
MBEDTLS_PADDING_NONE ) == 0 );
|
||||
}
|
||||
#endif /* MBEDTLS_CIPHER_MODE_CBC */
|
||||
|
||||
CHK( mbedtls_cipher_setkey( &t_in->cipher_ctx_enc, key0,
|
||||
keylen << 3, MBEDTLS_ENCRYPT ) == 0 );
|
||||
CHK( mbedtls_cipher_setkey( &t_in->cipher_ctx_dec, key1,
|
||||
keylen << 3, MBEDTLS_DECRYPT ) == 0 );
|
||||
CHK( mbedtls_cipher_setkey( &t_out->cipher_ctx_enc, key1,
|
||||
keylen << 3, MBEDTLS_ENCRYPT ) == 0 );
|
||||
CHK( mbedtls_cipher_setkey( &t_out->cipher_ctx_dec, key0,
|
||||
keylen << 3, MBEDTLS_DECRYPT ) == 0 );
|
||||
|
||||
/* Setup MAC contexts */
|
||||
#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
|
||||
if( cipher_info->mode == MBEDTLS_MODE_CBC ||
|
||||
cipher_info->mode == MBEDTLS_MODE_STREAM )
|
||||
{
|
||||
mbedtls_md_info_t const *md_info;
|
||||
unsigned char *md0, *md1;
|
||||
|
||||
/* Pick hash */
|
||||
md_info = mbedtls_md_info_from_type( hash_id );
|
||||
CHK( md_info != NULL );
|
||||
|
||||
/* Pick hash keys */
|
||||
maclen = mbedtls_md_get_size( md_info );
|
||||
CHK( ( md0 = mbedtls_calloc( 1, maclen ) ) != NULL );
|
||||
CHK( ( md1 = mbedtls_calloc( 1, maclen ) ) != NULL );
|
||||
memset( md0, 0x5, maclen );
|
||||
memset( md1, 0x6, maclen );
|
||||
|
||||
CHK( mbedtls_md_setup( &t_out->md_ctx_enc, md_info, 1 ) == 0 );
|
||||
CHK( mbedtls_md_setup( &t_out->md_ctx_dec, md_info, 1 ) == 0 );
|
||||
CHK( mbedtls_md_setup( &t_in->md_ctx_enc, md_info, 1 ) == 0 );
|
||||
CHK( mbedtls_md_setup( &t_in->md_ctx_dec, md_info, 1 ) == 0 );
|
||||
|
||||
if( ver > MBEDTLS_SSL_MINOR_VERSION_0 )
|
||||
{
|
||||
CHK( mbedtls_md_hmac_starts( &t_in->md_ctx_enc,
|
||||
md0, maclen ) == 0 );
|
||||
CHK( mbedtls_md_hmac_starts( &t_in->md_ctx_dec,
|
||||
md1, maclen ) == 0 );
|
||||
CHK( mbedtls_md_hmac_starts( &t_out->md_ctx_enc,
|
||||
md1, maclen ) == 0 );
|
||||
CHK( mbedtls_md_hmac_starts( &t_out->md_ctx_dec,
|
||||
md0, maclen ) == 0 );
|
||||
}
|
||||
#if defined(MBEDTLS_SSL_PROTO_SSL3)
|
||||
else
|
||||
{
|
||||
memcpy( &t_in->mac_enc, md0, maclen );
|
||||
memcpy( &t_in->mac_dec, md1, maclen );
|
||||
memcpy( &t_out->mac_enc, md1, maclen );
|
||||
memcpy( &t_out->mac_dec, md0, maclen );
|
||||
}
|
||||
#endif
|
||||
|
||||
mbedtls_free( md0 );
|
||||
mbedtls_free( md1 );
|
||||
}
|
||||
#else
|
||||
((void) hash_id);
|
||||
#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */
|
||||
|
||||
|
||||
/* Pick IV's (regardless of whether they
|
||||
* are being used by the transform). */
|
||||
ivlen = cipher_info->iv_size;
|
||||
memset( iv_enc, 0x3, sizeof( iv_enc ) );
|
||||
memset( iv_dec, 0x4, sizeof( iv_dec ) );
|
||||
|
||||
/*
|
||||
* Setup transforms
|
||||
*/
|
||||
|
||||
#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
|
||||
t_out->encrypt_then_mac = etm;
|
||||
t_in->encrypt_then_mac = etm;
|
||||
#else
|
||||
((void) etm);
|
||||
#endif
|
||||
|
||||
t_out->minor_ver = ver;
|
||||
t_in->minor_ver = ver;
|
||||
t_out->ivlen = ivlen;
|
||||
t_in->ivlen = ivlen;
|
||||
|
||||
switch( cipher_info->mode )
|
||||
{
|
||||
case MBEDTLS_MODE_GCM:
|
||||
case MBEDTLS_MODE_CCM:
|
||||
t_out->fixed_ivlen = 4;
|
||||
t_in->fixed_ivlen = 4;
|
||||
t_out->maclen = 0;
|
||||
t_in->maclen = 0;
|
||||
switch( tag_mode )
|
||||
{
|
||||
case 0: /* Full tag */
|
||||
t_out->taglen = 16;
|
||||
t_in->taglen = 16;
|
||||
break;
|
||||
case 1: /* Partial tag */
|
||||
t_out->taglen = 8;
|
||||
t_in->taglen = 8;
|
||||
break;
|
||||
default:
|
||||
return( 1 );
|
||||
}
|
||||
break;
|
||||
|
||||
case MBEDTLS_MODE_CHACHAPOLY:
|
||||
t_out->fixed_ivlen = 12;
|
||||
t_in->fixed_ivlen = 12;
|
||||
t_out->maclen = 0;
|
||||
t_in->maclen = 0;
|
||||
switch( tag_mode )
|
||||
{
|
||||
case 0: /* Full tag */
|
||||
t_out->taglen = 16;
|
||||
t_in->taglen = 16;
|
||||
break;
|
||||
case 1: /* Partial tag */
|
||||
t_out->taglen = 8;
|
||||
t_in->taglen = 8;
|
||||
break;
|
||||
default:
|
||||
return( 1 );
|
||||
}
|
||||
break;
|
||||
|
||||
case MBEDTLS_MODE_STREAM:
|
||||
case MBEDTLS_MODE_CBC:
|
||||
t_out->fixed_ivlen = 0; /* redundant, must be 0 */
|
||||
t_in->fixed_ivlen = 0; /* redundant, must be 0 */
|
||||
t_out->taglen = 0;
|
||||
t_in->taglen = 0;
|
||||
switch( tag_mode )
|
||||
{
|
||||
case 0: /* Full tag */
|
||||
t_out->maclen = maclen;
|
||||
t_in->maclen = maclen;
|
||||
break;
|
||||
case 1: /* Partial tag */
|
||||
t_out->maclen = 10;
|
||||
t_in->maclen = 10;
|
||||
break;
|
||||
default:
|
||||
return( 1 );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return( 1 );
|
||||
break;
|
||||
}
|
||||
|
||||
/* Setup IV's */
|
||||
|
||||
memcpy( &t_in->iv_dec, iv_dec, sizeof( iv_dec ) );
|
||||
memcpy( &t_in->iv_enc, iv_enc, sizeof( iv_enc ) );
|
||||
memcpy( &t_out->iv_dec, iv_enc, sizeof( iv_enc ) );
|
||||
memcpy( &t_out->iv_enc, iv_dec, sizeof( iv_dec ) );
|
||||
|
||||
cleanup:
|
||||
|
||||
mbedtls_free( key0 );
|
||||
mbedtls_free( key1 );
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
/* END_HEADER */
|
||||
|
||||
/* BEGIN_DEPENDENCIES
|
||||
|
@ -52,3 +287,257 @@ void ssl_set_hostname_twice( char *hostname0, char *hostname1 )
|
|||
mbedtls_ssl_free( &ssl );
|
||||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN_CASE */
|
||||
void ssl_crypt_record( int cipher_type, int hash_id,
|
||||
int etm, int tag_mode, int ver )
|
||||
{
|
||||
/*
|
||||
* Test several record encryptions and decryptions
|
||||
* with plenty of space before and after the data
|
||||
* within the record buffer.
|
||||
*/
|
||||
|
||||
int ret;
|
||||
int num_records = 16;
|
||||
mbedtls_ssl_context ssl; /* ONLY for debugging */
|
||||
|
||||
mbedtls_ssl_transform t0, t1;
|
||||
unsigned char *buf = NULL;
|
||||
size_t const buflen = 512;
|
||||
mbedtls_record rec, rec_backup;
|
||||
|
||||
mbedtls_ssl_init( &ssl );
|
||||
mbedtls_ssl_transform_init( &t0 );
|
||||
mbedtls_ssl_transform_init( &t1 );
|
||||
TEST_ASSERT( build_transforms( &t0, &t1, cipher_type, hash_id,
|
||||
etm, tag_mode, ver ) == 0 );
|
||||
|
||||
TEST_ASSERT( ( buf = mbedtls_calloc( 1, buflen ) ) != NULL );
|
||||
|
||||
while( num_records-- > 0 )
|
||||
{
|
||||
mbedtls_ssl_transform *t_dec, *t_enc;
|
||||
/* Take turns in who's sending and who's receiving. */
|
||||
if( num_records % 3 == 0 )
|
||||
{
|
||||
t_dec = &t0;
|
||||
t_enc = &t1;
|
||||
}
|
||||
else
|
||||
{
|
||||
t_dec = &t1;
|
||||
t_enc = &t0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The record header affects the transformation in two ways:
|
||||
* 1) It determines the AEAD additional data
|
||||
* 2) The record counter sometimes determines the IV.
|
||||
*
|
||||
* Apart from that, the fields don't have influence.
|
||||
* In particular, it is currently not the responsibility
|
||||
* of ssl_encrypt/decrypt_buf to check if the transform
|
||||
* version matches the record version, or that the
|
||||
* type is sensible.
|
||||
*/
|
||||
|
||||
memset( rec.ctr, num_records, sizeof( rec.ctr ) );
|
||||
rec.type = 42;
|
||||
rec.ver[0] = num_records;
|
||||
rec.ver[1] = num_records;
|
||||
|
||||
rec.buf = buf;
|
||||
rec.buf_len = buflen;
|
||||
rec.data_offset = 16;
|
||||
/* Make sure to vary the length to exercise different
|
||||
* paddings. */
|
||||
rec.data_len = 1 + num_records;
|
||||
|
||||
memset( rec.buf + rec.data_offset, 42, rec.data_len );
|
||||
|
||||
/* Make a copy for later comparison */
|
||||
rec_backup = rec;
|
||||
|
||||
/* Encrypt record */
|
||||
ret = mbedtls_ssl_encrypt_buf( &ssl, t_enc, &rec,
|
||||
rnd_std_rand, NULL );
|
||||
TEST_ASSERT( ret == 0 || ret == MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
|
||||
if( ret != 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Decrypt record with t_dec */
|
||||
TEST_ASSERT( mbedtls_ssl_decrypt_buf( &ssl, t_dec, &rec ) == 0 );
|
||||
|
||||
/* Compare results */
|
||||
TEST_ASSERT( rec.type == rec_backup.type );
|
||||
TEST_ASSERT( memcmp( rec.ctr, rec_backup.ctr, 8 ) == 0 );
|
||||
TEST_ASSERT( rec.ver[0] == rec_backup.ver[0] );
|
||||
TEST_ASSERT( rec.ver[1] == rec_backup.ver[1] );
|
||||
TEST_ASSERT( rec.data_len == rec_backup.data_len );
|
||||
TEST_ASSERT( rec.data_offset == rec_backup.data_offset );
|
||||
TEST_ASSERT( memcmp( rec.buf + rec.data_offset,
|
||||
rec_backup.buf + rec_backup.data_offset,
|
||||
rec.data_len ) == 0 );
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
/* Cleanup */
|
||||
mbedtls_ssl_free( &ssl );
|
||||
mbedtls_ssl_transform_free( &t0 );
|
||||
mbedtls_ssl_transform_free( &t1 );
|
||||
|
||||
mbedtls_free( buf );
|
||||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN_CASE */
|
||||
void ssl_crypt_record_small( int cipher_type, int hash_id,
|
||||
int etm, int tag_mode, int ver )
|
||||
{
|
||||
/*
|
||||
* Test pairs of encryption and decryption with an increasing
|
||||
* amount of space in the record buffer - in more detail:
|
||||
* 1) Try to encrypt with 0, 1, 2, ... bytes available
|
||||
* in front of the plaintext, and expect the encryption
|
||||
* to succeed starting from some offset. Always keep
|
||||
* enough space in the end of the buffer.
|
||||
* 2) Try to encrypt with 0, 1, 2, ... bytes available
|
||||
* at the end of the plaintext, and expect the encryption
|
||||
* to succeed starting from some offset. Always keep
|
||||
* enough space at the beginning of the buffer.
|
||||
* 3) Try to encrypt with 0, 1, 2, ... bytes available
|
||||
* both at the front and end of the plaintext,
|
||||
* and expect the encryption to succeed starting from
|
||||
* some offset.
|
||||
*
|
||||
* If encryption succeeds, check that decryption succeeds
|
||||
* and yields the original record.
|
||||
*/
|
||||
|
||||
mbedtls_ssl_context ssl; /* ONLY for debugging */
|
||||
|
||||
mbedtls_ssl_transform t0, t1;
|
||||
unsigned char *buf = NULL;
|
||||
size_t const buflen = 150;
|
||||
mbedtls_record rec, rec_backup;
|
||||
|
||||
int ret;
|
||||
int mode; /* Mode 1, 2 or 3 as explained above */
|
||||
size_t offset; /* Available space at beginning/end/both */
|
||||
size_t threshold = 64; /* Maximum offset to test against */
|
||||
|
||||
size_t default_pre_padding = 64; /* Pre-padding to use in mode 2 */
|
||||
size_t default_post_padding = 64; /* Post-padding to use in mode 1 */
|
||||
|
||||
int seen_success; /* Indicates if in the current mode we've
|
||||
* already seen a successful test. */
|
||||
|
||||
mbedtls_ssl_init( &ssl );
|
||||
mbedtls_ssl_transform_init( &t0 );
|
||||
mbedtls_ssl_transform_init( &t1 );
|
||||
TEST_ASSERT( build_transforms( &t0, &t1, cipher_type, hash_id,
|
||||
etm, tag_mode, ver ) == 0 );
|
||||
|
||||
TEST_ASSERT( ( buf = mbedtls_calloc( 1, buflen ) ) != NULL );
|
||||
|
||||
for( mode=1; mode <= 3; mode++ )
|
||||
{
|
||||
seen_success = 0;
|
||||
for( offset=0; offset <= threshold; offset++ )
|
||||
{
|
||||
mbedtls_ssl_transform *t_dec, *t_enc;
|
||||
/* Take turns in who's sending and who's receiving. */
|
||||
if( offset % 2 == 0 )
|
||||
{
|
||||
t_dec = &t0;
|
||||
t_enc = &t1;
|
||||
}
|
||||
else
|
||||
{
|
||||
t_dec = &t1;
|
||||
t_enc = &t0;
|
||||
}
|
||||
|
||||
memset( rec.ctr, offset, sizeof( rec.ctr ) );
|
||||
rec.type = 42;
|
||||
rec.ver[0] = offset;
|
||||
rec.ver[1] = offset;
|
||||
rec.buf = buf;
|
||||
rec.buf_len = buflen;
|
||||
|
||||
switch( mode )
|
||||
{
|
||||
case 1: /* Space in the beginning */
|
||||
rec.data_offset = offset;
|
||||
rec.data_len = buflen - offset - default_post_padding;
|
||||
break;
|
||||
|
||||
case 2: /* Space in the end */
|
||||
rec.data_offset = default_pre_padding;
|
||||
rec.data_len = buflen - default_pre_padding - offset;
|
||||
break;
|
||||
|
||||
case 3: /* Space in the beginning and end */
|
||||
rec.data_offset = offset;
|
||||
rec.data_len = buflen - 2 * offset;
|
||||
break;
|
||||
|
||||
default:
|
||||
TEST_ASSERT( 0 );
|
||||
break;
|
||||
}
|
||||
|
||||
memset( rec.buf + rec.data_offset, 42, rec.data_len );
|
||||
|
||||
/* Make a copy for later comparison */
|
||||
rec_backup = rec;
|
||||
|
||||
/* Encrypt record */
|
||||
ret = mbedtls_ssl_encrypt_buf( &ssl, t_enc, &rec, rnd_std_rand, NULL );
|
||||
|
||||
if( ( mode == 1 || mode == 2 ) && seen_success )
|
||||
{
|
||||
TEST_ASSERT( ret == 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
TEST_ASSERT( ret == 0 || ret == MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
|
||||
if( ret == 0 )
|
||||
seen_success = 1;
|
||||
}
|
||||
|
||||
if( ret != 0 )
|
||||
continue;
|
||||
|
||||
/* Decrypt record with t_dec */
|
||||
TEST_ASSERT( mbedtls_ssl_decrypt_buf( &ssl, t_dec, &rec ) == 0 );
|
||||
|
||||
/* Compare results */
|
||||
TEST_ASSERT( rec.type == rec_backup.type );
|
||||
TEST_ASSERT( memcmp( rec.ctr, rec_backup.ctr, 8 ) == 0 );
|
||||
TEST_ASSERT( rec.ver[0] == rec_backup.ver[0] );
|
||||
TEST_ASSERT( rec.ver[1] == rec_backup.ver[1] );
|
||||
TEST_ASSERT( rec.data_len == rec_backup.data_len );
|
||||
TEST_ASSERT( rec.data_offset == rec_backup.data_offset );
|
||||
TEST_ASSERT( memcmp( rec.buf + rec.data_offset,
|
||||
rec_backup.buf + rec_backup.data_offset,
|
||||
rec.data_len ) == 0 );
|
||||
}
|
||||
|
||||
TEST_ASSERT( seen_success == 1 );
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
/* Cleanup */
|
||||
mbedtls_ssl_free( &ssl );
|
||||
mbedtls_ssl_transform_free( &t0 );
|
||||
mbedtls_ssl_transform_free( &t1 );
|
||||
|
||||
mbedtls_free( buf );
|
||||
}
|
||||
/* END_CASE */
|
||||
|
|
Loading…
Reference in a new issue