Merge pull request #20539 from akien-mga/mbedtls-2.12.0

mbedtls: Update to upstream version 2.12.0
This commit is contained in:
Rémi Verschelde 2018-07-28 15:40:40 +02:00 committed by GitHub
commit 04ec0bf5e1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
63 changed files with 7386 additions and 599 deletions

View file

@ -20,6 +20,8 @@ if env['builtin_mbedtls']:
"camellia.c",
"ccm.c",
"certs.c",
"chacha20.c",
"chachapoly.c",
"cipher.c",
"cipher_wrap.c",
"cmac.c",
@ -37,6 +39,7 @@ if env['builtin_mbedtls']:
"error.c",
"gcm.c",
"havege.c",
"hkdf.c",
"hmac_drbg.c",
"md2.c",
"md4.c",
@ -45,6 +48,7 @@ if env['builtin_mbedtls']:
"md_wrap.c",
"memory_buffer_alloc.c",
"net_sockets.c",
"nist_kw.c",
"oid.c",
"padlock.c",
"pem.c",
@ -57,6 +61,7 @@ if env['builtin_mbedtls']:
"pkwrite.c",
"platform.c",
"platform_util.c",
"poly1305.c",
"ripemd160.c",
"rsa.c",
"rsa_internal.c",

View file

@ -263,14 +263,12 @@ Godot build configurations, check them out when updating.
## mbedtls
- Upstream: https://tls.mbed.org/
- Version: 2.8.0
- Version: 2.12.0
- License: Apache 2.0
File extracted from upstream release tarball `mbedtls-2.8.0-apache.tgz`:
File extracted from upstream release tarball `mbedtls-2.12.0-apache.tgz`:
- All `*.h` from `include/mbedtls/` to `thirdparty/mbedtls/include/mbedtls/`
- All `*.c` from `library/` to `thirdparty/mbedtls/library/`
- In file `thirdparty/mbedtls/library/net_sockets.c` mbedTLS overrides the `_WIN32_WINNT` define.
Be sure to check the Godot addition to only redfine it when undefined or `< 0x0501` (PRed upstream).
- Applied the patch in `thirdparty/mbedtls/1453.diff` (PR 1453). Soon to be merged upstream. Check it out at next update.

View file

@ -1,5 +1,5 @@
diff --git a/library/entropy_poll.c b/library/entropy_poll.c
index 67900c46..cefe882d 100644
index 67900c46c8..cefe882d2a 100644
--- a/library/entropy_poll.c
+++ b/library/entropy_poll.c
@@ -54,28 +54,43 @@
@ -54,7 +54,7 @@ index 67900c46..cefe882d 100644
return( 0 );
diff --git a/library/x509_crt.c b/library/x509_crt.c
index 290c1eb3..038eae02 100644
index 290c1eb3d1..3cf1743821 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -65,6 +65,19 @@
@ -81,7 +81,7 @@ index 290c1eb3..038eae02 100644
char filename[MAX_PATH];
char *p;
size_t len = strlen( path );
+ int lengthAsInt = 0;
+ int length_as_int = 0;
WIN32_FIND_DATAW file_data;
HANDLE hFind;
@ -90,7 +90,7 @@ index 290c1eb3..038eae02 100644
filename[len++] = '*';
- w_ret = MultiByteToWideChar( CP_ACP, 0, filename, (int)len, szDir,
+ if ( FAILED ( SizeTToInt( len, &lengthAsInt ) ) )
+ if ( FAILED ( SizeTToInt( len, &length_as_int ) ) )
+ return( MBEDTLS_ERR_X509_FILE_IO_ERROR );
+
+ /*
@ -101,7 +101,7 @@ index 290c1eb3..038eae02 100644
+ * incoming string are less than MAX_PATH to avoid a buffer overrun with
+ * MultiByteToWideChar().
+ */
+ w_ret = MultiByteToWideChar( CP_ACP, 0, filename, lengthAsInt, szDir,
+ w_ret = MultiByteToWideChar( CP_ACP, 0, filename, length_as_int, szDir,
MAX_PATH - 3 );
if( w_ret == 0 )
return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
@ -109,12 +109,12 @@ index 290c1eb3..038eae02 100644
if( file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
continue;
+ if ( FAILED( SizeTToInt( wcslen( file_data.cFileName ), &lengthAsInt ) ) )
+ if ( FAILED( SizeTToInt( wcslen( file_data.cFileName ), &length_as_int ) ) )
+ return( MBEDTLS_ERR_X509_FILE_IO_ERROR );
+
w_ret = WideCharToMultiByte( CP_ACP, 0, file_data.cFileName,
- lstrlenW( file_data.cFileName ),
+ lengthAsInt,
+ length_as_int,
p, (int) len - 1,
NULL, NULL );
if( w_ret == 0 )

View file

@ -13,6 +13,11 @@
* <em>ISO/IEC 18033-2:2006: Information technology -- Security
* techniques -- Encryption algorithms -- Part 2: Asymmetric
* ciphers</em>.
*
* The AES-XTS block mode is standardized by NIST SP 800-38E
* <https://nvlpubs.nist.gov/nistpubs/legacy/sp/nistspecialpublication800-38e.pdf>
* and described in detail by IEEE P1619
* <https://ieeexplore.ieee.org/servlet/opac?punumber=4375278>.
*/
/* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved.
@ -89,6 +94,19 @@ typedef struct
}
mbedtls_aes_context;
#if defined(MBEDTLS_CIPHER_MODE_XTS)
/**
* \brief The AES XTS context-type definition.
*/
typedef struct
{
mbedtls_aes_context crypt; /*!< The AES context to use for AES block
encryption or decryption. */
mbedtls_aes_context tweak; /*!< The AES context used for tweak
computation. */
} mbedtls_aes_xts_context;
#endif /* MBEDTLS_CIPHER_MODE_XTS */
#else /* MBEDTLS_AES_ALT */
#include "aes_alt.h"
#endif /* MBEDTLS_AES_ALT */
@ -110,6 +128,25 @@ void mbedtls_aes_init( mbedtls_aes_context *ctx );
*/
void mbedtls_aes_free( mbedtls_aes_context *ctx );
#if defined(MBEDTLS_CIPHER_MODE_XTS)
/**
* \brief This function initializes the specified AES XTS context.
*
* It must be the first API called before using
* the context.
*
* \param ctx The AES XTS context to initialize.
*/
void mbedtls_aes_xts_init( mbedtls_aes_xts_context *ctx );
/**
* \brief This function releases and clears the specified AES XTS context.
*
* \param ctx The AES XTS context to clear.
*/
void mbedtls_aes_xts_free( mbedtls_aes_xts_context *ctx );
#endif /* MBEDTLS_CIPHER_MODE_XTS */
/**
* \brief This function sets the encryption key.
*
@ -142,6 +179,44 @@ int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key,
int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key,
unsigned int keybits );
#if defined(MBEDTLS_CIPHER_MODE_XTS)
/**
* \brief This function prepares an XTS context for encryption and
* sets the encryption key.
*
* \param ctx The AES XTS context to which the key should be bound.
* \param key The encryption key. This is comprised of the XTS key1
* concatenated with the XTS key2.
* \param keybits The size of \p key passed in bits. Valid options are:
* <ul><li>256 bits (each of key1 and key2 is a 128-bit key)</li>
* <li>512 bits (each of key1 and key2 is a 256-bit key)</li></ul>
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.
*/
int mbedtls_aes_xts_setkey_enc( mbedtls_aes_xts_context *ctx,
const unsigned char *key,
unsigned int keybits );
/**
* \brief This function prepares an XTS context for decryption and
* sets the decryption key.
*
* \param ctx The AES XTS context to which the key should be bound.
* \param key The decryption key. This is comprised of the XTS key1
* concatenated with the XTS key2.
* \param keybits The size of \p key passed in bits. Valid options are:
* <ul><li>256 bits (each of key1 and key2 is a 128-bit key)</li>
* <li>512 bits (each of key1 and key2 is a 256-bit key)</li></ul>
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.
*/
int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx,
const unsigned char *key,
unsigned int keybits );
#endif /* MBEDTLS_CIPHER_MODE_XTS */
/**
* \brief This function performs an AES single-block encryption or
* decryption operation.
@ -213,6 +288,49 @@ int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx,
unsigned char *output );
#endif /* MBEDTLS_CIPHER_MODE_CBC */
#if defined(MBEDTLS_CIPHER_MODE_XTS)
/**
* \brief This function performs an AES-XTS encryption or decryption
* operation for an entire XTS data unit.
*
* AES-XTS encrypts or decrypts blocks based on their location as
* defined by a data unit number. The data unit number must be
* provided by \p data_unit.
*
* NIST SP 800-38E limits the maximum size of a data unit to 2^20
* AES blocks. If the data unit is larger than this, this function
* returns #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH.
*
* \param ctx The AES XTS context to use for AES XTS operations.
* \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or
* #MBEDTLS_AES_DECRYPT.
* \param length The length of a data unit in bytes. This can be any
* length between 16 bytes and 2^24 bytes inclusive
* (between 1 and 2^20 block cipher blocks).
* \param data_unit The address of the data unit encoded as an array of 16
* bytes in little-endian format. For disk encryption, this
* is typically the index of the block device sector that
* contains the data.
* \param input The buffer holding the input data (which is an entire
* data unit). This function reads \p length bytes from \p
* input.
* \param output The buffer holding the output data (which is an entire
* data unit). This function writes \p length bytes to \p
* output.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH if \p length is
* smaller than an AES block in size (16 bytes) or if \p
* length is larger than 2^20 blocks (16 MiB).
*/
int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx,
int mode,
size_t length,
const unsigned char data_unit[16],
const unsigned char *input,
unsigned char *output );
#endif /* MBEDTLS_CIPHER_MODE_XTS */
#if defined(MBEDTLS_CIPHER_MODE_CFB)
/**
* \brief This function performs an AES-CFB128 encryption or decryption
@ -296,6 +414,56 @@ int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx,
unsigned char *output );
#endif /*MBEDTLS_CIPHER_MODE_CFB */
#if defined(MBEDTLS_CIPHER_MODE_OFB)
/**
* \brief This function performs an AES-OFB (Output Feedback Mode)
* encryption or decryption operation.
*
* For OFB, you must set up the context with
* mbedtls_aes_setkey_enc(), regardless of whether you are
* performing an encryption or decryption operation. This is
* because OFB mode uses the same key schedule for encryption and
* decryption.
*
* The OFB operation is identical for encryption or decryption,
* therefore no operation mode needs to be specified.
*
* \note Upon exit, the content of iv, the Initialisation Vector, is
* updated so that you can call the same function again on the next
* block(s) of data and get the same result as if it was encrypted
* in one call. This allows a "streaming" usage, by initialising
* iv_off to 0 before the first call, and preserving its value
* between calls.
*
* For non-streaming use, the iv should be initialised on each call
* to a unique value, and iv_off set to 0 on each call.
*
* If you need to retain the contents of the initialisation vector,
* you must either save it manually or use the cipher module
* instead.
*
* \warning For the OFB mode, the initialisation vector must be unique
* every encryption operation. Reuse of an initialisation vector
* will compromise security.
*
* \param ctx The AES context to use for encryption or decryption.
* \param length The length of the input data.
* \param iv_off The offset in IV (updated after use).
* \param iv The initialization vector (updated after use).
* \param input The buffer holding the input data.
* \param output The buffer holding the output data.
*
* \return \c 0 on success.
*/
int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx,
size_t length,
size_t *iv_off,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output );
#endif /* MBEDTLS_CIPHER_MODE_OFB */
#if defined(MBEDTLS_CIPHER_MODE_CTR)
/**
* \brief This function performs an AES-CTR encryption or decryption

View file

@ -49,7 +49,14 @@
/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */
#if defined(__GNUC__) && \
( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 )
#if defined(__i386__)
/*
* Disable use of the i386 assembly code below if option -O0, to disable all
* compiler optimisations, is passed, detected with __OPTIMIZE__
* This is done as the number of registers used in the assembly code doesn't
* work with the -O0 option.
*/
#if defined(__i386__) && defined(__OPTIMIZE__)
#define MULADDC_INIT \
asm( \
@ -142,7 +149,7 @@
"movl %%esi, %3 \n\t" \
: "=m" (t), "=m" (c), "=m" (d), "=m" (s) \
: "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \
: "eax", "ecx", "edx", "esi", "edi" \
: "eax", "ebx", "ecx", "edx", "esi", "edi" \
);
#else
@ -154,7 +161,7 @@
"movl %%esi, %3 \n\t" \
: "=m" (t), "=m" (c), "=m" (d), "=m" (s) \
: "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \
: "eax", "ecx", "edx", "esi", "edi" \
: "eax", "ebx", "ecx", "edx", "esi", "edi" \
);
#endif /* SSE2 */
#endif /* i386 */

View file

@ -14,6 +14,18 @@
* <li>Nonce - A unique value that is assigned to the payload and the
* associated data.</li></ul>
*
* Definition of CCM:
* http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf
* RFC 3610 "Counter with CBC-MAC (CCM)"
*
* Related:
* RFC 5116 "An Interface and Algorithms for Authenticated Encryption"
*
* Definition of CCM*:
* IEEE 802.15.4 - IEEE Standard for Local and metropolitan area networks
* Integer representation is fixed most-significant-octet-first order and
* the representation of octets is most-significant-bit-first order. This is
* consistent with RFC 3610.
*/
/*
* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved
@ -102,7 +114,6 @@ void mbedtls_ccm_free( mbedtls_ccm_context *ctx );
/**
* \brief This function encrypts a buffer using CCM.
*
*
* \note The tag is written to a separate buffer. To concatenate
* the \p tag with the \p output, as done in <em>RFC-3610:
* Counter with CBC-MAC (CCM)</em>, use
@ -112,15 +123,17 @@ void mbedtls_ccm_free( mbedtls_ccm_context *ctx );
* \param ctx The CCM context to use for encryption.
* \param length The length of the input data in Bytes.
* \param iv Initialization vector (nonce).
* \param iv_len The length of the IV in Bytes: 7, 8, 9, 10, 11, 12, or 13.
* \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12,
* or 13. The length L of the message length field is
* 15 - \p iv_len.
* \param add The additional data field.
* \param add_len The length of additional data in Bytes.
* Must be less than 2^16 - 2^8.
* \param input The buffer holding the input data.
* \param output The buffer holding the output data.
* Must be at least \p length Bytes wide.
* \param tag The buffer holding the tag.
* \param tag_len The length of the tag to generate in Bytes:
* \param tag The buffer holding the authentication field.
* \param tag_len The length of the authentication field to generate in Bytes:
* 4, 6, 8, 10, 12, 14 or 16.
*
* \return \c 0 on success.
@ -133,21 +146,64 @@ int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
unsigned char *tag, size_t tag_len );
/**
* \brief This function performs a CCM authenticated decryption of a
* buffer.
* \brief This function encrypts a buffer using CCM*.
*
* \param ctx The CCM context to use for decryption.
* \note The tag is written to a separate buffer. To concatenate
* the \p tag with the \p output, as done in <em>RFC-3610:
* Counter with CBC-MAC (CCM)</em>, use
* \p tag = \p output + \p length, and make sure that the
* output buffer is at least \p length + \p tag_len wide.
*
* \note When using this function in a variable tag length context,
* the tag length has to be encoded into the \p iv passed to
* this function.
*
* \param ctx The CCM context to use for encryption.
* \param length The length of the input data in Bytes.
* \param iv Initialization vector.
* \param iv_len The length of the IV in Bytes: 7, 8, 9, 10, 11, 12, or 13.
* \param iv Initialization vector (nonce).
* \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12,
* or 13. The length L of the message length field is
* 15 - \p iv_len.
* \param add The additional data field.
* \param add_len The length of additional data in Bytes.
* Must be less than 2^16 - 2^8.
* \param input The buffer holding the input data.
* \param output The buffer holding the output data.
* Must be at least \p length Bytes wide.
* \param tag The buffer holding the tag.
* \param tag_len The length of the tag in Bytes.
* \param tag The buffer holding the authentication field.
* \param tag_len The length of the authentication field to generate in Bytes:
* 0, 4, 6, 8, 10, 12, 14 or 16.
*
* \warning Passing 0 as \p tag_len means that the message is no
* longer authenticated.
*
* \return \c 0 on success.
* \return A CCM or cipher-specific error code on failure.
*/
int mbedtls_ccm_star_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *iv, size_t iv_len,
const unsigned char *add, size_t add_len,
const unsigned char *input, unsigned char *output,
unsigned char *tag, size_t tag_len );
/**
* \brief This function performs a CCM authenticated decryption of a
* buffer.
*
* \param ctx The CCM context to use for decryption.
* \param length The length of the input data in Bytes.
* \param iv Initialization vector (nonce).
* \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12,
* or 13. The length L of the message length field is
* 15 - \p iv_len.
* \param add The additional data field.
* \param add_len The length of additional data in Bytes.
* Must be less than 2^16 - 2^8.
* \param input The buffer holding the input data.
* \param output The buffer holding the output data.
* Must be at least \p length Bytes wide.
* \param tag The buffer holding the authentication field.
* \param tag_len The length of the authentication field in Bytes.
* 4, 6, 8, 10, 12, 14 or 16.
*
* \return \c 0 on success. This indicates that the message is authentic.
@ -160,6 +216,43 @@ int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *input, unsigned char *output,
const unsigned char *tag, size_t tag_len );
/**
* \brief This function performs a CCM* authenticated decryption of a
* buffer.
*
* \note When using this function in a variable tag length context,
* the tag length has to be decoded from \p iv and passed to
* this function as \p tag_len. (\p tag needs to be adjusted
* accordingly.)
*
* \param ctx The CCM context to use for decryption.
* \param length The length of the input data in Bytes.
* \param iv Initialization vector (nonce).
* \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12,
* or 13. The length L of the message length field is
* 15 - \p iv_len.
* \param add The additional data field.
* \param add_len The length of additional data in Bytes.
* Must be less than 2^16 - 2^8.
* \param input The buffer holding the input data.
* \param output The buffer holding the output data.
* Must be at least \p length Bytes wide.
* \param tag The buffer holding the authentication field.
* \param tag_len The length of the authentication field in Bytes.
* 0, 4, 6, 8, 10, 12, 14 or 16.
*
* \warning Passing 0 as \p tag_len means that the message is no
* longer authenticated.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_CCM_AUTH_FAILED if the tag does not match.
* \return A cipher-specific error code on calculation failure.
*/
int mbedtls_ccm_star_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *iv, size_t iv_len,
const unsigned char *add, size_t add_len,
const unsigned char *input, unsigned char *output,
const unsigned char *tag, size_t tag_len );
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
/**

View file

@ -0,0 +1,212 @@
/**
* \file chacha20.h
*
* \brief This file contains ChaCha20 definitions and functions.
*
* ChaCha20 is a stream cipher that can encrypt and decrypt
* information. ChaCha was created by Daniel Bernstein as a variant of
* its Salsa cipher https://cr.yp.to/chacha/chacha-20080128.pdf
* ChaCha20 is the variant with 20 rounds, that was also standardized
* in RFC 7539.
*
* \author Daniel King <damaki.gh@gmail.com>
*/
/* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.
*
* This file is part of Mbed TLS (https://tls.mbed.org)
*/
#ifndef MBEDTLS_CHACHA20_H
#define MBEDTLS_CHACHA20_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include <stdint.h>
#include <stddef.h>
#define MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA -0x0051 /**< Invalid input parameter(s). */
#define MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE -0x0053 /**< Feature not available. For example, s part of the API is not implemented. */
#define MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED -0x0055 /**< Chacha20 hardware accelerator failed. */
#ifdef __cplusplus
extern "C" {
#endif
#if !defined(MBEDTLS_CHACHA20_ALT)
typedef struct
{
uint32_t state[16]; /*! The state (before round operations). */
uint8_t keystream8[64]; /*! Leftover keystream bytes. */
size_t keystream_bytes_used; /*! Number of keystream bytes already used. */
}
mbedtls_chacha20_context;
#else /* MBEDTLS_CHACHA20_ALT */
#include "chacha20_alt.h"
#endif /* MBEDTLS_CHACHA20_ALT */
/**
* \brief This function initializes the specified ChaCha20 context.
*
* It must be the first API called before using
* the context.
*
* It is usually followed by calls to
* \c mbedtls_chacha20_setkey() and
* \c mbedtls_chacha20_starts(), then one or more calls to
* to \c mbedtls_chacha20_update(), and finally to
* \c mbedtls_chacha20_free().
*
* \param ctx The ChaCha20 context to initialize.
*/
void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx );
/**
* \brief This function releases and clears the specified ChaCha20 context.
*
* \param ctx The ChaCha20 context to clear.
*/
void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx );
/**
* \brief This function sets the encryption/decryption key.
*
* \note After using this function, you must also call
* \c mbedtls_chacha20_starts() to set a nonce before you
* start encrypting/decrypting data with
* \c mbedtls_chacha_update().
*
* \param ctx The ChaCha20 context to which the key should be bound.
* \param key The encryption/decryption key. Must be 32 bytes in length.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if ctx or key is NULL.
*/
int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx,
const unsigned char key[32] );
/**
* \brief This function sets the nonce and initial counter value.
*
* \note A ChaCha20 context can be re-used with the same key by
* calling this function to change the nonce.
*
* \warning You must never use the same nonce twice with the same key.
* This would void any confidentiality guarantees for the
* messages encrypted with the same nonce and key.
*
* \param ctx The ChaCha20 context to which the nonce should be bound.
* \param nonce The nonce. Must be 12 bytes in size.
* \param counter The initial counter value. This is usually 0.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if ctx or nonce is
* NULL.
*/
int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx,
const unsigned char nonce[12],
uint32_t counter );
/**
* \brief This function encrypts or decrypts data.
*
* Since ChaCha20 is a stream cipher, the same operation is
* used for encrypting and decrypting data.
*
* \note The \p input and \p output pointers must either be equal or
* point to non-overlapping buffers.
*
* \note \c mbedtls_chacha20_setkey() and
* \c mbedtls_chacha20_starts() must be called at least once
* to setup the context before this function can be called.
*
* \note This function can be called multiple times in a row in
* order to encrypt of decrypt data piecewise with the same
* key and nonce.
*
* \param ctx The ChaCha20 context to use for encryption or decryption.
* \param size The length of the input data in bytes.
* \param input The buffer holding the input data.
* This pointer can be NULL if size == 0.
* \param output The buffer holding the output data.
* Must be able to hold \p size bytes.
* This pointer can be NULL if size == 0.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if the ctx, input, or
* output pointers are NULL.
*/
int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx,
size_t size,
const unsigned char *input,
unsigned char *output );
/**
* \brief This function encrypts or decrypts data with ChaCha20 and
* the given key and nonce.
*
* Since ChaCha20 is a stream cipher, the same operation is
* used for encrypting and decrypting data.
*
* \warning You must never use the same (key, nonce) pair more than
* once. This would void any confidentiality guarantees for
* the messages encrypted with the same nonce and key.
*
* \note The \p input and \p output pointers must either be equal or
* point to non-overlapping buffers.
*
* \param key The encryption/decryption key. Must be 32 bytes in length.
* \param nonce The nonce. Must be 12 bytes in size.
* \param counter The initial counter value. This is usually 0.
* \param size The length of the input data in bytes.
* \param input The buffer holding the input data.
* This pointer can be NULL if size == 0.
* \param output The buffer holding the output data.
* Must be able to hold \p size bytes.
* This pointer can be NULL if size == 0.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if key, nonce, input,
* or output is NULL.
*/
int mbedtls_chacha20_crypt( const unsigned char key[32],
const unsigned char nonce[12],
uint32_t counter,
size_t size,
const unsigned char* input,
unsigned char* output );
#if defined(MBEDTLS_SELF_TEST)
/**
* \brief The ChaCha20 checkup routine.
*
* \return \c 0 on success.
* \return \c 1 on failure.
*/
int mbedtls_chacha20_self_test( int verbose );
#endif /* MBEDTLS_SELF_TEST */
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_CHACHA20_H */

View file

@ -0,0 +1,355 @@
/**
* \file chachapoly.h
*
* \brief This file contains the AEAD-ChaCha20-Poly1305 definitions and
* functions.
*
* ChaCha20-Poly1305 is an algorithm for Authenticated Encryption
* with Associated Data (AEAD) that can be used to encrypt and
* authenticate data. It is based on ChaCha20 and Poly1305 by Daniel
* Bernstein and was standardized in RFC 7539.
*
* \author Daniel King <damaki.gh@gmail.com>
*/
/* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.
*
* This file is part of Mbed TLS (https://tls.mbed.org)
*/
#ifndef MBEDTLS_CHACHAPOLY_H
#define MBEDTLS_CHACHAPOLY_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
/* for shared error codes */
#include "poly1305.h"
#define MBEDTLS_ERR_CHACHAPOLY_BAD_STATE -0x0054 /**< The requested operation is not permitted in the current state. */
#define MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED -0x0056 /**< Authenticated decryption failed: data was not authentic. */
#ifdef __cplusplus
extern "C" {
#endif
typedef enum
{
MBEDTLS_CHACHAPOLY_ENCRYPT, /**< The mode value for performing encryption. */
MBEDTLS_CHACHAPOLY_DECRYPT /**< The mode value for performing decryption. */
}
mbedtls_chachapoly_mode_t;
#if !defined(MBEDTLS_CHACHAPOLY_ALT)
#include "chacha20.h"
typedef struct
{
mbedtls_chacha20_context chacha20_ctx; /**< The ChaCha20 context. */
mbedtls_poly1305_context poly1305_ctx; /**< The Poly1305 context. */
uint64_t aad_len; /**< The length (bytes) of the Additional Authenticated Data. */
uint64_t ciphertext_len; /**< The length (bytes) of the ciphertext. */
int state; /**< The current state of the context. */
mbedtls_chachapoly_mode_t mode; /**< Cipher mode (encrypt or decrypt). */
}
mbedtls_chachapoly_context;
#else /* !MBEDTLS_CHACHAPOLY_ALT */
#include "chachapoly_alt.h"
#endif /* !MBEDTLS_CHACHAPOLY_ALT */
/**
* \brief This function initializes the specified ChaCha20-Poly1305 context.
*
* It must be the first API called before using
* the context. It must be followed by a call to
* \c mbedtls_chachapoly_setkey() before any operation can be
* done, and to \c mbedtls_chachapoly_free() once all
* operations with that context have been finished.
*
* In order to encrypt or decrypt full messages at once, for
* each message you should make a single call to
* \c mbedtls_chachapoly_crypt_and_tag() or
* \c mbedtls_chachapoly_auth_decrypt().
*
* In order to encrypt messages piecewise, for each
* message you should make a call to
* \c mbedtls_chachapoly_starts(), then 0 or more calls to
* \c mbedtls_chachapoly_update_aad(), then 0 or more calls to
* \c mbedtls_chachapoly_update(), then one call to
* \c mbedtls_chachapoly_finish().
*
* \warning Decryption with the piecewise API is discouraged! Always
* use \c mbedtls_chachapoly_auth_decrypt() when possible!
*
* If however this is not possible because the data is too
* large to fit in memory, you need to:
*
* - call \c mbedtls_chachapoly_starts() and (if needed)
* \c mbedtls_chachapoly_update_aad() as above,
* - call \c mbedtls_chachapoly_update() multiple times and
* ensure its output (the plaintext) is NOT used in any other
* way than placing it in temporary storage at this point,
* - call \c mbedtls_chachapoly_finish() to compute the
* authentication tag and compared it in constant time to the
* tag received with the ciphertext.
*
* If the tags are not equal, you must immediately discard
* all previous outputs of \c mbedtls_chachapoly_update(),
* otherwise you can now safely use the plaintext.
*
* \param ctx The ChachaPoly context to initialize.
*/
void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx );
/**
* \brief This function releases and clears the specified ChaCha20-Poly1305 context.
*
* \param ctx The ChachaPoly context to clear.
*/
void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx );
/**
* \brief This function sets the ChaCha20-Poly1305 symmetric encryption key.
*
* \param ctx The ChaCha20-Poly1305 context to which the key should be
* bound.
* \param key The 256-bit (32 bytes) key.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA
* if \p ctx or \p key are NULL.
*/
int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx,
const unsigned char key[32] );
/**
* \brief This function starts a ChaCha20-Poly1305 encryption or
* decryption operation.
*
* \warning You must never use the same nonce twice with the same key.
* This would void any confidentiality and authenticity
* guarantees for the messages encrypted with the same nonce
* and key.
*
* \note If the context is being used for AAD only (no data to
* encrypt or decrypt) then \p mode can be set to any value.
*
* \warning Decryption with the piecewise API is discouraged, see the
* warning on \c mbedtls_chachapoly_init().
*
* \param ctx The ChaCha20-Poly1305 context.
* \param nonce The nonce/IV to use for the message. Must be 12 bytes.
* \param mode The operation to perform: #MBEDTLS_CHACHAPOLY_ENCRYPT or
* #MBEDTLS_CHACHAPOLY_DECRYPT (discouraged, see warning).
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA
* if \p ctx or \p mac are NULL.
*/
int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx,
const unsigned char nonce[12],
mbedtls_chachapoly_mode_t mode );
/**
* \brief This function feeds additional data to be authenticated
* into an ongoing ChaCha20-Poly1305 operation.
*
* The Additional Authenticated Data (AAD), also called
* Associated Data (AD) is only authenticated but not
* encrypted nor included in the encrypted output. It is
* usually transmitted separately from the ciphertext or
* computed locally by each party.
*
* \note This function is called before data is encrypted/decrypted.
* I.e. call this function to process the AAD before calling
* \c mbedtls_chachapoly_update().
*
* You may call this function multiple times to process
* an arbitrary amount of AAD. It is permitted to call
* this function 0 times, if no AAD is used.
*
* This function cannot be called any more if data has
* been processed by \c mbedtls_chachapoly_update(),
* or if the context has been finished.
*
* \warning Decryption with the piecewise API is discouraged, see the
* warning on \c mbedtls_chachapoly_init().
*
* \param ctx The ChaCha20-Poly1305 context to use.
* \param aad_len The length (in bytes) of the AAD. The length has no
* restrictions.
* \param aad Buffer containing the AAD.
* This pointer can be NULL if aad_len == 0.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA
* if \p ctx or \p aad are NULL.
* \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE
* if the operations has not been started or has been
* finished, or if the AAD has been finished.
*/
int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx,
const unsigned char *aad,
size_t aad_len );
/**
* \brief Thus function feeds data to be encrypted or decrypted
* into an on-going ChaCha20-Poly1305
* operation.
*
* The direction (encryption or decryption) depends on the
* mode that was given when calling
* \c mbedtls_chachapoly_starts().
*
* You may call this function multiple times to process
* an arbitrary amount of data. It is permitted to call
* this function 0 times, if no data is to be encrypted
* or decrypted.
*
* \warning Decryption with the piecewise API is discouraged, see the
* warning on \c mbedtls_chachapoly_init().
*
* \param ctx The ChaCha20-Poly1305 context to use.
* \param len The length (in bytes) of the data to encrypt or decrypt.
* \param input The buffer containing the data to encrypt or decrypt.
* This pointer can be NULL if len == 0.
* \param output The buffer to where the encrypted or decrypted data is written.
* Must be able to hold \p len bytes.
* This pointer can be NULL if len == 0.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA
* if \p ctx, \p input, or \p output are NULL.
* \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE
* if the operation has not been started or has been
* finished.
*/
int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx,
size_t len,
const unsigned char *input,
unsigned char *output );
/**
* \brief This function finished the ChaCha20-Poly1305 operation and
* generates the MAC (authentication tag).
*
* \param ctx The ChaCha20-Poly1305 context to use.
* \param mac The buffer to where the 128-bit (16 bytes) MAC is written.
*
* \warning Decryption with the piecewise API is discouraged, see the
* warning on \c mbedtls_chachapoly_init().
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA
* if \p ctx or \p mac are NULL.
* \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE
* if the operation has not been started or has been
* finished.
*/
int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx,
unsigned char mac[16] );
/**
* \brief This function performs a complete ChaCha20-Poly1305
* authenticated encryption with the previously-set key.
*
* \note Before using this function, you must set the key with
* \c mbedtls_chachapoly_setkey().
*
* \warning You must never use the same nonce twice with the same key.
* This would void any confidentiality and authenticity
* guarantees for the messages encrypted with the same nonce
* and key.
*
* \param ctx The ChaCha20-Poly1305 context to use (holds the key).
* \param length The length (in bytes) of the data to encrypt or decrypt.
* \param nonce The 96-bit (12 bytes) nonce/IV to use.
* \param aad The buffer containing the additional authenticated data (AAD).
* This pointer can be NULL if aad_len == 0.
* \param aad_len The length (in bytes) of the AAD data to process.
* \param input The buffer containing the data to encrypt or decrypt.
* This pointer can be NULL if ilen == 0.
* \param output The buffer to where the encrypted or decrypted data is written.
* This pointer can be NULL if ilen == 0.
* \param tag The buffer to where the computed 128-bit (16 bytes) MAC is written.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA
* if one or more of the required parameters are NULL.
*/
int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx,
size_t length,
const unsigned char nonce[12],
const unsigned char *aad,
size_t aad_len,
const unsigned char *input,
unsigned char *output,
unsigned char tag[16] );
/**
* \brief This function performs a complete ChaCha20-Poly1305
* authenticated decryption with the previously-set key.
*
* \note Before using this function, you must set the key with
* \c mbedtls_chachapoly_setkey().
*
* \param ctx The ChaCha20-Poly1305 context to use (holds the key).
* \param length The length (in bytes) of the data to decrypt.
* \param nonce The 96-bit (12 bytes) nonce/IV to use.
* \param aad The buffer containing the additional authenticated data (AAD).
* This pointer can be NULL if aad_len == 0.
* \param aad_len The length (in bytes) of the AAD data to process.
* \param tag The buffer holding the authentication tag.
* \param input The buffer containing the data to decrypt.
* This pointer can be NULL if ilen == 0.
* \param output The buffer to where the decrypted data is written.
* This pointer can be NULL if ilen == 0.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA
* if one or more of the required parameters are NULL.
* \return #MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED
* if the data was not authentic.
*/
int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx,
size_t length,
const unsigned char nonce[12],
const unsigned char *aad,
size_t aad_len,
const unsigned char tag[16],
const unsigned char *input,
unsigned char *output );
#if defined(MBEDTLS_SELF_TEST)
/**
* \brief The ChaCha20-Poly1305 checkup routine.
*
* \return \c 0 on success.
* \return \c 1 on failure.
*/
int mbedtls_chachapoly_self_test( int verbose );
#endif /* MBEDTLS_SELF_TEST */
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_CHACHAPOLY_H */

View file

@ -4,7 +4,7 @@
* \brief Consistency checks for configuration options
*/
/*
* Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
* Copyright (C) 2006-2018, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -87,6 +87,11 @@
#error "MBEDTLS_CMAC_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_NIST_KW_C) && \
( !defined(MBEDTLS_AES_C) || !defined(MBEDTLS_CIPHER_C) )
#error "MBEDTLS_NIST_KW_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_ECDH_C) && !defined(MBEDTLS_ECP_C)
#error "MBEDTLS_ECDH_C defined, but not all prerequisites"
#endif
@ -191,6 +196,10 @@
#error "MBEDTLS_HAVEGE_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_HKDF_C) && !defined(MBEDTLS_MD_C)
#error "MBEDTLS_HKDF_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_HMAC_DRBG_C) && !defined(MBEDTLS_MD_C)
#error "MBEDTLS_HMAC_DRBG_C defined, but not all prerequisites"
#endif

View file

@ -37,7 +37,7 @@
#include <stddef.h>
#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C)
#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
#define MBEDTLS_CIPHER_MODE_AEAD
#endif
@ -45,7 +45,7 @@
#define MBEDTLS_CIPHER_MODE_WITH_PADDING
#endif
#if defined(MBEDTLS_ARC4_C)
#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER)
#define MBEDTLS_CIPHER_MODE_STREAM
#endif
@ -87,6 +87,7 @@ typedef enum {
MBEDTLS_CIPHER_ID_BLOWFISH, /**< The Blowfish cipher. */
MBEDTLS_CIPHER_ID_ARC4, /**< The RC4 cipher. */
MBEDTLS_CIPHER_ID_ARIA, /**< The Aria cipher. */
MBEDTLS_CIPHER_ID_CHACHA20, /**< The ChaCha20 cipher. */
} mbedtls_cipher_id_t;
/**
@ -164,6 +165,13 @@ typedef enum {
MBEDTLS_CIPHER_ARIA_128_CCM, /**< Aria cipher with 128-bit key and CCM mode. */
MBEDTLS_CIPHER_ARIA_192_CCM, /**< Aria cipher with 192-bit key and CCM mode. */
MBEDTLS_CIPHER_ARIA_256_CCM, /**< Aria cipher with 256-bit key and CCM mode. */
MBEDTLS_CIPHER_AES_128_OFB, /**< AES 128-bit cipher in OFB mode. */
MBEDTLS_CIPHER_AES_192_OFB, /**< AES 192-bit cipher in OFB mode. */
MBEDTLS_CIPHER_AES_256_OFB, /**< AES 256-bit cipher in OFB mode. */
MBEDTLS_CIPHER_AES_128_XTS, /**< AES 128-bit cipher in XTS block mode. */
MBEDTLS_CIPHER_AES_256_XTS, /**< AES 256-bit cipher in XTS block mode. */
MBEDTLS_CIPHER_CHACHA20, /**< ChaCha20 stream cipher. */
MBEDTLS_CIPHER_CHACHA20_POLY1305, /**< ChaCha20-Poly1305 AEAD cipher. */
} mbedtls_cipher_type_t;
/** Supported cipher modes. */
@ -172,11 +180,13 @@ typedef enum {
MBEDTLS_MODE_ECB, /**< The ECB cipher mode. */
MBEDTLS_MODE_CBC, /**< The CBC cipher mode. */
MBEDTLS_MODE_CFB, /**< The CFB cipher mode. */
MBEDTLS_MODE_OFB, /**< The OFB cipher mode - unsupported. */
MBEDTLS_MODE_OFB, /**< The OFB cipher mode. */
MBEDTLS_MODE_CTR, /**< The CTR cipher mode. */
MBEDTLS_MODE_GCM, /**< The GCM cipher mode. */
MBEDTLS_MODE_STREAM, /**< The stream cipher mode. */
MBEDTLS_MODE_CCM, /**< The CCM cipher mode. */
MBEDTLS_MODE_XTS, /**< The XTS cipher mode. */
MBEDTLS_MODE_CHACHAPOLY, /**< The ChaCha-Poly cipher mode. */
} mbedtls_cipher_mode_t;
/** Supported cipher padding types. */
@ -292,7 +302,8 @@ typedef struct {
/** Number of Bytes that have not been processed yet. */
size_t unprocessed_len;
/** Current IV or NONCE_COUNTER for CTR-mode. */
/** Current IV or NONCE_COUNTER for CTR-mode, data unit (or sector) number
* for XTS-mode. */
unsigned char iv[MBEDTLS_MAX_IV_LENGTH];
/** IV size in Bytes, for ciphers with variable-length IVs. */
@ -579,11 +590,11 @@ int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx,
*/
int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx );
#if defined(MBEDTLS_GCM_C)
#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
/**
* \brief This function adds additional data for AEAD ciphers.
* Only supported with GCM. Must be called
* exactly once, after mbedtls_cipher_reset().
* Currently supported with GCM and ChaCha20+Poly1305.
* Must be called exactly once, after mbedtls_cipher_reset().
*
* \param ctx The generic cipher context.
* \param ad The additional data to use.
@ -594,7 +605,7 @@ int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx );
*/
int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx,
const unsigned char *ad, size_t ad_len );
#endif /* MBEDTLS_GCM_C */
#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */
/**
* \brief The generic cipher update function. It encrypts or
@ -652,10 +663,10 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i
int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx,
unsigned char *output, size_t *olen );
#if defined(MBEDTLS_GCM_C)
#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
/**
* \brief This function writes a tag for AEAD ciphers.
* Only supported with GCM.
* Currently supported with GCM and ChaCha20+Poly1305.
* Must be called after mbedtls_cipher_finish().
*
* \param ctx The generic cipher context.
@ -670,7 +681,7 @@ int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx,
/**
* \brief This function checks the tag for AEAD ciphers.
* Only supported with GCM.
* Currently supported with GCM and ChaCha20+Poly1305.
* Must be called after mbedtls_cipher_finish().
*
* \param ctx The generic cipher context.
@ -682,7 +693,7 @@ int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx,
*/
int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx,
const unsigned char *tag, size_t tag_len );
#endif /* MBEDTLS_GCM_C */
#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */
/**
* \brief The generic all-in-one encryption/decryption function,

View file

@ -64,6 +64,14 @@ struct mbedtls_cipher_base_t
unsigned char *output );
#endif
#if defined(MBEDTLS_CIPHER_MODE_OFB)
/** Encrypt using OFB (Full length) */
int (*ofb_func)( void *ctx, size_t length, size_t *iv_off,
unsigned char *iv,
const unsigned char *input,
unsigned char *output );
#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR)
/** Encrypt using CTR */
int (*ctr_func)( void *ctx, size_t length, size_t *nc_off,
@ -71,6 +79,13 @@ struct mbedtls_cipher_base_t
const unsigned char *input, unsigned char *output );
#endif
#if defined(MBEDTLS_CIPHER_MODE_XTS)
/** Encrypt or decrypt using XTS. */
int (*xts_func)( void *ctx, mbedtls_operation_t mode, size_t length,
const unsigned char data_unit[16],
const unsigned char *input, unsigned char *output );
#endif
#if defined(MBEDTLS_CIPHER_MODE_STREAM)
/** Encrypt using STREAM */
int (*stream_func)( void *ctx, size_t length,

View file

@ -28,7 +28,7 @@
#ifndef MBEDTLS_CMAC_H
#define MBEDTLS_CMAC_H
#include "mbedtls/cipher.h"
#include "cipher.h"
#ifdef __cplusplus
extern "C" {

View file

@ -1378,7 +1378,8 @@
#define SSL_ANTI_REPLAY_ENABLED MBEDTLS_SSL_ANTI_REPLAY_ENABLED
#define SSL_ARC4_DISABLED MBEDTLS_SSL_ARC4_DISABLED
#define SSL_ARC4_ENABLED MBEDTLS_SSL_ARC4_ENABLED
#define SSL_BUFFER_LEN MBEDTLS_SSL_BUFFER_LEN
#define SSL_BUFFER_LEN ( ( ( MBEDTLS_SSL_IN_BUFFER_LEN ) < ( MBEDTLS_SSL_OUT_BUFFER_LEN ) ) \
? ( MBEDTLS_SSL_IN_BUFFER_LEN ) : ( MBEDTLS_SSL_OUT_BUFFER_LEN ) )
#define SSL_CACHE_DEFAULT_MAX_ENTRIES MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES
#define SSL_CACHE_DEFAULT_TIMEOUT MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT
#define SSL_CBC_RECORD_SPLITTING_DISABLED MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED

View file

@ -8,7 +8,7 @@
* memory footprint.
*/
/*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* Copyright (C) 2006-2018, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -88,6 +88,28 @@
*/
//#define MBEDTLS_NO_UDBL_DIVISION
/**
* \def MBEDTLS_NO_64BIT_MULTIPLICATION
*
* The platform lacks support for 32x32 -> 64-bit multiplication.
*
* Used in:
* library/poly1305.c
*
* Some parts of the library may use multiplication of two unsigned 32-bit
* operands with a 64-bit result in order to speed up computations. On some
* platforms, this is not available in hardware and has to be implemented in
* software, usually in a library provided by the toolchain.
*
* Sometimes it is not desirable to have to link to that library. This option
* removes the dependency of that library on platforms that lack a hardware
* 64-bit multiplier by embedding a software implementation in Mbed TLS.
*
* Note that depending on the compiler, this may decrease performance compared
* to using the library function provided by the toolchain.
*/
//#define MBEDTLS_NO_64BIT_MULTIPLICATION
/**
* \def MBEDTLS_HAVE_SSE2
*
@ -279,14 +301,18 @@
//#define MBEDTLS_BLOWFISH_ALT
//#define MBEDTLS_CAMELLIA_ALT
//#define MBEDTLS_CCM_ALT
//#define MBEDTLS_CHACHA20_ALT
//#define MBEDTLS_CHACHAPOLY_ALT
//#define MBEDTLS_CMAC_ALT
//#define MBEDTLS_DES_ALT
//#define MBEDTLS_DHM_ALT
//#define MBEDTLS_ECJPAKE_ALT
//#define MBEDTLS_GCM_ALT
//#define MBEDTLS_NIST_KW_ALT
//#define MBEDTLS_MD2_ALT
//#define MBEDTLS_MD4_ALT
//#define MBEDTLS_MD5_ALT
//#define MBEDTLS_POLY1305_ALT
//#define MBEDTLS_RIPEMD160_ALT
//#define MBEDTLS_RSA_ALT
//#define MBEDTLS_SHA1_ALT
@ -515,6 +541,20 @@
*/
#define MBEDTLS_CIPHER_MODE_CTR
/**
* \def MBEDTLS_CIPHER_MODE_OFB
*
* Enable Output Feedback mode (OFB) for symmetric ciphers.
*/
#define MBEDTLS_CIPHER_MODE_OFB
/**
* \def MBEDTLS_CIPHER_MODE_XTS
*
* Enable Xor-encrypt-xor with ciphertext stealing mode (XTS) for AES.
*/
#define MBEDTLS_CIPHER_MODE_XTS
/**
* \def MBEDTLS_CIPHER_NULL_CIPHER
*
@ -1134,6 +1174,17 @@
*/
#define MBEDTLS_SSL_ALL_ALERT_MESSAGES
/**
* \def MBEDTLS_SSL_ASYNC_PRIVATE
*
* Enable asynchronous external private key operations in SSL. This allows
* you to configure an SSL connection to call an external cryptographic
* module to perform private key operations instead of performing the
* operation inside the library.
*
*/
//#define MBEDTLS_SSL_ASYNC_PRIVATE
/**
* \def MBEDTLS_SSL_DEBUG_ALL
*
@ -1919,6 +1970,26 @@
*/
#define MBEDTLS_CERTS_C
/**
* \def MBEDTLS_CHACHA20_C
*
* Enable the ChaCha20 stream cipher.
*
* Module: library/chacha20.c
*/
#define MBEDTLS_CHACHA20_C
/**
* \def MBEDTLS_CHACHAPOLY_C
*
* Enable the ChaCha20-Poly1305 AEAD algorithm.
*
* Module: library/chachapoly.c
*
* This module requires: MBEDTLS_CHACHA20_C, MBEDTLS_POLY1305_C
*/
#define MBEDTLS_CHACHAPOLY_C
/**
* \def MBEDTLS_CIPHER_C
*
@ -2149,6 +2220,21 @@
*/
//#define MBEDTLS_HAVEGE_C
/**
* \def MBEDTLS_HKDF_C
*
* Enable the HKDF algorithm (RFC 5869).
*
* Module: library/hkdf.c
* Caller:
*
* Requires: MBEDTLS_MD_C
*
* This module adds support for the Hashed Message Authentication Code
* (HMAC)-based key derivation function (HKDF).
*/
#define MBEDTLS_HKDF_C
/**
* \def MBEDTLS_HMAC_DRBG_C
*
@ -2163,6 +2249,19 @@
*/
#define MBEDTLS_HMAC_DRBG_C
/**
* \def MBEDTLS_NIST_KW_C
*
* Enable the Key Wrapping mode for 128-bit block ciphers,
* as defined in NIST SP 800-38F. Only KW and KWP modes
* are supported. At the moment, only AES is approved by NIST.
*
* Module: library/nist_kw.c
*
* Requires: MBEDTLS_AES_C and MBEDTLS_CIPHER_C
*/
//#define MBEDTLS_NIST_KW_C
/**
* \def MBEDTLS_MD_C
*
@ -2446,6 +2545,16 @@
*/
#define MBEDTLS_PLATFORM_C
/**
* \def MBEDTLS_POLY1305_C
*
* Enable the Poly1305 MAC algorithm.
*
* Module: library/poly1305.c
* Caller: library/chachapoly.c
*/
#define MBEDTLS_POLY1305_C
/**
* \def MBEDTLS_RIPEMD160_C
*
@ -2856,7 +2965,51 @@
//#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /**< Maximum entries in cache */
/* SSL options */
//#define MBEDTLS_SSL_MAX_CONTENT_LEN 16384 /**< Maxium fragment length in bytes, determines the size of each of the two internal I/O buffers */
/** \def MBEDTLS_SSL_MAX_CONTENT_LEN
*
* Maximum fragment length in bytes.
*
* Determines the size of both the incoming and outgoing TLS I/O buffers.
*
* Uncommenting MBEDTLS_SSL_IN_CONTENT_LEN and/or MBEDTLS_SSL_OUT_CONTENT_LEN
* will override this length by setting maximum incoming and/or outgoing
* fragment length, respectively.
*/
//#define MBEDTLS_SSL_MAX_CONTENT_LEN 16384
/** \def MBEDTLS_SSL_IN_CONTENT_LEN
*
* Maximum incoming fragment length in bytes.
*
* Uncomment to set the size of the inward TLS buffer independently of the
* outward buffer.
*/
//#define MBEDTLS_SSL_IN_CONTENT_LEN 16384
/** \def MBEDTLS_SSL_OUT_CONTENT_LEN
*
* Maximum outgoing fragment length in bytes.
*
* Uncomment to set the size of the outward TLS buffer independently of the
* inward buffer.
*
* It is possible to save RAM by setting a smaller outward buffer, while keeping
* the default inward 16384 byte buffer to conform to the TLS specification.
*
* The minimum required outward buffer size is determined by the handshake
* protocol's usage. Handshaking will fail if the outward buffer is too small.
* The specific size requirement depends on the configured ciphers and any
* certificate data which is sent during the handshake.
*
* For absolute minimum RAM usage, it's best to enable
* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH and reduce MBEDTLS_SSL_MAX_CONTENT_LEN. This
* reduces both incoming and outgoing buffer sizes. However this is only
* guaranteed if the other end of the connection also supports the TLS
* max_fragment_len extension. Otherwise the connection may fail.
*/
//#define MBEDTLS_SSL_OUT_CONTENT_LEN 16384
//#define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */
//#define MBEDTLS_PSK_MAX_LEN 32 /**< Max size of TLS pre-shared keys, in bytes (default 256 bits) */
//#define MBEDTLS_SSL_COOKIE_TIMEOUT 60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */
@ -2933,7 +3086,7 @@
/* \} name SECTION: Customisation configuration options */
/* Target and application specific configurations */
//#define YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE "mbedtls/target_config.h"
//#define YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE "target_config.h"
#if defined(TARGET_LIKE_MBED) && defined(YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE)
#include YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE

View file

@ -36,7 +36,7 @@
#include "aes.h"
#if defined(MBEDTLS_THREADING_C)
#include "mbedtls/threading.h"
#include "threading.h"
#endif
#define MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED -0x0034 /**< The entropy source failed. */

View file

@ -4,7 +4,7 @@
* \brief Error to string translation
*/
/*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* Copyright (C) 2006-2018, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -62,7 +62,7 @@
* DES 2 0x0032-0x0032 0x0033-0x0033
* CTR_DBRG 4 0x0034-0x003A
* ENTROPY 3 0x003C-0x0040 0x003D-0x003F
* NET 11 0x0042-0x0052 0x0043-0x0045
* NET 13 0x0042-0x0052 0x0043-0x0049
* ARIA 4 0x0058-0x005E
* ASN1 7 0x0060-0x006C
* CMAC 1 0x007A-0x007A
@ -77,6 +77,9 @@
* SHA1 1 0x0035-0x0035
* SHA256 1 0x0037-0x0037
* SHA512 1 0x0039-0x0039
* CHACHA20 3 0x0051-0x0055
* POLY1305 3 0x0057-0x005B
* CHACHAPOLY 2 0x0054-0x0056
*
* High-level module nr (3 bits - 0x0...-0x7...)
* Name ID Nr of Errors
@ -89,8 +92,9 @@
* RSA 4 11
* ECP 4 9 (Started from top)
* MD 5 5
* HKDF 5 1 (Started from top)
* CIPHER 6 8
* SSL 6 17 (Started from top)
* SSL 6 22 (Started from top)
* SSL 7 31
*
* Module dependent error code (5 bits 0x.00.-0x.F8.)

View file

@ -113,21 +113,41 @@ int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx,
* the same as input buffer. If the buffers overlap, the output
* buffer must trail at least 8 Bytes behind the input buffer.
*
* \warning When this function performs a decryption, it outputs the
* authentication tag and does not verify that the data is
* authentic. You should use this function to perform encryption
* only. For decryption, use mbedtls_gcm_auth_decrypt() instead.
*
* \param ctx The GCM context to use for encryption or decryption.
* \param mode The operation to perform: #MBEDTLS_GCM_ENCRYPT or
* #MBEDTLS_GCM_DECRYPT.
* \param length The length of the input data. This must be a multiple of
* 16 except in the last call before mbedtls_gcm_finish().
* \param mode The operation to perform:
* - #MBEDTLS_GCM_ENCRYPT to perform authenticated encryption.
* The ciphertext is written to \p output and the
* authentication tag is written to \p tag.
* - #MBEDTLS_GCM_DECRYPT to perform decryption.
* The plaintext is written to \p output and the
* authentication tag is written to \p tag.
* Note that this mode is not recommended, because it does
* not verify the authenticity of the data. For this reason,
* you should use mbedtls_gcm_auth_decrypt() instead of
* calling this function in decryption mode.
* \param length The length of the input data, which is equal to the length
* of the output data.
* \param iv The initialization vector.
* \param iv_len The length of the IV.
* \param add The buffer holding the additional data.
* \param add_len The length of the additional data.
* \param input The buffer holding the input data.
* \param output The buffer for holding the output data.
* \param input The buffer holding the input data. Its size is \b length.
* \param output The buffer for holding the output data. It must have room
* for \b length bytes.
* \param tag_len The length of the tag to generate.
* \param tag The buffer for holding the tag.
*
* \return \c 0 on success.
* \return \c 0 if the encryption or decryption was performed
* successfully. Note that in #MBEDTLS_GCM_DECRYPT mode,
* this does not indicate that the data is authentic.
* \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths are not valid.
* \return #MBEDTLS_ERR_GCM_HW_ACCEL_FAILED or a cipher-specific
* error code if the encryption or decryption failed.
*/
int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx,
int mode,
@ -150,19 +170,23 @@ int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx,
* must trail at least 8 Bytes behind the input buffer.
*
* \param ctx The GCM context.
* \param length The length of the input data. This must be a multiple
* of 16 except in the last call before mbedtls_gcm_finish().
* \param length The length of the ciphertext to decrypt, which is also
* the length of the decrypted plaintext.
* \param iv The initialization vector.
* \param iv_len The length of the IV.
* \param add The buffer holding the additional data.
* \param add_len The length of the additional data.
* \param tag The buffer holding the tag.
* \param tag_len The length of the tag.
* \param input The buffer holding the input data.
* \param output The buffer for holding the output data.
* \param tag The buffer holding the tag to verify.
* \param tag_len The length of the tag to verify.
* \param input The buffer holding the ciphertext. Its size is \b length.
* \param output The buffer for holding the decrypted plaintext. It must
* have room for \b length bytes.
*
* \return 0 if successful and authenticated.
* \return #MBEDTLS_ERR_GCM_AUTH_FAILED if the tag does not match.
* \return \c 0 if successful and authenticated.
* \return #MBEDTLS_ERR_GCM_AUTH_FAILED if the tag does not match.
* \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths are not valid.
* \return #MBEDTLS_ERR_GCM_HW_ACCEL_FAILED or a cipher-specific
* error code if the decryption failed.
*/
int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx,
size_t length,

View file

@ -0,0 +1,125 @@
/**
* \file hkdf.h
*
* \brief This file contains the HKDF interface.
*
* The HMAC-based Extract-and-Expand Key Derivation Function (HKDF) is
* specified by RFC 5869.
*/
/*
* Copyright (C) 2016-2018, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#ifndef MBEDTLS_HKDF_H
#define MBEDTLS_HKDF_H
#include "md.h"
/**
* \name HKDF Error codes
* \{
*/
#define MBEDTLS_ERR_HKDF_BAD_INPUT_DATA -0x5F80 /**< Bad input parameters to function. */
/* \} name */
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief This is the HMAC-based Extract-and-Expand Key Derivation Function
* (HKDF).
*
* \param md A hash function; md.size denotes the length of the hash
* function output in bytes.
* \param salt An optional salt value (a non-secret random value);
* if the salt is not provided, a string of all zeros of
* md.size length is used as the salt.
* \param salt_len The length in bytes of the optional \p salt.
* \param ikm The input keying material.
* \param ikm_len The length in bytes of \p ikm.
* \param info An optional context and application specific information
* string. This can be a zero-length string.
* \param info_len The length of \p info in bytes.
* \param okm The output keying material of \p okm_len bytes.
* \param okm_len The length of the output keying material in bytes. This
* must be less than or equal to 255 * md.size bytes.
*
* \return 0 on success.
* \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid.
* \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying
* MD layer.
*/
int mbedtls_hkdf( const mbedtls_md_info_t *md, const unsigned char *salt,
size_t salt_len, const unsigned char *ikm, size_t ikm_len,
const unsigned char *info, size_t info_len,
unsigned char *okm, size_t okm_len );
/**
* \brief Take the input keying material \p ikm and extract from it a
* fixed-length pseudorandom key \p prk.
*
* \param md A hash function; md.size denotes the length of the
* hash function output in bytes.
* \param salt An optional salt value (a non-secret random value);
* if the salt is not provided, a string of all zeros
* of md.size length is used as the salt.
* \param salt_len The length in bytes of the optional \p salt.
* \param ikm The input keying material.
* \param ikm_len The length in bytes of \p ikm.
* \param[out] prk A pseudorandom key of at least md.size bytes.
*
* \return 0 on success.
* \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid.
* \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying
* MD layer.
*/
int mbedtls_hkdf_extract( const mbedtls_md_info_t *md,
const unsigned char *salt, size_t salt_len,
const unsigned char *ikm, size_t ikm_len,
unsigned char *prk );
/**
* \brief Expand the supplied \p prk into several additional pseudorandom
* keys, which is the output of the HKDF.
*
* \param md A hash function; md.size denotes the length of the hash
* function output in bytes.
* \param prk A pseudorandom key of at least md.size bytes. \p prk is usually,
* the output from the HKDF extract step.
* \param prk_len The length in bytes of \p prk.
* \param info An optional context and application specific information
* string. This can be a zero-length string.
* \param info_len The length of \p info in bytes.
* \param okm The output keying material of \p okm_len bytes.
* \param okm_len The length of the output keying material in bytes. This
* must be less than or equal to 255 * md.size bytes.
*
* \return 0 on success.
* \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid.
* \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying
* MD layer.
*/
int mbedtls_hkdf_expand( const mbedtls_md_info_t *md, const unsigned char *prk,
size_t prk_len, const unsigned char *info,
size_t info_len, unsigned char *okm, size_t okm_len );
#ifdef __cplusplus
}
#endif
#endif /* hkdf.h */

View file

@ -27,7 +27,7 @@
#include "md.h"
#if defined(MBEDTLS_THREADING_C)
#include "mbedtls/threading.h"
#include "threading.h"
#endif
/*

View file

@ -1,7 +1,7 @@
/**
* \file net.h
*
* \brief Deprecated header file that includes mbedtls/net_sockets.h
* \brief Deprecated header file that includes net_sockets.h
*
* \deprecated Superseded by mbedtls/net_sockets.h
*/
@ -25,7 +25,7 @@
*/
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
#include "mbedtls/net_sockets.h"
#include "net_sockets.h"
#if defined(MBEDTLS_DEPRECATED_WARNING)
#warning "Deprecated header file: Superseded by mbedtls/net_sockets.h"
#endif /* MBEDTLS_DEPRECATED_WARNING */

View file

@ -1,7 +1,23 @@
/**
* \file net_sockets.h
*
* \brief Network communication functions
* \brief Network sockets abstraction layer to integrate Mbed TLS into a
* BSD-style sockets API.
*
* The network sockets module provides an example integration of the
* Mbed TLS library into a BSD sockets implementation. The module is
* intended to be an example of how Mbed TLS can be integrated into a
* networking stack, as well as to be Mbed TLS's network integration
* for its supported platforms.
*
* The module is intended only to be used with the Mbed TLS library and
* is not intended to be used by third party application software
* directly.
*
* The supported platforms are as follows:
* * Microsoft Windows and Windows CE
* * POSIX/Unix platforms including Linux, OS X
*
*/
/*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved

View file

@ -0,0 +1,178 @@
/**
* \file nist_kw.h
*
* \brief This file provides an API for key wrapping (KW) and key wrapping with
* padding (KWP) as defined in NIST SP 800-38F.
* https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf
*
* Key wrapping specifies a deterministic authenticated-encryption mode
* of operation, according to <em>NIST SP 800-38F: Recommendation for
* Block Cipher Modes of Operation: Methods for Key Wrapping</em>. Its
* purpose is to protect cryptographic keys.
*
* Its equivalent is RFC 3394 for KW, and RFC 5649 for KWP.
* https://tools.ietf.org/html/rfc3394
* https://tools.ietf.org/html/rfc5649
*
*/
/*
* Copyright (C) 2018, Arm Limited (or its affiliates), All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.
*
* This file is part of Mbed TLS (https://tls.mbed.org)
*/
#ifndef MBEDTLS_NIST_KW_H
#define MBEDTLS_NIST_KW_H
#include "cipher.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum
{
MBEDTLS_KW_MODE_KW = 0,
MBEDTLS_KW_MODE_KWP = 1
} mbedtls_nist_kw_mode_t;
#if !defined(MBEDTLS_NIST_KW_ALT)
// Regular implementation
//
/**
* \brief The key wrapping context-type definition. The key wrapping context is passed
* to the APIs called.
*
* \note The definition of this type may change in future library versions.
* Don't make any assumptions on this context!
*/
typedef struct {
mbedtls_cipher_context_t cipher_ctx; /*!< The cipher context used. */
} mbedtls_nist_kw_context;
#else /* MBEDTLS_NIST_key wrapping_ALT */
#include "nist_kw_alt.h"
#endif /* MBEDTLS_NIST_KW_ALT */
/**
* \brief This function initializes the specified key wrapping context
* to make references valid and prepare the context
* for mbedtls_nist_kw_setkey() or mbedtls_nist_kw_free().
*
* \param ctx The key wrapping context to initialize.
*
*/
void mbedtls_nist_kw_init( mbedtls_nist_kw_context *ctx );
/**
* \brief This function initializes the key wrapping context set in the
* \p ctx parameter and sets the encryption key.
*
* \param ctx The key wrapping context.
* \param cipher The 128-bit block cipher to use. Only AES is supported.
* \param key The Key Encryption Key (KEK).
* \param keybits The KEK size in bits. This must be acceptable by the cipher.
* \param is_wrap Specify whether the operation within the context is wrapping or unwrapping
*
* \return \c 0 on success.
* \return \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for any invalid input.
* \return \c MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE for 128-bit block ciphers
* which are not supported.
* \return cipher-specific error code on failure of the underlying cipher.
*/
int mbedtls_nist_kw_setkey( mbedtls_nist_kw_context *ctx,
mbedtls_cipher_id_t cipher,
const unsigned char *key,
unsigned int keybits,
const int is_wrap );
/**
* \brief This function releases and clears the specified key wrapping context
* and underlying cipher sub-context.
*
* \param ctx The key wrapping context to clear.
*/
void mbedtls_nist_kw_free( mbedtls_nist_kw_context *ctx );
/**
* \brief This function encrypts a buffer using key wrapping.
*
* \param ctx The key wrapping context to use for encryption.
* \param mode The key wrapping mode to use (MBEDTLS_KW_MODE_KW or MBEDTLS_KW_MODE_KWP)
* \param input The buffer holding the input data.
* \param in_len The length of the input data in Bytes.
* The input uses units of 8 Bytes called semiblocks.
* <ul><li>For KW mode: a multiple of 8 bytes between 16 and 2^57-8 inclusive. </li>
* <li>For KWP mode: any length between 1 and 2^32-1 inclusive.</li></ul>
* \param[out] output The buffer holding the output data.
* <ul><li>For KW mode: Must be at least 8 bytes larger than \p in_len.</li>
* <li>For KWP mode: Must be at least 8 bytes larger rounded up to a multiple of
* 8 bytes for KWP (15 bytes at most).</li></ul>
* \param[out] out_len The number of bytes written to the output buffer. \c 0 on failure.
* \param[in] out_size The capacity of the output buffer.
*
* \return \c 0 on success.
* \return \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for invalid input length.
* \return cipher-specific error code on failure of the underlying cipher.
*/
int mbedtls_nist_kw_wrap( mbedtls_nist_kw_context *ctx, mbedtls_nist_kw_mode_t mode,
const unsigned char *input, size_t in_len,
unsigned char *output, size_t* out_len, size_t out_size );
/**
* \brief This function decrypts a buffer using key wrapping.
*
* \param ctx The key wrapping context to use for decryption.
* \param mode The key wrapping mode to use (MBEDTLS_KW_MODE_KW or MBEDTLS_KW_MODE_KWP)
* \param input The buffer holding the input data.
* \param in_len The length of the input data in Bytes.
* The input uses units of 8 Bytes called semiblocks.
* The input must be a multiple of semiblocks.
* <ul><li>For KW mode: a multiple of 8 bytes between 24 and 2^57 inclusive. </li>
* <li>For KWP mode: a multiple of 8 bytes between 16 and 2^32 inclusive.</li></ul>
* \param[out] output The buffer holding the output data.
* The output buffer's minimal length is 8 bytes shorter than \p in_len.
* \param[out] out_len The number of bytes written to the output buffer. \c 0 on failure.
* For KWP mode, the length could be up to 15 bytes shorter than \p in_len,
* depending on how much padding was added to the data.
* \param[in] out_size The capacity of the output buffer.
*
* \return \c 0 on success.
* \return \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for invalid input length.
* \return \c MBEDTLS_ERR_CIPHER_AUTH_FAILED for verification failure of the ciphertext.
* \return cipher-specific error code on failure of the underlying cipher.
*/
int mbedtls_nist_kw_unwrap( mbedtls_nist_kw_context *ctx, mbedtls_nist_kw_mode_t mode,
const unsigned char *input, size_t in_len,
unsigned char *output, size_t* out_len, size_t out_size);
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
/**
* \brief The key wrapping checkup routine.
*
* \return \c 0 on success.
* \return \c 1 on failure.
*/
int mbedtls_nist_kw_self_test( int verbose );
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_NIST_KW_H */

View file

@ -97,6 +97,8 @@
/* ISO arc for standard certificate and CRL extensions */
#define MBEDTLS_OID_ID_CE MBEDTLS_OID_ISO_CCITT_DS "\x1D" /**< id-ce OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 29} */
#define MBEDTLS_OID_NIST_ALG MBEDTLS_OID_GOV "\x03\x04" /** { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) */
/**
* Private Internet Extensions
* { iso(1) identified-organization(3) dod(6) internet(1)
@ -219,12 +221,12 @@
#define MBEDTLS_OID_DIGEST_ALG_MD4 MBEDTLS_OID_RSA_COMPANY "\x02\x04" /**< id-mbedtls_md4 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 4 } */
#define MBEDTLS_OID_DIGEST_ALG_MD5 MBEDTLS_OID_RSA_COMPANY "\x02\x05" /**< id-mbedtls_md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5 } */
#define MBEDTLS_OID_DIGEST_ALG_SHA1 MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_OIW_SECSIG_SHA1 /**< id-mbedtls_sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } */
#define MBEDTLS_OID_DIGEST_ALG_SHA224 MBEDTLS_OID_GOV "\x03\x04\x02\x04" /**< id-sha224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 4 } */
#define MBEDTLS_OID_DIGEST_ALG_SHA256 MBEDTLS_OID_GOV "\x03\x04\x02\x01" /**< id-mbedtls_sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1 } */
#define MBEDTLS_OID_DIGEST_ALG_SHA224 MBEDTLS_OID_NIST_ALG "\x02\x04" /**< id-sha224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 4 } */
#define MBEDTLS_OID_DIGEST_ALG_SHA256 MBEDTLS_OID_NIST_ALG "\x02\x01" /**< id-mbedtls_sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1 } */
#define MBEDTLS_OID_DIGEST_ALG_SHA384 MBEDTLS_OID_GOV "\x03\x04\x02\x02" /**< id-sha384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 2 } */
#define MBEDTLS_OID_DIGEST_ALG_SHA384 MBEDTLS_OID_NIST_ALG "\x02\x02" /**< id-sha384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 2 } */
#define MBEDTLS_OID_DIGEST_ALG_SHA512 MBEDTLS_OID_GOV "\x03\x04\x02\x03" /**< id-mbedtls_sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 } */
#define MBEDTLS_OID_DIGEST_ALG_SHA512 MBEDTLS_OID_NIST_ALG "\x02\x03" /**< id-mbedtls_sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 } */
#define MBEDTLS_OID_HMAC_SHA1 MBEDTLS_OID_RSA_COMPANY "\x02\x07" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 7 } */
@ -241,7 +243,20 @@
*/
#define MBEDTLS_OID_DES_CBC MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_OIW_SECSIG_ALG "\x07" /**< desCBC OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 7 } */
#define MBEDTLS_OID_DES_EDE3_CBC MBEDTLS_OID_RSA_COMPANY "\x03\x07" /**< des-ede3-cbc OBJECT IDENTIFIER ::= { iso(1) member-body(2) -- us(840) rsadsi(113549) encryptionAlgorithm(3) 7 } */
#define MBEDTLS_OID_AES MBEDTLS_OID_NIST_ALG "\x01" /** aes OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) 1 } */
/*
* Key Wrapping algorithms
*/
/*
* RFC 5649
*/
#define MBEDTLS_OID_AES128_KW MBEDTLS_OID_AES "\x05" /** id-aes128-wrap OBJECT IDENTIFIER ::= { aes 5 } */
#define MBEDTLS_OID_AES128_KWP MBEDTLS_OID_AES "\x08" /** id-aes128-wrap-pad OBJECT IDENTIFIER ::= { aes 8 } */
#define MBEDTLS_OID_AES192_KW MBEDTLS_OID_AES "\x19" /** id-aes192-wrap OBJECT IDENTIFIER ::= { aes 25 } */
#define MBEDTLS_OID_AES192_KWP MBEDTLS_OID_AES "\x1c" /** id-aes192-wrap-pad OBJECT IDENTIFIER ::= { aes 28 } */
#define MBEDTLS_OID_AES256_KW MBEDTLS_OID_AES "\x2d" /** id-aes256-wrap OBJECT IDENTIFIER ::= { aes 45 } */
#define MBEDTLS_OID_AES256_KWP MBEDTLS_OID_AES "\x30" /** id-aes256-wrap-pad OBJECT IDENTIFIER ::= { aes 48 } */
/*
* PKCS#5 OIDs
*/

View file

@ -40,7 +40,7 @@
#endif
#if defined(MBEDTLS_HAVE_TIME)
#include "mbedtls/platform_time.h"
#include "platform_time.h"
#endif
#ifdef __cplusplus
@ -121,8 +121,8 @@ extern "C" {
#else
/* For size_t */
#include <stddef.h>
extern void * (*mbedtls_calloc)( size_t n, size_t size );
extern void (*mbedtls_free)( void *ptr );
extern void *mbedtls_calloc( size_t n, size_t size );
extern void mbedtls_free( void *ptr );
/**
* \brief This function dynamically sets the memory-management

View file

@ -0,0 +1,181 @@
/**
* \file poly1305.h
*
* \brief This file contains Poly1305 definitions and functions.
*
* Poly1305 is a one-time message authenticator that can be used to
* authenticate messages. Poly1305-AES was created by Daniel
* Bernstein https://cr.yp.to/mac/poly1305-20050329.pdf The generic
* Poly1305 algorithm (not tied to AES) was also standardized in RFC
* 7539.
*
* \author Daniel King <damaki.gh@gmail.com>
*/
/* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.
*
* This file is part of Mbed TLS (https://tls.mbed.org)
*/
#ifndef MBEDTLS_POLY1305_H
#define MBEDTLS_POLY1305_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include <stdint.h>
#include <stddef.h>
#define MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA -0x0057 /**< Invalid input parameter(s). */
#define MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE -0x0059 /**< Feature not available. For example, s part of the API is not implemented. */
#define MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED -0x005B /**< Poly1305 hardware accelerator failed. */
#ifdef __cplusplus
extern "C" {
#endif
#if !defined(MBEDTLS_POLY1305_ALT)
typedef struct
{
uint32_t r[4]; /** The value for 'r' (low 128 bits of the key). */
uint32_t s[4]; /** The value for 's' (high 128 bits of the key). */
uint32_t acc[5]; /** The accumulator number. */
uint8_t queue[16]; /** The current partial block of data. */
size_t queue_len; /** The number of bytes stored in 'queue'. */
}
mbedtls_poly1305_context;
#else /* MBEDTLS_POLY1305_ALT */
#include "poly1305_alt.h"
#endif /* MBEDTLS_POLY1305_ALT */
/**
* \brief This function initializes the specified Poly1305 context.
*
* It must be the first API called before using
* the context.
*
* It is usually followed by a call to
* \c mbedtls_poly1305_starts(), then one or more calls to
* \c mbedtls_poly1305_update(), then one call to
* \c mbedtls_poly1305_finish(), then finally
* \c mbedtls_poly1305_free().
*
* \param ctx The Poly1305 context to initialize.
*/
void mbedtls_poly1305_init( mbedtls_poly1305_context *ctx );
/**
* \brief This function releases and clears the specified Poly1305 context.
*
* \param ctx The Poly1305 context to clear.
*/
void mbedtls_poly1305_free( mbedtls_poly1305_context *ctx );
/**
* \brief This function sets the one-time authentication key.
*
* \warning The key must be unique and unpredictable for each
* invocation of Poly1305.
*
* \param ctx The Poly1305 context to which the key should be bound.
* \param key The buffer containing the 256-bit key.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA
* if ctx or key are NULL.
*/
int mbedtls_poly1305_starts( mbedtls_poly1305_context *ctx,
const unsigned char key[32] );
/**
* \brief This functions feeds an input buffer into an ongoing
* Poly1305 computation.
*
* It is called between \c mbedtls_cipher_poly1305_starts() and
* \c mbedtls_cipher_poly1305_finish().
* It can be called repeatedly to process a stream of data.
*
* \param ctx The Poly1305 context to use for the Poly1305 operation.
* \param ilen The length of the input data (in bytes). Any value is accepted.
* \param input The buffer holding the input data.
* This pointer can be NULL if ilen == 0.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA
* if ctx or input are NULL.
*/
int mbedtls_poly1305_update( mbedtls_poly1305_context *ctx,
const unsigned char *input,
size_t ilen );
/**
* \brief This function generates the Poly1305 Message
* Authentication Code (MAC).
*
* \param ctx The Poly1305 context to use for the Poly1305 operation.
* \param mac The buffer to where the MAC is written. Must be big enough
* to hold the 16-byte MAC.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA
* if ctx or mac are NULL.
*/
int mbedtls_poly1305_finish( mbedtls_poly1305_context *ctx,
unsigned char mac[16] );
/**
* \brief This function calculates the Poly1305 MAC of the input
* buffer with the provided key.
*
* \warning The key must be unique and unpredictable for each
* invocation of Poly1305.
*
* \param key The buffer containing the 256-bit key.
* \param ilen The length of the input data (in bytes). Any value is accepted.
* \param input The buffer holding the input data.
* This pointer can be NULL if ilen == 0.
* \param mac The buffer to where the MAC is written. Must be big enough
* to hold the 16-byte MAC.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA
* if key, input, or mac are NULL.
*/
int mbedtls_poly1305_mac( const unsigned char key[32],
const unsigned char *input,
size_t ilen,
unsigned char mac[16] );
#if defined(MBEDTLS_SELF_TEST)
/**
* \brief The Poly1305 checkup routine.
*
* \return \c 0 on success.
* \return \c 1 on failure.
*/
int mbedtls_poly1305_self_test( int verbose );
#endif /* MBEDTLS_SELF_TEST */
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_POLY1305_H */

View file

@ -62,7 +62,7 @@
#endif
#if defined(MBEDTLS_HAVE_TIME)
#include "mbedtls/platform_time.h"
#include "platform_time.h"
#endif
/*
@ -120,6 +120,7 @@
#define MBEDTLS_ERR_SSL_NON_FATAL -0x6680 /**< The alert message received indicates a non-fatal error. */
#define MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH -0x6600 /**< Couldn't set the hash for verifying CertificateVerify */
#define MBEDTLS_ERR_SSL_CONTINUE_PROCESSING -0x6580 /**< Internal-only message signaling that further message-processing should be done */
#define MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS -0x6500 /**< The asynchronous operation is not completed yet. */
/*
* Various constants
@ -219,7 +220,7 @@
#endif
/*
* Maxium fragment length in bytes,
* Maximum fragment length in bytes,
* determines the size of each of the two internal I/O buffers.
*
* Note: the RFC defines the default size of SSL / TLS messages. If you
@ -233,6 +234,14 @@
#define MBEDTLS_SSL_MAX_CONTENT_LEN 16384 /**< Size of the input / output buffer */
#endif
#if !defined(MBEDTLS_SSL_IN_CONTENT_LEN)
#define MBEDTLS_SSL_IN_CONTENT_LEN MBEDTLS_SSL_MAX_CONTENT_LEN
#endif
#if !defined(MBEDTLS_SSL_OUT_CONTENT_LEN)
#define MBEDTLS_SSL_OUT_CONTENT_LEN MBEDTLS_SSL_MAX_CONTENT_LEN
#endif
/* \} name SECTION: Module settings */
/*
@ -536,7 +545,6 @@ typedef void mbedtls_ssl_set_timer_t( void * ctx,
*/
typedef int mbedtls_ssl_get_timer_t( void * ctx );
/* Defined below */
typedef struct mbedtls_ssl_session mbedtls_ssl_session;
typedef struct mbedtls_ssl_context mbedtls_ssl_context;
@ -553,6 +561,218 @@ typedef struct mbedtls_ssl_key_cert mbedtls_ssl_key_cert;
typedef struct mbedtls_ssl_flight_item mbedtls_ssl_flight_item;
#endif
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
#if defined(MBEDTLS_X509_CRT_PARSE_C)
/**
* \brief Callback type: start external signature operation.
*
* This callback is called during an SSL handshake to start
* a signature decryption operation using an
* external processor. The parameter \p cert contains
* the public key; it is up to the callback function to
* determine how to access the associated private key.
*
* This function typically sends or enqueues a request, and
* does not wait for the operation to complete. This allows
* the handshake step to be non-blocking.
*
* The parameters \p ssl and \p cert are guaranteed to remain
* valid throughout the handshake. On the other hand, this
* function must save the contents of \p hash if the value
* is needed for later processing, because the \p hash buffer
* is no longer valid after this function returns.
*
* This function may call mbedtls_ssl_set_async_operation_data()
* to store an operation context for later retrieval
* by the resume or cancel callback.
*
* \note For RSA signatures, this function must produce output
* that is consistent with PKCS#1 v1.5 in the same way as
* mbedtls_rsa_pkcs1_sign(). Before the private key operation,
* apply the padding steps described in RFC 8017, section 9.2
* "EMSA-PKCS1-v1_5" as follows.
* - If \p md_alg is #MBEDTLS_MD_NONE, apply the PKCS#1 v1.5
* encoding, treating \p hash as the DigestInfo to be
* padded. In other words, apply EMSA-PKCS1-v1_5 starting
* from step 3, with `T = hash` and `tLen = hash_len`.
* - If `md_alg != MBEDTLS_MD_NONE`, apply the PKCS#1 v1.5
* encoding, treating \p hash as the hash to be encoded and
* padded. In other words, apply EMSA-PKCS1-v1_5 starting
* from step 2, with `digestAlgorithm` obtained by calling
* mbedtls_oid_get_oid_by_md() on \p md_alg.
*
* \note For ECDSA signatures, the output format is the DER encoding
* `Ecdsa-Sig-Value` defined in
* [RFC 4492 section 5.4](https://tools.ietf.org/html/rfc4492#section-5.4).
*
* \param ssl The SSL connection instance. It should not be
* modified other than via
* mbedtls_ssl_set_async_operation_data().
* \param cert Certificate containing the public key.
* In simple cases, this is one of the pointers passed to
* mbedtls_ssl_conf_own_cert() when configuring the SSL
* connection. However, if other callbacks are used, this
* property may not hold. For example, if an SNI callback
* is registered with mbedtls_ssl_conf_sni(), then
* this callback determines what certificate is used.
* \param md_alg Hash algorithm.
* \param hash Buffer containing the hash. This buffer is
* no longer valid when the function returns.
* \param hash_len Size of the \c hash buffer in bytes.
*
* \return 0 if the operation was started successfully and the SSL
* stack should call the resume callback immediately.
* \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the operation
* was started successfully and the SSL stack should return
* immediately without calling the resume callback yet.
* \return #MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH if the external
* processor does not support this key. The SSL stack will
* use the private key object instead.
* \return Any other error indicates a fatal failure and is
* propagated up the call chain. The callback should
* use \c MBEDTLS_ERR_PK_xxx error codes, and <b>must not</b>
* use \c MBEDTLS_ERR_SSL_xxx error codes except as
* directed in the documentation of this callback.
*/
typedef int mbedtls_ssl_async_sign_t( mbedtls_ssl_context *ssl,
mbedtls_x509_crt *cert,
mbedtls_md_type_t md_alg,
const unsigned char *hash,
size_t hash_len );
/**
* \brief Callback type: start external decryption operation.
*
* This callback is called during an SSL handshake to start
* an RSA decryption operation using an
* external processor. The parameter \p cert contains
* the public key; it is up to the callback function to
* determine how to access the associated private key.
*
* This function typically sends or enqueues a request, and
* does not wait for the operation to complete. This allows
* the handshake step to be non-blocking.
*
* The parameters \p ssl and \p cert are guaranteed to remain
* valid throughout the handshake. On the other hand, this
* function must save the contents of \p input if the value
* is needed for later processing, because the \p input buffer
* is no longer valid after this function returns.
*
* This function may call mbedtls_ssl_set_async_operation_data()
* to store an operation context for later retrieval
* by the resume or cancel callback.
*
* \warning RSA decryption as used in TLS is subject to a potential
* timing side channel attack first discovered by Bleichenbacher
* in 1998. This attack can be remotely exploitable
* in practice. To avoid this attack, you must ensure that
* if the callback performs an RSA decryption, the time it
* takes to execute and return the result does not depend
* on whether the RSA decryption succeeded or reported
* invalid padding.
*
* \param ssl The SSL connection instance. It should not be
* modified other than via
* mbedtls_ssl_set_async_operation_data().
* \param cert Certificate containing the public key.
* In simple cases, this is one of the pointers passed to
* mbedtls_ssl_conf_own_cert() when configuring the SSL
* connection. However, if other callbacks are used, this
* property may not hold. For example, if an SNI callback
* is registered with mbedtls_ssl_conf_sni(), then
* this callback determines what certificate is used.
* \param input Buffer containing the input ciphertext. This buffer
* is no longer valid when the function returns.
* \param input_len Size of the \p input buffer in bytes.
*
* \return 0 if the operation was started successfully and the SSL
* stack should call the resume callback immediately.
* \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the operation
* was started successfully and the SSL stack should return
* immediately without calling the resume callback yet.
* \return #MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH if the external
* processor does not support this key. The SSL stack will
* use the private key object instead.
* \return Any other error indicates a fatal failure and is
* propagated up the call chain. The callback should
* use \c MBEDTLS_ERR_PK_xxx error codes, and <b>must not</b>
* use \c MBEDTLS_ERR_SSL_xxx error codes except as
* directed in the documentation of this callback.
*/
typedef int mbedtls_ssl_async_decrypt_t( mbedtls_ssl_context *ssl,
mbedtls_x509_crt *cert,
const unsigned char *input,
size_t input_len );
#endif /* MBEDTLS_X509_CRT_PARSE_C */
/**
* \brief Callback type: resume external operation.
*
* This callback is called during an SSL handshake to resume
* an external operation started by the
* ::mbedtls_ssl_async_sign_t or
* ::mbedtls_ssl_async_decrypt_t callback.
*
* This function typically checks the status of a pending
* request or causes the request queue to make progress, and
* does not wait for the operation to complete. This allows
* the handshake step to be non-blocking.
*
* This function may call mbedtls_ssl_get_async_operation_data()
* to retrieve an operation context set by the start callback.
* It may call mbedtls_ssl_set_async_operation_data() to modify
* this context.
*
* Note that when this function returns a status other than
* #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, it must free any
* resources associated with the operation.
*
* \param ssl The SSL connection instance. It should not be
* modified other than via
* mbedtls_ssl_set_async_operation_data().
* \param output Buffer containing the output (signature or decrypted
* data) on success.
* \param output_len On success, number of bytes written to \p output.
* \param output_size Size of the \p output buffer in bytes.
*
* \return 0 if output of the operation is available in the
* \p output buffer.
* \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the operation
* is still in progress. Subsequent requests for progress
* on the SSL connection will call the resume callback
* again.
* \return Any other error means that the operation is aborted.
* The SSL handshake is aborted. The callback should
* use \c MBEDTLS_ERR_PK_xxx error codes, and <b>must not</b>
* use \c MBEDTLS_ERR_SSL_xxx error codes except as
* directed in the documentation of this callback.
*/
typedef int mbedtls_ssl_async_resume_t( mbedtls_ssl_context *ssl,
unsigned char *output,
size_t *output_len,
size_t output_size );
/**
* \brief Callback type: cancel external operation.
*
* This callback is called if an SSL connection is closed
* while an asynchronous operation is in progress. Note that
* this callback is not called if the
* ::mbedtls_ssl_async_resume_t callback has run and has
* returned a value other than
* #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, since in that case
* the asynchronous operation has already completed.
*
* This function may call mbedtls_ssl_get_async_operation_data()
* to retrieve an operation context set by the start callback.
*
* \param ssl The SSL connection instance. It should not be
* modified.
*/
typedef void mbedtls_ssl_async_cancel_t( mbedtls_ssl_context *ssl );
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
/*
* This structure is used for storing current session data.
*/
@ -669,6 +889,16 @@ struct mbedtls_ssl_config
mbedtls_x509_crl *ca_crl; /*!< trusted CAs CRLs */
#endif /* MBEDTLS_X509_CRT_PARSE_C */
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
#if defined(MBEDTLS_X509_CRT_PARSE_C)
mbedtls_ssl_async_sign_t *f_async_sign_start; /*!< start asynchronous signature operation */
mbedtls_ssl_async_decrypt_t *f_async_decrypt_start; /*!< start asynchronous decryption operation */
#endif /* MBEDTLS_X509_CRT_PARSE_C */
mbedtls_ssl_async_resume_t *f_async_resume; /*!< resume asynchronous operation */
mbedtls_ssl_async_cancel_t *f_async_cancel; /*!< cancel asynchronous operation */
void *p_async_config_data; /*!< Configuration data set by mbedtls_ssl_conf_async_private_cb(). */
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED)
const int *sig_hashes; /*!< allowed signature hashes */
#endif
@ -1307,6 +1537,85 @@ void mbedtls_ssl_conf_export_keys_cb( mbedtls_ssl_config *conf,
void *p_export_keys );
#endif /* MBEDTLS_SSL_EXPORT_KEYS */
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
/**
* \brief Configure asynchronous private key operation callbacks.
*
* \param conf SSL configuration context
* \param f_async_sign Callback to start a signature operation. See
* the description of ::mbedtls_ssl_async_sign_t
* for more information. This may be \c NULL if the
* external processor does not support any signature
* operation; in this case the private key object
* associated with the certificate will be used.
* \param f_async_decrypt Callback to start a decryption operation. See
* the description of ::mbedtls_ssl_async_decrypt_t
* for more information. This may be \c NULL if the
* external processor does not support any decryption
* operation; in this case the private key object
* associated with the certificate will be used.
* \param f_async_resume Callback to resume an asynchronous operation. See
* the description of ::mbedtls_ssl_async_resume_t
* for more information. This may not be \c NULL unless
* \p f_async_sign and \p f_async_decrypt are both
* \c NULL.
* \param f_async_cancel Callback to cancel an asynchronous operation. See
* the description of ::mbedtls_ssl_async_cancel_t
* for more information. This may be \c NULL if
* no cleanup is needed.
* \param config_data A pointer to configuration data which can be
* retrieved with
* mbedtls_ssl_conf_get_async_config_data(). The
* library stores this value without dereferencing it.
*/
void mbedtls_ssl_conf_async_private_cb( mbedtls_ssl_config *conf,
mbedtls_ssl_async_sign_t *f_async_sign,
mbedtls_ssl_async_decrypt_t *f_async_decrypt,
mbedtls_ssl_async_resume_t *f_async_resume,
mbedtls_ssl_async_cancel_t *f_async_cancel,
void *config_data );
/**
* \brief Retrieve the configuration data set by
* mbedtls_ssl_conf_async_private_cb().
*
* \param conf SSL configuration context
* \return The configuration data set by
* mbedtls_ssl_conf_async_private_cb().
*/
void *mbedtls_ssl_conf_get_async_config_data( const mbedtls_ssl_config *conf );
/**
* \brief Retrieve the asynchronous operation user context.
*
* \note This function may only be called while a handshake
* is in progress.
*
* \param ssl The SSL context to access.
*
* \return The asynchronous operation user context that was last
* set during the current handshake. If
* mbedtls_ssl_set_async_operation_data() has not yet been
* called during the current handshake, this function returns
* \c NULL.
*/
void *mbedtls_ssl_get_async_operation_data( const mbedtls_ssl_context *ssl );
/**
* \brief Retrieve the asynchronous operation user context.
*
* \note This function may only be called while a handshake
* is in progress.
*
* \param ssl The SSL context to access.
* \param ctx The new value of the asynchronous operation user context.
* Call mbedtls_ssl_get_async_operation_data() later during the
* same handshake to retrieve this value.
*/
void mbedtls_ssl_set_async_operation_data( mbedtls_ssl_context *ssl,
void *ctx );
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
/**
* \brief Callback type: generate a cookie
*
@ -2117,7 +2426,8 @@ void mbedtls_ssl_conf_cert_req_ca_list( mbedtls_ssl_config *conf,
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
/**
* \brief Set the maximum fragment length to emit and/or negotiate
* (Default: MBEDTLS_SSL_MAX_CONTENT_LEN, usually 2^14 bytes)
* (Default: the smaller of MBEDTLS_SSL_IN_CONTENT_LEN and
* MBEDTLS_SSL_OUT_CONTENT_LEN, usually 2^14 bytes)
* (Server: set maximum fragment length to emit,
* usually negotiated by the client during handshake
* (Client: set maximum fragment length to emit *and*
@ -2436,7 +2746,6 @@ const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ss
* \brief Save session in order to resume it later (client-side only)
* Session data is copied to presented session structure.
*
* \warning Currently, peer certificate is lost in the operation.
*
* \param ssl SSL context
* \param session session context
@ -2444,7 +2753,18 @@ const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ss
* \return 0 if successful,
* MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed,
* MBEDTLS_ERR_SSL_BAD_INPUT_DATA if used server-side or
* arguments are otherwise invalid
* arguments are otherwise invalid.
*
* \note Only the server certificate is copied, and not the full chain,
* so you should not attempt to validate the certificate again
* by calling \c mbedtls_x509_crt_verify() on it.
* Instead, you should use the results from the verification
* in the original handshake by calling \c mbedtls_ssl_get_verify_result()
* after loading the session again into a new SSL context
* using \c mbedtls_ssl_set_session().
*
* \note Once the session object is not needed anymore, you should
* free it by calling \c mbedtls_ssl_session_free().
*
* \sa mbedtls_ssl_set_session()
*/
@ -2606,17 +2926,19 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
* or MBEDTLS_ERR_SSL_WANT_WRITE or MBEDTLS_ERR_SSL_WANT_READ,
* or another negative error code.
*
* \note If this function returns something other than a positive value
* or MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using
* the SSL context for reading or writing, and either free it or
* call \c mbedtls_ssl_session_reset() on it before re-using it
* for a new connection; the current connection must be closed.
* \note If this function returns something other than 0, a positive
* value or MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop
* using the SSL context for reading or writing, and either
* free it or call \c mbedtls_ssl_session_reset() on it before
* re-using it for a new connection; the current connection
* must be closed.
*
* \note When this function returns MBEDTLS_ERR_SSL_WANT_WRITE/READ,
* it must be called later with the *same* arguments,
* until it returns a positive value. When the function returns
* MBEDTLS_ERR_SSL_WANT_WRITE there may be some partial
* data in the output buffer, however this is not yet sent.
* until it returns a value greater that or equal to 0. When
* the function returns MBEDTLS_ERR_SSL_WANT_WRITE there may be
* some partial data in the output buffer, however this is not
* yet sent.
*
* \note If the requested length is greater than the maximum
* fragment length (either the built-in limit or the one set
@ -2625,6 +2947,9 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
* - with DTLS, MBEDTLS_ERR_SSL_BAD_INPUT_DATA is returned.
* \c mbedtls_ssl_get_max_frag_len() may be used to query the
* active maximum fragment length.
*
* \note Attempting to write 0 bytes will result in an empty TLS
* application record being sent.
*/
int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len );
@ -2717,6 +3042,9 @@ void mbedtls_ssl_session_init( mbedtls_ssl_session *session );
* \brief Free referenced items in an SSL session including the
* peer certificate and clear memory
*
* \note A session object can be freed even if the SSL context
* that was used to retrieve the session is still in use.
*
* \param session SSL session
*/
void mbedtls_ssl_session_free( mbedtls_ssl_session *session );

View file

@ -271,6 +271,15 @@ extern "C" {
#define MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 0xC0FF /**< experimental */
/* RFC 7905 */
#define MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA8 /**< TLS 1.2 */
#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA9 /**< TLS 1.2 */
#define MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCAA /**< TLS 1.2 */
#define MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAB /**< TLS 1.2 */
#define MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAC /**< TLS 1.2 */
#define MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAD /**< TLS 1.2 */
#define MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAE /**< TLS 1.2 */
/* Reminder: update mbedtls_ssl_premaster_secret when adding a new key exchange.
* Reminder: update MBEDTLS_KEY_EXCHANGE__xxx below
*/

View file

@ -143,32 +143,73 @@
#define MBEDTLS_SSL_PADDING_ADD 0
#endif
#define MBEDTLS_SSL_PAYLOAD_LEN ( MBEDTLS_SSL_MAX_CONTENT_LEN \
+ MBEDTLS_SSL_COMPRESSION_ADD \
+ MBEDTLS_MAX_IV_LENGTH \
+ MBEDTLS_SSL_MAC_ADD \
+ MBEDTLS_SSL_PADDING_ADD \
)
#define MBEDTLS_SSL_PAYLOAD_OVERHEAD ( MBEDTLS_SSL_COMPRESSION_ADD + \
MBEDTLS_MAX_IV_LENGTH + \
MBEDTLS_SSL_MAC_ADD + \
MBEDTLS_SSL_PADDING_ADD \
)
#define MBEDTLS_SSL_IN_PAYLOAD_LEN ( MBEDTLS_SSL_PAYLOAD_OVERHEAD + \
( MBEDTLS_SSL_IN_CONTENT_LEN ) )
#define MBEDTLS_SSL_OUT_PAYLOAD_LEN ( MBEDTLS_SSL_PAYLOAD_OVERHEAD + \
( MBEDTLS_SSL_OUT_CONTENT_LEN ) )
/* Maximum length we can advertise as our max content length for
RFC 6066 max_fragment_length extension negotiation purposes
(the lesser of both sizes, if they are unequal.)
*/
#define MBEDTLS_TLS_EXT_ADV_CONTENT_LEN ( \
(MBEDTLS_SSL_IN_CONTENT_LEN > MBEDTLS_SSL_OUT_CONTENT_LEN) \
? ( MBEDTLS_SSL_OUT_CONTENT_LEN ) \
: ( MBEDTLS_SSL_IN_CONTENT_LEN ) \
)
/*
* Check that we obey the standard's message size bounds
*/
#if MBEDTLS_SSL_MAX_CONTENT_LEN > 16384
#error Bad configuration - record content too large.
#error "Bad configuration - record content too large."
#endif
#if MBEDTLS_SSL_PAYLOAD_LEN > 16384 + 2048
#error Bad configuration - protected record payload too large.
#if MBEDTLS_SSL_IN_CONTENT_LEN > MBEDTLS_SSL_MAX_CONTENT_LEN
#error "Bad configuration - incoming record content should not be larger than MBEDTLS_SSL_MAX_CONTENT_LEN."
#endif
#if MBEDTLS_SSL_OUT_CONTENT_LEN > MBEDTLS_SSL_MAX_CONTENT_LEN
#error "Bad configuration - outgoing record content should not be larger than MBEDTLS_SSL_MAX_CONTENT_LEN."
#endif
#if MBEDTLS_SSL_IN_PAYLOAD_LEN > MBEDTLS_SSL_MAX_CONTENT_LEN + 2048
#error "Bad configuration - incoming protected record payload too large."
#endif
#if MBEDTLS_SSL_OUT_PAYLOAD_LEN > MBEDTLS_SSL_MAX_CONTENT_LEN + 2048
#error "Bad configuration - outgoing protected record payload too large."
#endif
/* Calculate buffer sizes */
/* Note: Even though the TLS record header is only 5 bytes
long, we're internally using 8 bytes to store the
implicit sequence number. */
#define MBEDTLS_SSL_HEADER_LEN 13
#define MBEDTLS_SSL_BUFFER_LEN \
( ( MBEDTLS_SSL_HEADER_LEN ) + ( MBEDTLS_SSL_PAYLOAD_LEN ) )
#define MBEDTLS_SSL_IN_BUFFER_LEN \
( ( MBEDTLS_SSL_HEADER_LEN ) + ( MBEDTLS_SSL_IN_PAYLOAD_LEN ) )
#define MBEDTLS_SSL_OUT_BUFFER_LEN \
( ( MBEDTLS_SSL_HEADER_LEN ) + ( MBEDTLS_SSL_OUT_PAYLOAD_LEN ) )
#ifdef MBEDTLS_ZLIB_SUPPORT
/* Compression buffer holds both IN and OUT buffers, so should be size of the larger */
#define MBEDTLS_SSL_COMPRESS_BUFFER_LEN ( \
( MBEDTLS_SSL_IN_BUFFER_LEN > MBEDTLS_SSL_OUT_BUFFER_LEN ) \
? MBEDTLS_SSL_IN_BUFFER_LEN \
: MBEDTLS_SSL_OUT_BUFFER_LEN \
)
#endif
/*
* TLS extension flags (for extensions with outgoing ServerHello content
@ -243,6 +284,7 @@ struct mbedtls_ssl_handshake_params
mbedtls_x509_crl *sni_ca_crl; /*!< trusted CAs CRLs from SNI */
#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
#endif /* MBEDTLS_X509_CRT_PARSE_C */
#if defined(MBEDTLS_SSL_PROTO_DTLS)
unsigned int out_msg_seq; /*!< Outgoing handshake sequence number */
unsigned int in_msg_seq; /*!< Incoming handshake sequence number */
@ -307,6 +349,19 @@ struct mbedtls_ssl_handshake_params
#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
int extended_ms; /*!< use Extended Master Secret? */
#endif
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
unsigned int async_in_progress : 1; /*!< an asynchronous operation is in progress */
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
/** Asynchronous operation context. This field is meant for use by the
* asynchronous operation callbacks (mbedtls_ssl_config::f_async_sign_start,
* mbedtls_ssl_config::f_async_decrypt_start,
* mbedtls_ssl_config::f_async_resume, mbedtls_ssl_config::f_async_cancel).
* The library does not use it internally. */
void *user_async_ctx;
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
};
/*
@ -410,9 +465,9 @@ void mbedtls_ssl_transform_free( mbedtls_ssl_transform *transform );
* \brief Free referenced items in an SSL handshake context and clear
* memory
*
* \param handshake SSL handshake context
* \param ssl SSL context
*/
void mbedtls_ssl_handshake_free( mbedtls_ssl_handshake_params *handshake );
void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl );
int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl );
int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl );
@ -630,7 +685,13 @@ static inline int mbedtls_ssl_safer_memcmp( const void *a, const void *b, size_t
volatile unsigned char diff = 0;
for( i = 0; i < n; i++ )
diff |= A[i] ^ B[i];
{
/* Read volatile data in order before computing diff.
* This avoids IAR compiler warning:
* 'the order of volatile accesses is undefined ..' */
unsigned char x = A[i], y = B[i];
diff |= x ^ y;
}
return( diff );
}
@ -646,9 +707,9 @@ int mbedtls_ssl_get_key_exchange_md_ssl_tls( mbedtls_ssl_context *ssl,
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
defined(MBEDTLS_SSL_PROTO_TLS1_2)
int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl,
unsigned char *output,
unsigned char *data, size_t data_len,
mbedtls_md_type_t md_alg );
unsigned char *hash, size_t *hashlen,
unsigned char *data, size_t data_len,
mbedtls_md_type_t md_alg );
#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \
MBEDTLS_SSL_PROTO_TLS1_2 */

View file

@ -99,9 +99,6 @@ extern int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t *mutex );
#if defined(MBEDTLS_FS_IO)
extern mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex;
#endif
#if defined(MBEDTLS_HAVE_TIME_DATE)
extern mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex;
#endif
#endif /* MBEDTLS_THREADING_C */
#ifdef __cplusplus

View file

@ -39,7 +39,7 @@
* Major, Minor, Patchlevel
*/
#define MBEDTLS_VERSION_MAJOR 2
#define MBEDTLS_VERSION_MINOR 10
#define MBEDTLS_VERSION_MINOR 12
#define MBEDTLS_VERSION_PATCH 0
/**
@ -47,9 +47,9 @@
* MMNNPP00
* Major version | Minor version | Patch version
*/
#define MBEDTLS_VERSION_NUMBER 0x020A0000
#define MBEDTLS_VERSION_STRING "2.10.0"
#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.10.0"
#define MBEDTLS_VERSION_NUMBER 0x020C0000
#define MBEDTLS_VERSION_STRING "2.12.0"
#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.12.0"
#if defined(MBEDTLS_VERSION_C)

View file

@ -521,6 +521,20 @@ void mbedtls_aes_free( mbedtls_aes_context *ctx )
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_aes_context ) );
}
#if defined(MBEDTLS_CIPHER_MODE_XTS)
void mbedtls_aes_xts_init( mbedtls_aes_xts_context *ctx )
{
mbedtls_aes_init( &ctx->crypt );
mbedtls_aes_init( &ctx->tweak );
}
void mbedtls_aes_xts_free( mbedtls_aes_xts_context *ctx )
{
mbedtls_aes_free( &ctx->crypt );
mbedtls_aes_free( &ctx->tweak );
}
#endif /* MBEDTLS_CIPHER_MODE_XTS */
/*
* AES key schedule (encryption)
*/
@ -702,6 +716,78 @@ exit:
return( ret );
}
#if defined(MBEDTLS_CIPHER_MODE_XTS)
static int mbedtls_aes_xts_decode_keys( const unsigned char *key,
unsigned int keybits,
const unsigned char **key1,
unsigned int *key1bits,
const unsigned char **key2,
unsigned int *key2bits )
{
const unsigned int half_keybits = keybits / 2;
const unsigned int half_keybytes = half_keybits / 8;
switch( keybits )
{
case 256: break;
case 512: break;
default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
}
*key1bits = half_keybits;
*key2bits = half_keybits;
*key1 = &key[0];
*key2 = &key[half_keybytes];
return 0;
}
int mbedtls_aes_xts_setkey_enc( mbedtls_aes_xts_context *ctx,
const unsigned char *key,
unsigned int keybits)
{
int ret;
const unsigned char *key1, *key2;
unsigned int key1bits, key2bits;
ret = mbedtls_aes_xts_decode_keys( key, keybits, &key1, &key1bits,
&key2, &key2bits );
if( ret != 0 )
return( ret );
/* Set the tweak key. Always set tweak key for the encryption mode. */
ret = mbedtls_aes_setkey_enc( &ctx->tweak, key2, key2bits );
if( ret != 0 )
return( ret );
/* Set crypt key for encryption. */
return mbedtls_aes_setkey_enc( &ctx->crypt, key1, key1bits );
}
int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx,
const unsigned char *key,
unsigned int keybits)
{
int ret;
const unsigned char *key1, *key2;
unsigned int key1bits, key2bits;
ret = mbedtls_aes_xts_decode_keys( key, keybits, &key1, &key1bits,
&key2, &key2bits );
if( ret != 0 )
return( ret );
/* Set the tweak key. Always set tweak key for encryption. */
ret = mbedtls_aes_setkey_enc( &ctx->tweak, key2, key2bits );
if( ret != 0 )
return( ret );
/* Set crypt key for decryption. */
return mbedtls_aes_setkey_dec( &ctx->crypt, key1, key1bits );
}
#endif /* MBEDTLS_CIPHER_MODE_XTS */
#endif /* !MBEDTLS_AES_SETKEY_DEC_ALT */
#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
@ -983,6 +1069,165 @@ int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx,
}
#endif /* MBEDTLS_CIPHER_MODE_CBC */
#if defined(MBEDTLS_CIPHER_MODE_XTS)
/* Endianess with 64 bits values */
#ifndef GET_UINT64_LE
#define GET_UINT64_LE(n,b,i) \
{ \
(n) = ( (uint64_t) (b)[(i) + 7] << 56 ) \
| ( (uint64_t) (b)[(i) + 6] << 48 ) \
| ( (uint64_t) (b)[(i) + 5] << 40 ) \
| ( (uint64_t) (b)[(i) + 4] << 32 ) \
| ( (uint64_t) (b)[(i) + 3] << 24 ) \
| ( (uint64_t) (b)[(i) + 2] << 16 ) \
| ( (uint64_t) (b)[(i) + 1] << 8 ) \
| ( (uint64_t) (b)[(i) ] ); \
}
#endif
#ifndef PUT_UINT64_LE
#define PUT_UINT64_LE(n,b,i) \
{ \
(b)[(i) + 7] = (unsigned char) ( (n) >> 56 ); \
(b)[(i) + 6] = (unsigned char) ( (n) >> 48 ); \
(b)[(i) + 5] = (unsigned char) ( (n) >> 40 ); \
(b)[(i) + 4] = (unsigned char) ( (n) >> 32 ); \
(b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) ] = (unsigned char) ( (n) ); \
}
#endif
typedef unsigned char mbedtls_be128[16];
/*
* GF(2^128) multiplication function
*
* This function multiplies a field element by x in the polynomial field
* representation. It uses 64-bit word operations to gain speed but compensates
* for machine endianess and hence works correctly on both big and little
* endian machines.
*/
static void mbedtls_gf128mul_x_ble( unsigned char r[16],
const unsigned char x[16] )
{
uint64_t a, b, ra, rb;
GET_UINT64_LE( a, x, 0 );
GET_UINT64_LE( b, x, 8 );
ra = ( a << 1 ) ^ 0x0087 >> ( 8 - ( ( b >> 63 ) << 3 ) );
rb = ( a >> 63 ) | ( b << 1 );
PUT_UINT64_LE( ra, r, 0 );
PUT_UINT64_LE( rb, r, 8 );
}
/*
* AES-XTS buffer encryption/decryption
*/
int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx,
int mode,
size_t length,
const unsigned char data_unit[16],
const unsigned char *input,
unsigned char *output )
{
int ret;
size_t blocks = length / 16;
size_t leftover = length % 16;
unsigned char tweak[16];
unsigned char prev_tweak[16];
unsigned char tmp[16];
/* Sectors must be at least 16 bytes. */
if( length < 16 )
return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
/* NIST SP 80-38E disallows data units larger than 2**20 blocks. */
if( length > ( 1 << 20 ) * 16 )
return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
/* Compute the tweak. */
ret = mbedtls_aes_crypt_ecb( &ctx->tweak, MBEDTLS_AES_ENCRYPT,
data_unit, tweak );
if( ret != 0 )
return( ret );
while( blocks-- )
{
size_t i;
if( leftover && ( mode == MBEDTLS_AES_DECRYPT ) && blocks == 0 )
{
/* We are on the last block in a decrypt operation that has
* leftover bytes, so we need to use the next tweak for this block,
* and this tweak for the lefover bytes. Save the current tweak for
* the leftovers and then update the current tweak for use on this,
* the last full block. */
memcpy( prev_tweak, tweak, sizeof( tweak ) );
mbedtls_gf128mul_x_ble( tweak, tweak );
}
for( i = 0; i < 16; i++ )
tmp[i] = input[i] ^ tweak[i];
ret = mbedtls_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp );
if( ret != 0 )
return( ret );
for( i = 0; i < 16; i++ )
output[i] = tmp[i] ^ tweak[i];
/* Update the tweak for the next block. */
mbedtls_gf128mul_x_ble( tweak, tweak );
output += 16;
input += 16;
}
if( leftover )
{
/* If we are on the leftover bytes in a decrypt operation, we need to
* use the previous tweak for these bytes (as saved in prev_tweak). */
unsigned char *t = mode == MBEDTLS_AES_DECRYPT ? prev_tweak : tweak;
/* We are now on the final part of the data unit, which doesn't divide
* evenly by 16. It's time for ciphertext stealing. */
size_t i;
unsigned char *prev_output = output - 16;
/* Copy ciphertext bytes from the previous block to our output for each
* byte of cyphertext we won't steal. At the same time, copy the
* remainder of the input for this final round (since the loop bounds
* are the same). */
for( i = 0; i < leftover; i++ )
{
output[i] = prev_output[i];
tmp[i] = input[i] ^ t[i];
}
/* Copy ciphertext bytes from the previous block for input in this
* round. */
for( ; i < 16; i++ )
tmp[i] = prev_output[i] ^ t[i];
ret = mbedtls_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp );
if( ret != 0 )
return ret;
/* Write the result back to the previous block, overriding the previous
* output we copied. */
for( i = 0; i < 16; i++ )
prev_output[i] = tmp[i] ^ t[i];
}
return( 0 );
}
#endif /* MBEDTLS_CIPHER_MODE_XTS */
#if defined(MBEDTLS_CIPHER_MODE_CFB)
/*
* AES-CFB128 buffer encryption/decryption
@ -1061,7 +1306,41 @@ int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx,
return( 0 );
}
#endif /*MBEDTLS_CIPHER_MODE_CFB */
#endif /* MBEDTLS_CIPHER_MODE_CFB */
#if defined(MBEDTLS_CIPHER_MODE_OFB)
/*
* AES-OFB (Output Feedback Mode) buffer encryption/decryption
*/
int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx,
size_t length,
size_t *iv_off,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output )
{
int ret = 0;
size_t n = *iv_off;
while( length-- )
{
if( n == 0 )
{
ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
if( ret != 0 )
goto exit;
}
*output++ = *input++ ^ iv[n];
n = ( n + 1 ) & 0x0F;
}
*iv_off = n;
exit:
return( ret );
}
#endif /* MBEDTLS_CIPHER_MODE_OFB */
#if defined(MBEDTLS_CIPHER_MODE_CTR)
/*
@ -1218,6 +1497,72 @@ static const unsigned char aes_test_cfb128_ct[3][64] =
};
#endif /* MBEDTLS_CIPHER_MODE_CFB */
#if defined(MBEDTLS_CIPHER_MODE_OFB)
/*
* AES-OFB test vectors from:
*
* https://csrc.nist.gov/publications/detail/sp/800-38a/final
*/
static const unsigned char aes_test_ofb_key[3][32] =
{
{ 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C },
{ 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52,
0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5,
0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B },
{ 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE,
0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81,
0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7,
0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 }
};
static const unsigned char aes_test_ofb_iv[16] =
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
};
static const unsigned char aes_test_ofb_pt[64] =
{
0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96,
0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A,
0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C,
0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51,
0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11,
0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF,
0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17,
0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10
};
static const unsigned char aes_test_ofb_ct[3][64] =
{
{ 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20,
0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A,
0x77, 0x89, 0x50, 0x8d, 0x16, 0x91, 0x8f, 0x03,
0xf5, 0x3c, 0x52, 0xda, 0xc5, 0x4e, 0xd8, 0x25,
0x97, 0x40, 0x05, 0x1e, 0x9c, 0x5f, 0xec, 0xf6,
0x43, 0x44, 0xf7, 0xa8, 0x22, 0x60, 0xed, 0xcc,
0x30, 0x4c, 0x65, 0x28, 0xf6, 0x59, 0xc7, 0x78,
0x66, 0xa5, 0x10, 0xd9, 0xc1, 0xd6, 0xae, 0x5e },
{ 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB,
0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74,
0xfc, 0xc2, 0x8b, 0x8d, 0x4c, 0x63, 0x83, 0x7c,
0x09, 0xe8, 0x17, 0x00, 0xc1, 0x10, 0x04, 0x01,
0x8d, 0x9a, 0x9a, 0xea, 0xc0, 0xf6, 0x59, 0x6f,
0x55, 0x9c, 0x6d, 0x4d, 0xaf, 0x59, 0xa5, 0xf2,
0x6d, 0x9f, 0x20, 0x08, 0x57, 0xca, 0x6c, 0x3e,
0x9c, 0xac, 0x52, 0x4b, 0xd9, 0xac, 0xc9, 0x2a },
{ 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B,
0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60,
0x4f, 0xeb, 0xdc, 0x67, 0x40, 0xd2, 0x0b, 0x3a,
0xc8, 0x8f, 0x6a, 0xd8, 0x2a, 0x4f, 0xb0, 0x8d,
0x71, 0xab, 0x47, 0xa0, 0x86, 0xe8, 0x6e, 0xed,
0xf3, 0x9d, 0x1c, 0x5b, 0xba, 0x97, 0xc4, 0x08,
0x01, 0x26, 0x14, 0x1d, 0x67, 0xf3, 0x7b, 0xe8,
0x53, 0x8f, 0x5a, 0x8b, 0xe7, 0x40, 0xe4, 0x84 }
};
#endif /* MBEDTLS_CIPHER_MODE_OFB */
#if defined(MBEDTLS_CIPHER_MODE_CTR)
/*
* AES-CTR test vectors from:
@ -1281,6 +1626,74 @@ static const int aes_test_ctr_len[3] =
{ 16, 32, 36 };
#endif /* MBEDTLS_CIPHER_MODE_CTR */
#if defined(MBEDTLS_CIPHER_MODE_XTS)
/*
* AES-XTS test vectors from:
*
* IEEE P1619/D16 Annex B
* https://web.archive.org/web/20150629024421/http://grouper.ieee.org/groups/1619/email/pdf00086.pdf
* (Archived from original at http://grouper.ieee.org/groups/1619/email/pdf00086.pdf)
*/
static const unsigned char aes_test_xts_key[][32] =
{
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 },
{ 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8,
0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 },
};
static const unsigned char aes_test_xts_pt32[][32] =
{
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 },
{ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 },
};
static const unsigned char aes_test_xts_ct32[][32] =
{
{ 0x91, 0x7c, 0xf6, 0x9e, 0xbd, 0x68, 0xb2, 0xec,
0x9b, 0x9f, 0xe9, 0xa3, 0xea, 0xdd, 0xa6, 0x92,
0xcd, 0x43, 0xd2, 0xf5, 0x95, 0x98, 0xed, 0x85,
0x8c, 0x02, 0xc2, 0x65, 0x2f, 0xbf, 0x92, 0x2e },
{ 0xc4, 0x54, 0x18, 0x5e, 0x6a, 0x16, 0x93, 0x6e,
0x39, 0x33, 0x40, 0x38, 0xac, 0xef, 0x83, 0x8b,
0xfb, 0x18, 0x6f, 0xff, 0x74, 0x80, 0xad, 0xc4,
0x28, 0x93, 0x82, 0xec, 0xd6, 0xd3, 0x94, 0xf0 },
{ 0xaf, 0x85, 0x33, 0x6b, 0x59, 0x7a, 0xfc, 0x1a,
0x90, 0x0b, 0x2e, 0xb2, 0x1e, 0xc9, 0x49, 0xd2,
0x92, 0xdf, 0x4c, 0x04, 0x7e, 0x0b, 0x21, 0x53,
0x21, 0x86, 0xa5, 0x97, 0x1a, 0x22, 0x7a, 0x89 },
};
static const unsigned char aes_test_xts_data_unit[][16] =
{
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
};
#endif /* MBEDTLS_CIPHER_MODE_XTS */
/*
* Checkup routine
*/
@ -1297,11 +1710,14 @@ int mbedtls_aes_self_test( int verbose )
#if defined(MBEDTLS_CIPHER_MODE_CBC)
unsigned char prv[16];
#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_CFB)
#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_CFB) || \
defined(MBEDTLS_CIPHER_MODE_OFB)
size_t offset;
#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR)
#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_XTS)
int len;
#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR)
unsigned char nonce_counter[16];
unsigned char stream_block[16];
#endif
@ -1509,6 +1925,69 @@ int mbedtls_aes_self_test( int verbose )
mbedtls_printf( "\n" );
#endif /* MBEDTLS_CIPHER_MODE_CFB */
#if defined(MBEDTLS_CIPHER_MODE_OFB)
/*
* OFB mode
*/
for( i = 0; i < 6; i++ )
{
u = i >> 1;
keybits = 128 + u * 64;
mode = i & 1;
if( verbose != 0 )
mbedtls_printf( " AES-OFB-%3d (%s): ", keybits,
( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
memcpy( iv, aes_test_ofb_iv, 16 );
memcpy( key, aes_test_ofb_key[u], keybits / 8 );
offset = 0;
ret = mbedtls_aes_setkey_enc( &ctx, key, keybits );
/*
* AES-192 is an optional feature that may be unavailable when
* there is an alternative underlying implementation i.e. when
* MBEDTLS_AES_ALT is defined.
*/
if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 )
{
mbedtls_printf( "skipped\n" );
continue;
}
else if( ret != 0 )
{
goto exit;
}
if( mode == MBEDTLS_AES_DECRYPT )
{
memcpy( buf, aes_test_ofb_ct[u], 64 );
aes_tests = aes_test_ofb_pt;
}
else
{
memcpy( buf, aes_test_ofb_pt, 64 );
aes_tests = aes_test_ofb_ct[u];
}
ret = mbedtls_aes_crypt_ofb( &ctx, 64, &offset, iv, buf, buf );
if( ret != 0 )
goto exit;
if( memcmp( buf, aes_tests, 64 ) != 0 )
{
ret = 1;
goto exit;
}
if( verbose != 0 )
mbedtls_printf( "passed\n" );
}
if( verbose != 0 )
mbedtls_printf( "\n" );
#endif /* MBEDTLS_CIPHER_MODE_OFB */
#if defined(MBEDTLS_CIPHER_MODE_CTR)
/*
* CTR mode
@ -1561,6 +2040,73 @@ int mbedtls_aes_self_test( int verbose )
mbedtls_printf( "\n" );
#endif /* MBEDTLS_CIPHER_MODE_CTR */
#if defined(MBEDTLS_CIPHER_MODE_XTS)
{
static const int num_tests =
sizeof(aes_test_xts_key) / sizeof(*aes_test_xts_key);
mbedtls_aes_xts_context ctx_xts;
/*
* XTS mode
*/
mbedtls_aes_xts_init( &ctx_xts );
for( i = 0; i < num_tests << 1; i++ )
{
const unsigned char *data_unit;
u = i >> 1;
mode = i & 1;
if( verbose != 0 )
mbedtls_printf( " AES-XTS-128 (%s): ",
( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
memset( key, 0, sizeof( key ) );
memcpy( key, aes_test_xts_key[u], 32 );
data_unit = aes_test_xts_data_unit[u];
len = sizeof( *aes_test_xts_ct32 );
if( mode == MBEDTLS_AES_DECRYPT )
{
ret = mbedtls_aes_xts_setkey_dec( &ctx_xts, key, 256 );
if( ret != 0)
goto exit;
memcpy( buf, aes_test_xts_ct32[u], len );
aes_tests = aes_test_xts_pt32[u];
}
else
{
ret = mbedtls_aes_xts_setkey_enc( &ctx_xts, key, 256 );
if( ret != 0)
goto exit;
memcpy( buf, aes_test_xts_pt32[u], len );
aes_tests = aes_test_xts_ct32[u];
}
ret = mbedtls_aes_crypt_xts( &ctx_xts, mode, len, data_unit,
buf, buf );
if( ret != 0 )
goto exit;
if( memcmp( buf, aes_tests, len ) != 0 )
{
ret = 1;
goto exit;
}
if( verbose != 0 )
mbedtls_printf( "passed\n" );
}
if( verbose != 0 )
mbedtls_printf( "\n" );
mbedtls_aes_xts_free( &ctx_xts );
}
#endif /* MBEDTLS_CIPHER_MODE_XTS */
ret = 0;
exit:

View file

@ -83,7 +83,9 @@ int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len
return( 4 );
}
#if SIZE_MAX > 0xFFFFFFFF
if( len <= 0xFFFFFFFF )
#endif
{
if( *p - start < 5 )
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
@ -96,7 +98,9 @@ int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len
return( 5 );
}
#if SIZE_MAX > 0xFFFFFFFF
return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
#endif
}
int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag )

View file

@ -152,8 +152,10 @@ static int ccm_auth_crypt( mbedtls_ccm_context *ctx, int mode, size_t length,
* Check length requirements: SP800-38C A.1
* Additional requirement: a < 2^16 - 2^8 to simplify the code.
* 'length' checked later (when writing it to the first block)
*
* Also, loosen the requirements to enable support for CCM* (IEEE 802.15.4).
*/
if( tag_len < 4 || tag_len > 16 || tag_len % 2 != 0 )
if( tag_len == 2 || tag_len > 16 || tag_len % 2 != 0 )
return( MBEDTLS_ERR_CCM_BAD_INPUT );
/* Also implies q is within bounds */
@ -302,7 +304,7 @@ static int ccm_auth_crypt( mbedtls_ccm_context *ctx, int mode, size_t length,
/*
* Authenticated encryption
*/
int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
int mbedtls_ccm_star_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *iv, size_t iv_len,
const unsigned char *add, size_t add_len,
const unsigned char *input, unsigned char *output,
@ -312,10 +314,23 @@ int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
add, add_len, input, output, tag, tag_len ) );
}
int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *iv, size_t iv_len,
const unsigned char *add, size_t add_len,
const unsigned char *input, unsigned char *output,
unsigned char *tag, size_t tag_len )
{
if( tag_len == 0 )
return( MBEDTLS_ERR_CCM_BAD_INPUT );
return( mbedtls_ccm_star_encrypt_and_tag( ctx, length, iv, iv_len, add,
add_len, input, output, tag, tag_len ) );
}
/*
* Authenticated decryption
*/
int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
int mbedtls_ccm_star_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *iv, size_t iv_len,
const unsigned char *add, size_t add_len,
const unsigned char *input, unsigned char *output,
@ -346,6 +361,18 @@ int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
return( 0 );
}
int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *iv, size_t iv_len,
const unsigned char *add, size_t add_len,
const unsigned char *input, unsigned char *output,
const unsigned char *tag, size_t tag_len )
{
if( tag_len == 0 )
return( MBEDTLS_ERR_CCM_BAD_INPUT );
return( mbedtls_ccm_star_auth_decrypt( ctx, length, iv, iv_len, add,
add_len, input, output, tag, tag_len ) );
}
#endif /* !MBEDTLS_CCM_ALT */
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)

570
thirdparty/mbedtls/library/chacha20.c vendored Normal file
View file

@ -0,0 +1,570 @@
/**
* \file chacha20.c
*
* \brief ChaCha20 cipher.
*
* \author Daniel King <damaki.gh@gmail.com>
*
* Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_CHACHA20_C)
#include "mbedtls/chacha20.h"
#include "mbedtls/platform_util.h"
#include <stddef.h>
#include <string.h>
#if defined(MBEDTLS_SELF_TEST)
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#define mbedtls_printf printf
#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST */
#if !defined(MBEDTLS_CHACHA20_ALT)
#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
!defined(inline) && !defined(__cplusplus)
#define inline __inline
#endif
#define BYTES_TO_U32_LE( data, offset ) \
( (uint32_t) data[offset] \
| (uint32_t) ( (uint32_t) data[( offset ) + 1] << 8 ) \
| (uint32_t) ( (uint32_t) data[( offset ) + 2] << 16 ) \
| (uint32_t) ( (uint32_t) data[( offset ) + 3] << 24 ) \
)
#define ROTL32( value, amount ) \
( (uint32_t) ( value << amount ) | ( value >> ( 32 - amount ) ) )
#define CHACHA20_CTR_INDEX ( 12U )
#define CHACHA20_BLOCK_SIZE_BYTES ( 4U * 16U )
/**
* \brief ChaCha20 quarter round operation.
*
* The quarter round is defined as follows (from RFC 7539):
* 1. a += b; d ^= a; d <<<= 16;
* 2. c += d; b ^= c; b <<<= 12;
* 3. a += b; d ^= a; d <<<= 8;
* 4. c += d; b ^= c; b <<<= 7;
*
* \param state ChaCha20 state to modify.
* \param a The index of 'a' in the state.
* \param b The index of 'b' in the state.
* \param c The index of 'c' in the state.
* \param d The index of 'd' in the state.
*/
static inline void chacha20_quarter_round( uint32_t state[16],
size_t a,
size_t b,
size_t c,
size_t d )
{
/* a += b; d ^= a; d <<<= 16; */
state[a] += state[b];
state[d] ^= state[a];
state[d] = ROTL32( state[d], 16 );
/* c += d; b ^= c; b <<<= 12 */
state[c] += state[d];
state[b] ^= state[c];
state[b] = ROTL32( state[b], 12 );
/* a += b; d ^= a; d <<<= 8; */
state[a] += state[b];
state[d] ^= state[a];
state[d] = ROTL32( state[d], 8 );
/* c += d; b ^= c; b <<<= 7; */
state[c] += state[d];
state[b] ^= state[c];
state[b] = ROTL32( state[b], 7 );
}
/**
* \brief Perform the ChaCha20 inner block operation.
*
* This function performs two rounds: the column round and the
* diagonal round.
*
* \param state The ChaCha20 state to update.
*/
static void chacha20_inner_block( uint32_t state[16] )
{
chacha20_quarter_round( state, 0, 4, 8, 12 );
chacha20_quarter_round( state, 1, 5, 9, 13 );
chacha20_quarter_round( state, 2, 6, 10, 14 );
chacha20_quarter_round( state, 3, 7, 11, 15 );
chacha20_quarter_round( state, 0, 5, 10, 15 );
chacha20_quarter_round( state, 1, 6, 11, 12 );
chacha20_quarter_round( state, 2, 7, 8, 13 );
chacha20_quarter_round( state, 3, 4, 9, 14 );
}
/**
* \brief Generates a keystream block.
*
* \param initial_state The initial ChaCha20 state (key, nonce, counter).
* \param keystream Generated keystream bytes are written to this buffer.
*/
static void chacha20_block( const uint32_t initial_state[16],
unsigned char keystream[64] )
{
uint32_t working_state[16];
size_t i;
memcpy( working_state,
initial_state,
CHACHA20_BLOCK_SIZE_BYTES );
for( i = 0U; i < 10U; i++ )
chacha20_inner_block( working_state );
working_state[ 0] += initial_state[ 0];
working_state[ 1] += initial_state[ 1];
working_state[ 2] += initial_state[ 2];
working_state[ 3] += initial_state[ 3];
working_state[ 4] += initial_state[ 4];
working_state[ 5] += initial_state[ 5];
working_state[ 6] += initial_state[ 6];
working_state[ 7] += initial_state[ 7];
working_state[ 8] += initial_state[ 8];
working_state[ 9] += initial_state[ 9];
working_state[10] += initial_state[10];
working_state[11] += initial_state[11];
working_state[12] += initial_state[12];
working_state[13] += initial_state[13];
working_state[14] += initial_state[14];
working_state[15] += initial_state[15];
for( i = 0U; i < 16; i++ )
{
size_t offset = i * 4U;
keystream[offset ] = (unsigned char)( working_state[i] );
keystream[offset + 1U] = (unsigned char)( working_state[i] >> 8 );
keystream[offset + 2U] = (unsigned char)( working_state[i] >> 16 );
keystream[offset + 3U] = (unsigned char)( working_state[i] >> 24 );
}
mbedtls_platform_zeroize( working_state, sizeof( working_state ) );
}
void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx )
{
if( ctx != NULL )
{
mbedtls_platform_zeroize( ctx->state, sizeof( ctx->state ) );
mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
/* Initially, there's no keystream bytes available */
ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
}
}
void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx )
{
if( ctx != NULL )
{
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_chacha20_context ) );
}
}
int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx,
const unsigned char key[32] )
{
if( ( ctx == NULL ) || ( key == NULL ) )
{
return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
}
/* ChaCha20 constants - the string "expand 32-byte k" */
ctx->state[0] = 0x61707865;
ctx->state[1] = 0x3320646e;
ctx->state[2] = 0x79622d32;
ctx->state[3] = 0x6b206574;
/* Set key */
ctx->state[4] = BYTES_TO_U32_LE( key, 0 );
ctx->state[5] = BYTES_TO_U32_LE( key, 4 );
ctx->state[6] = BYTES_TO_U32_LE( key, 8 );
ctx->state[7] = BYTES_TO_U32_LE( key, 12 );
ctx->state[8] = BYTES_TO_U32_LE( key, 16 );
ctx->state[9] = BYTES_TO_U32_LE( key, 20 );
ctx->state[10] = BYTES_TO_U32_LE( key, 24 );
ctx->state[11] = BYTES_TO_U32_LE( key, 28 );
return( 0 );
}
int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx,
const unsigned char nonce[12],
uint32_t counter )
{
if( ( ctx == NULL ) || ( nonce == NULL ) )
{
return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
}
/* Counter */
ctx->state[12] = counter;
/* Nonce */
ctx->state[13] = BYTES_TO_U32_LE( nonce, 0 );
ctx->state[14] = BYTES_TO_U32_LE( nonce, 4 );
ctx->state[15] = BYTES_TO_U32_LE( nonce, 8 );
mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
/* Initially, there's no keystream bytes available */
ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
return( 0 );
}
int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx,
size_t size,
const unsigned char *input,
unsigned char *output )
{
size_t offset = 0U;
size_t i;
if( ctx == NULL )
{
return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
}
else if( ( size > 0U ) && ( ( input == NULL ) || ( output == NULL ) ) )
{
/* input and output pointers are allowed to be NULL only if size == 0 */
return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
}
/* Use leftover keystream bytes, if available */
while( size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES )
{
output[offset] = input[offset]
^ ctx->keystream8[ctx->keystream_bytes_used];
ctx->keystream_bytes_used++;
offset++;
size--;
}
/* Process full blocks */
while( size >= CHACHA20_BLOCK_SIZE_BYTES )
{
/* Generate new keystream block and increment counter */
chacha20_block( ctx->state, ctx->keystream8 );
ctx->state[CHACHA20_CTR_INDEX]++;
for( i = 0U; i < 64U; i += 8U )
{
output[offset + i ] = input[offset + i ] ^ ctx->keystream8[i ];
output[offset + i+1] = input[offset + i+1] ^ ctx->keystream8[i+1];
output[offset + i+2] = input[offset + i+2] ^ ctx->keystream8[i+2];
output[offset + i+3] = input[offset + i+3] ^ ctx->keystream8[i+3];
output[offset + i+4] = input[offset + i+4] ^ ctx->keystream8[i+4];
output[offset + i+5] = input[offset + i+5] ^ ctx->keystream8[i+5];
output[offset + i+6] = input[offset + i+6] ^ ctx->keystream8[i+6];
output[offset + i+7] = input[offset + i+7] ^ ctx->keystream8[i+7];
}
offset += CHACHA20_BLOCK_SIZE_BYTES;
size -= CHACHA20_BLOCK_SIZE_BYTES;
}
/* Last (partial) block */
if( size > 0U )
{
/* Generate new keystream block and increment counter */
chacha20_block( ctx->state, ctx->keystream8 );
ctx->state[CHACHA20_CTR_INDEX]++;
for( i = 0U; i < size; i++)
{
output[offset + i] = input[offset + i] ^ ctx->keystream8[i];
}
ctx->keystream_bytes_used = size;
}
return( 0 );
}
int mbedtls_chacha20_crypt( const unsigned char key[32],
const unsigned char nonce[12],
uint32_t counter,
size_t data_len,
const unsigned char* input,
unsigned char* output )
{
mbedtls_chacha20_context ctx;
int ret;
mbedtls_chacha20_init( &ctx );
ret = mbedtls_chacha20_setkey( &ctx, key );
if( ret != 0 )
goto cleanup;
ret = mbedtls_chacha20_starts( &ctx, nonce, counter );
if( ret != 0 )
goto cleanup;
ret = mbedtls_chacha20_update( &ctx, data_len, input, output );
cleanup:
mbedtls_chacha20_free( &ctx );
return( ret );
}
#endif /* !MBEDTLS_CHACHA20_ALT */
#if defined(MBEDTLS_SELF_TEST)
static const unsigned char test_keys[2][32] =
{
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
},
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
}
};
static const unsigned char test_nonces[2][12] =
{
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
},
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x02
}
};
static const uint32_t test_counters[2] =
{
0U,
1U
};
static const unsigned char test_input[2][375] =
{
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
},
{
0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d,
0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74,
0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45,
0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e,
0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74,
0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72,
0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66,
0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69,
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61,
0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72,
0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66,
0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46,
0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20,
0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61,
0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73,
0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74,
0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69,
0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49,
0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69,
0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20,
0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72,
0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49,
0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74,
0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e,
0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20,
0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75,
0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20,
0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45,
0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69,
0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20,
0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20,
0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20,
0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63,
0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63,
0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61,
0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e,
0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f,
0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c,
0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61,
0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65,
0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f
}
};
static const unsigned char test_output[2][375] =
{
{
0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86
},
{
0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde,
0x4f, 0x37, 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70,
0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd,
0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec,
0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15,
0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05,
0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f,
0x56, 0xe0, 0x31, 0xca, 0x5e, 0xb6, 0x25, 0x0d,
0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa,
0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e,
0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7,
0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50,
0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05,
0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, 0x41, 0x1c,
0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05,
0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a,
0xd0, 0x0f, 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0,
0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66,
0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4,
0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d,
0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91,
0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28,
0xe6, 0x35, 0x55, 0x3b, 0xa7, 0x6c, 0x5c, 0x87,
0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b,
0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2,
0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f,
0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76,
0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c,
0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, 0xc9, 0x2b,
0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84,
0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd,
0xa2, 0x36, 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b,
0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe,
0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0,
0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80,
0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f,
0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3,
0x6f, 0xf2, 0x16, 0xb9, 0xc1, 0xd3, 0x00, 0x62,
0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91,
0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6,
0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64,
0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85,
0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41,
0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, 0xd1, 0xab,
0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba,
0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd,
0xc4, 0xfd, 0x80, 0x6c, 0x22, 0xf2, 0x21
}
};
static const size_t test_lengths[2] =
{
64U,
375U
};
#define ASSERT( cond, args ) \
do \
{ \
if( ! ( cond ) ) \
{ \
if( verbose != 0 ) \
mbedtls_printf args; \
\
return( -1 ); \
} \
} \
while( 0 )
int mbedtls_chacha20_self_test( int verbose )
{
unsigned char output[381];
unsigned i;
int ret;
for( i = 0U; i < 2U; i++ )
{
if( verbose != 0 )
mbedtls_printf( " ChaCha20 test %u ", i );
ret = mbedtls_chacha20_crypt( test_keys[i],
test_nonces[i],
test_counters[i],
test_lengths[i],
test_input[i],
output );
ASSERT( 0 == ret, ( "error code: %i\n", ret ) );
ASSERT( 0 == memcmp( output, test_output[i], test_lengths[i] ),
( "failed (output)\n" ) );
if( verbose != 0 )
mbedtls_printf( "passed\n" );
}
if( verbose != 0 )
mbedtls_printf( "\n" );
return( 0 );
}
#endif /* MBEDTLS_SELF_TEST */
#endif /* !MBEDTLS_CHACHA20_C */

547
thirdparty/mbedtls/library/chachapoly.c vendored Normal file
View file

@ -0,0 +1,547 @@
/**
* \file chachapoly.c
*
* \brief ChaCha20-Poly1305 AEAD construction based on RFC 7539.
*
* Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_CHACHAPOLY_C)
#include "mbedtls/chachapoly.h"
#include "mbedtls/platform_util.h"
#include <string.h>
#if defined(MBEDTLS_SELF_TEST)
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#define mbedtls_printf printf
#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST */
#if !defined(MBEDTLS_CHACHAPOLY_ALT)
#define CHACHAPOLY_STATE_INIT ( 0 )
#define CHACHAPOLY_STATE_AAD ( 1 )
#define CHACHAPOLY_STATE_CIPHERTEXT ( 2 ) /* Encrypting or decrypting */
#define CHACHAPOLY_STATE_FINISHED ( 3 )
/**
* \brief Adds nul bytes to pad the AAD for Poly1305.
*
* \param ctx The ChaCha20-Poly1305 context.
*/
static int chachapoly_pad_aad( mbedtls_chachapoly_context *ctx )
{
uint32_t partial_block_len = (uint32_t) ( ctx->aad_len % 16U );
unsigned char zeroes[15];
if( partial_block_len == 0U )
return( 0 );
memset( zeroes, 0, sizeof( zeroes ) );
return( mbedtls_poly1305_update( &ctx->poly1305_ctx,
zeroes,
16U - partial_block_len ) );
}
/**
* \brief Adds nul bytes to pad the ciphertext for Poly1305.
*
* \param ctx The ChaCha20-Poly1305 context.
*/
static int chachapoly_pad_ciphertext( mbedtls_chachapoly_context *ctx )
{
uint32_t partial_block_len = (uint32_t) ( ctx->ciphertext_len % 16U );
unsigned char zeroes[15];
if( partial_block_len == 0U )
return( 0 );
memset( zeroes, 0, sizeof( zeroes ) );
return( mbedtls_poly1305_update( &ctx->poly1305_ctx,
zeroes,
16U - partial_block_len ) );
}
void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx )
{
if( ctx != NULL )
{
mbedtls_chacha20_init( &ctx->chacha20_ctx );
mbedtls_poly1305_init( &ctx->poly1305_ctx );
ctx->aad_len = 0U;
ctx->ciphertext_len = 0U;
ctx->state = CHACHAPOLY_STATE_INIT;
ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
}
}
void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx )
{
if( ctx != NULL )
{
mbedtls_chacha20_free( &ctx->chacha20_ctx );
mbedtls_poly1305_free( &ctx->poly1305_ctx );
ctx->aad_len = 0U;
ctx->ciphertext_len = 0U;
ctx->state = CHACHAPOLY_STATE_INIT;
ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
}
}
int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx,
const unsigned char key[32] )
{
int ret;
if( ( ctx == NULL ) || ( key == NULL ) )
{
return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
}
ret = mbedtls_chacha20_setkey( &ctx->chacha20_ctx, key );
return( ret );
}
int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx,
const unsigned char nonce[12],
mbedtls_chachapoly_mode_t mode )
{
int ret;
unsigned char poly1305_key[64];
if( ( ctx == NULL ) || ( nonce == NULL ) )
{
return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
}
/* Set counter = 0, will be update to 1 when generating Poly1305 key */
ret = mbedtls_chacha20_starts( &ctx->chacha20_ctx, nonce, 0U );
if( ret != 0 )
goto cleanup;
/* Generate the Poly1305 key by getting the ChaCha20 keystream output with
* counter = 0. This is the same as encrypting a buffer of zeroes.
* Only the first 256-bits (32 bytes) of the key is used for Poly1305.
* The other 256 bits are discarded.
*/
memset( poly1305_key, 0, sizeof( poly1305_key ) );
ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, sizeof( poly1305_key ),
poly1305_key, poly1305_key );
if( ret != 0 )
goto cleanup;
ret = mbedtls_poly1305_starts( &ctx->poly1305_ctx, poly1305_key );
if( ret == 0 )
{
ctx->aad_len = 0U;
ctx->ciphertext_len = 0U;
ctx->state = CHACHAPOLY_STATE_AAD;
ctx->mode = mode;
}
cleanup:
mbedtls_platform_zeroize( poly1305_key, 64U );
return( ret );
}
int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx,
const unsigned char *aad,
size_t aad_len )
{
if( ctx == NULL )
{
return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
}
else if( ( aad_len > 0U ) && ( aad == NULL ) )
{
/* aad pointer is allowed to be NULL if aad_len == 0 */
return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
}
else if( ctx->state != CHACHAPOLY_STATE_AAD )
{
return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
}
ctx->aad_len += aad_len;
return( mbedtls_poly1305_update( &ctx->poly1305_ctx, aad, aad_len ) );
}
int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx,
size_t len,
const unsigned char *input,
unsigned char *output )
{
int ret;
if( ctx == NULL )
{
return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
}
else if( ( len > 0U ) && ( ( input == NULL ) || ( output == NULL ) ) )
{
/* input and output pointers are allowed to be NULL if len == 0 */
return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
}
else if( ( ctx->state != CHACHAPOLY_STATE_AAD ) &&
( ctx->state != CHACHAPOLY_STATE_CIPHERTEXT ) )
{
return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
}
if( ctx->state == CHACHAPOLY_STATE_AAD )
{
ctx->state = CHACHAPOLY_STATE_CIPHERTEXT;
ret = chachapoly_pad_aad( ctx );
if( ret != 0 )
return( ret );
}
ctx->ciphertext_len += len;
if( ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT )
{
ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output );
if( ret != 0 )
return( ret );
ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, output, len );
if( ret != 0 )
return( ret );
}
else /* DECRYPT */
{
ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, input, len );
if( ret != 0 )
return( ret );
ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output );
if( ret != 0 )
return( ret );
}
return( 0 );
}
int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx,
unsigned char mac[16] )
{
int ret;
unsigned char len_block[16];
if( ( ctx == NULL ) || ( mac == NULL ) )
{
return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
}
else if( ctx->state == CHACHAPOLY_STATE_INIT )
{
return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
}
if( ctx->state == CHACHAPOLY_STATE_AAD )
{
ret = chachapoly_pad_aad( ctx );
if( ret != 0 )
return( ret );
}
else if( ctx->state == CHACHAPOLY_STATE_CIPHERTEXT )
{
ret = chachapoly_pad_ciphertext( ctx );
if( ret != 0 )
return( ret );
}
ctx->state = CHACHAPOLY_STATE_FINISHED;
/* The lengths of the AAD and ciphertext are processed by
* Poly1305 as the final 128-bit block, encoded as little-endian integers.
*/
len_block[ 0] = (unsigned char)( ctx->aad_len );
len_block[ 1] = (unsigned char)( ctx->aad_len >> 8 );
len_block[ 2] = (unsigned char)( ctx->aad_len >> 16 );
len_block[ 3] = (unsigned char)( ctx->aad_len >> 24 );
len_block[ 4] = (unsigned char)( ctx->aad_len >> 32 );
len_block[ 5] = (unsigned char)( ctx->aad_len >> 40 );
len_block[ 6] = (unsigned char)( ctx->aad_len >> 48 );
len_block[ 7] = (unsigned char)( ctx->aad_len >> 56 );
len_block[ 8] = (unsigned char)( ctx->ciphertext_len );
len_block[ 9] = (unsigned char)( ctx->ciphertext_len >> 8 );
len_block[10] = (unsigned char)( ctx->ciphertext_len >> 16 );
len_block[11] = (unsigned char)( ctx->ciphertext_len >> 24 );
len_block[12] = (unsigned char)( ctx->ciphertext_len >> 32 );
len_block[13] = (unsigned char)( ctx->ciphertext_len >> 40 );
len_block[14] = (unsigned char)( ctx->ciphertext_len >> 48 );
len_block[15] = (unsigned char)( ctx->ciphertext_len >> 56 );
ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, len_block, 16U );
if( ret != 0 )
return( ret );
ret = mbedtls_poly1305_finish( &ctx->poly1305_ctx, mac );
return( ret );
}
static int chachapoly_crypt_and_tag( mbedtls_chachapoly_context *ctx,
mbedtls_chachapoly_mode_t mode,
size_t length,
const unsigned char nonce[12],
const unsigned char *aad,
size_t aad_len,
const unsigned char *input,
unsigned char *output,
unsigned char tag[16] )
{
int ret;
ret = mbedtls_chachapoly_starts( ctx, nonce, mode );
if( ret != 0 )
goto cleanup;
ret = mbedtls_chachapoly_update_aad( ctx, aad, aad_len );
if( ret != 0 )
goto cleanup;
ret = mbedtls_chachapoly_update( ctx, length, input, output );
if( ret != 0 )
goto cleanup;
ret = mbedtls_chachapoly_finish( ctx, tag );
cleanup:
return( ret );
}
int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx,
size_t length,
const unsigned char nonce[12],
const unsigned char *aad,
size_t aad_len,
const unsigned char *input,
unsigned char *output,
unsigned char tag[16] )
{
return( chachapoly_crypt_and_tag( ctx, MBEDTLS_CHACHAPOLY_ENCRYPT,
length, nonce, aad, aad_len,
input, output, tag ) );
}
int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx,
size_t length,
const unsigned char nonce[12],
const unsigned char *aad,
size_t aad_len,
const unsigned char tag[16],
const unsigned char *input,
unsigned char *output )
{
int ret;
unsigned char check_tag[16];
size_t i;
int diff;
if( tag == NULL )
return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
if( ( ret = chachapoly_crypt_and_tag( ctx,
MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce,
aad, aad_len, input, output, check_tag ) ) != 0 )
{
return( ret );
}
/* Check tag in "constant-time" */
for( diff = 0, i = 0; i < sizeof( check_tag ); i++ )
diff |= tag[i] ^ check_tag[i];
if( diff != 0 )
{
mbedtls_platform_zeroize( output, length );
return( MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED );
}
return( 0 );
}
#endif /* MBEDTLS_CHACHAPOLY_ALT */
#if defined(MBEDTLS_SELF_TEST)
static const unsigned char test_key[1][32] =
{
{
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f
}
};
static const unsigned char test_nonce[1][12] =
{
{
0x07, 0x00, 0x00, 0x00, /* 32-bit common part */
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 /* 64-bit IV */
}
};
static const unsigned char test_aad[1][12] =
{
{
0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3,
0xc4, 0xc5, 0xc6, 0xc7
}
};
static const size_t test_aad_len[1] =
{
12U
};
static const unsigned char test_input[1][114] =
{
{
0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61,
0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c,
0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73,
0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39,
0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63,
0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66,
0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f,
0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20,
0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20,
0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75,
0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73,
0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f,
0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69,
0x74, 0x2e
}
};
static const unsigned char test_output[1][114] =
{
{
0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb,
0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2,
0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe,
0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6,
0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12,
0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b,
0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29,
0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36,
0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c,
0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58,
0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94,
0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc,
0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d,
0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b,
0x61, 0x16
}
};
static const size_t test_input_len[1] =
{
114U
};
static const unsigned char test_mac[1][16] =
{
{
0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a,
0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91
}
};
#define ASSERT( cond, args ) \
do \
{ \
if( ! ( cond ) ) \
{ \
if( verbose != 0 ) \
mbedtls_printf args; \
\
return( -1 ); \
} \
} \
while( 0 )
int mbedtls_chachapoly_self_test( int verbose )
{
mbedtls_chachapoly_context ctx;
unsigned i;
int ret;
unsigned char output[200];
unsigned char mac[16];
for( i = 0U; i < 1U; i++ )
{
if( verbose != 0 )
mbedtls_printf( " ChaCha20-Poly1305 test %u ", i );
mbedtls_chachapoly_init( &ctx );
ret = mbedtls_chachapoly_setkey( &ctx, test_key[i] );
ASSERT( 0 == ret, ( "setkey() error code: %i\n", ret ) );
ret = mbedtls_chachapoly_encrypt_and_tag( &ctx,
test_input_len[i],
test_nonce[i],
test_aad[i],
test_aad_len[i],
test_input[i],
output,
mac );
ASSERT( 0 == ret, ( "crypt_and_tag() error code: %i\n", ret ) );
ASSERT( 0 == memcmp( output, test_output[i], test_input_len[i] ),
( "failure (wrong output)\n" ) );
ASSERT( 0 == memcmp( mac, test_mac[i], 16U ),
( "failure (wrong MAC)\n" ) );
mbedtls_chachapoly_free( &ctx );
if( verbose != 0 )
mbedtls_printf( "passed\n" );
}
if( verbose != 0 )
mbedtls_printf( "\n" );
return( 0 );
}
#endif /* MBEDTLS_SELF_TEST */
#endif /* MBEDTLS_CHACHAPOLY_C */

View file

@ -38,6 +38,10 @@
#include <stdlib.h>
#include <string.h>
#if defined(MBEDTLS_CHACHAPOLY_C)
#include "mbedtls/chachapoly.h"
#endif
#if defined(MBEDTLS_GCM_C)
#include "mbedtls/gcm.h"
#endif
@ -46,6 +50,10 @@
#include "mbedtls/ccm.h"
#endif
#if defined(MBEDTLS_CHACHA20_C)
#include "mbedtls/chacha20.h"
#endif
#if defined(MBEDTLS_CMAC_C)
#include "mbedtls/cmac.h"
#endif
@ -57,9 +65,25 @@
#define mbedtls_free free
#endif
#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER)
#define MBEDTLS_CIPHER_MODE_STREAM
#endif
#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
/* Compare the contents of two buffers in constant time.
* Returns 0 if the contents are bitwise identical, otherwise returns
* a non-zero value.
* This is currently only used by GCM and ChaCha20+Poly1305.
*/
static int mbedtls_constant_time_memcmp( const void *v1, const void *v2, size_t len )
{
const unsigned char *p1 = (const unsigned char*) v1;
const unsigned char *p2 = (const unsigned char*) v2;
size_t i;
unsigned char diff;
for( diff = 0, i = 0; i < len; i++ )
diff |= p1[i] ^ p2[i];
return (int)diff;
}
#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */
static int supported_init = 0;
@ -191,10 +215,11 @@ int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *k
ctx->operation = operation;
/*
* For CFB and CTR mode always use the encryption key schedule
* For OFB, CFB and CTR mode always use the encryption key schedule
*/
if( MBEDTLS_ENCRYPT == operation ||
MBEDTLS_MODE_CFB == ctx->cipher_info->mode ||
MBEDTLS_MODE_OFB == ctx->cipher_info->mode ||
MBEDTLS_MODE_CTR == ctx->cipher_info->mode )
{
return ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key,
@ -231,6 +256,18 @@ int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx,
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
}
#if defined(MBEDTLS_CHACHA20_C)
if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20 )
{
if ( 0 != mbedtls_chacha20_starts( (mbedtls_chacha20_context*)ctx->cipher_ctx,
iv,
0U ) ) /* Initial counter value */
{
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
}
}
#endif
memcpy( ctx->iv, iv, actual_iv_size );
ctx->iv_size = actual_iv_size;
@ -247,22 +284,45 @@ int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx )
return( 0 );
}
#if defined(MBEDTLS_GCM_C)
#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx,
const unsigned char *ad, size_t ad_len )
{
if( NULL == ctx || NULL == ctx->cipher_info )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
#if defined(MBEDTLS_GCM_C)
if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
{
return mbedtls_gcm_starts( (mbedtls_gcm_context *) ctx->cipher_ctx, ctx->operation,
ctx->iv, ctx->iv_size, ad, ad_len );
}
#endif
#if defined(MBEDTLS_CHACHAPOLY_C)
if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
{
int result;
mbedtls_chachapoly_mode_t mode;
mode = ( ctx->operation == MBEDTLS_ENCRYPT )
? MBEDTLS_CHACHAPOLY_ENCRYPT
: MBEDTLS_CHACHAPOLY_DECRYPT;
result = mbedtls_chachapoly_starts( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
ctx->iv,
mode );
if ( result != 0 )
return( result );
return mbedtls_chachapoly_update_aad( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
ad, ad_len );
}
#endif
return( 0 );
}
#endif /* MBEDTLS_GCM_C */
#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */
int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input,
size_t ilen, unsigned char *output, size_t *olen )
@ -303,6 +363,15 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i
}
#endif
#if defined(MBEDTLS_CHACHAPOLY_C)
if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 )
{
*olen = ilen;
return mbedtls_chachapoly_update( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
ilen, input, output );
}
#endif
if ( 0 == block_size )
{
return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT;
@ -424,6 +493,21 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i
}
#endif /* MBEDTLS_CIPHER_MODE_CFB */
#if defined(MBEDTLS_CIPHER_MODE_OFB)
if( ctx->cipher_info->mode == MBEDTLS_MODE_OFB )
{
if( 0 != ( ret = ctx->cipher_info->base->ofb_func( ctx->cipher_ctx,
ilen, &ctx->unprocessed_len, ctx->iv, input, output ) ) )
{
return( ret );
}
*olen = ilen;
return( 0 );
}
#endif /* MBEDTLS_CIPHER_MODE_OFB */
#if defined(MBEDTLS_CIPHER_MODE_CTR)
if( ctx->cipher_info->mode == MBEDTLS_MODE_CTR )
{
@ -440,6 +524,27 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i
}
#endif /* MBEDTLS_CIPHER_MODE_CTR */
#if defined(MBEDTLS_CIPHER_MODE_XTS)
if( ctx->cipher_info->mode == MBEDTLS_MODE_XTS )
{
if( ctx->unprocessed_len > 0 ) {
/* We can only process an entire data unit at a time. */
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
}
ret = ctx->cipher_info->base->xts_func( ctx->cipher_ctx,
ctx->operation, ilen, ctx->iv, input, output );
if( ret != 0 )
{
return( ret );
}
*olen = ilen;
return( 0 );
}
#endif /* MBEDTLS_CIPHER_MODE_XTS */
#if defined(MBEDTLS_CIPHER_MODE_STREAM)
if( ctx->cipher_info->mode == MBEDTLS_MODE_STREAM )
{
@ -639,13 +744,21 @@ int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx,
*olen = 0;
if( MBEDTLS_MODE_CFB == ctx->cipher_info->mode ||
MBEDTLS_MODE_OFB == ctx->cipher_info->mode ||
MBEDTLS_MODE_CTR == ctx->cipher_info->mode ||
MBEDTLS_MODE_GCM == ctx->cipher_info->mode ||
MBEDTLS_MODE_XTS == ctx->cipher_info->mode ||
MBEDTLS_MODE_STREAM == ctx->cipher_info->mode )
{
return( 0 );
}
if ( ( MBEDTLS_CIPHER_CHACHA20 == ctx->cipher_info->type ) ||
( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) )
{
return( 0 );
}
if( MBEDTLS_MODE_ECB == ctx->cipher_info->mode )
{
if( ctx->unprocessed_len != 0 )
@ -757,7 +870,7 @@ int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_ciph
}
#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
#if defined(MBEDTLS_GCM_C)
#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx,
unsigned char *tag, size_t tag_len )
{
@ -767,8 +880,22 @@ int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx,
if( MBEDTLS_ENCRYPT != ctx->operation )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
#if defined(MBEDTLS_GCM_C)
if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
return mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, tag, tag_len );
#endif
#if defined(MBEDTLS_CHACHAPOLY_C)
if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
{
/* Don't allow truncated MAC for Poly1305 */
if ( tag_len != 16U )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
return mbedtls_chachapoly_finish( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
tag );
}
#endif
return( 0 );
}
@ -776,6 +903,7 @@ int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx,
int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx,
const unsigned char *tag, size_t tag_len )
{
unsigned char check_tag[16];
int ret;
if( NULL == ctx || NULL == ctx->cipher_info ||
@ -784,12 +912,9 @@ int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx,
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
}
#if defined(MBEDTLS_GCM_C)
if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
{
unsigned char check_tag[16];
size_t i;
int diff;
if( tag_len > sizeof( check_tag ) )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
@ -800,18 +925,38 @@ int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx,
}
/* Check the tag in "constant-time" */
for( diff = 0, i = 0; i < tag_len; i++ )
diff |= tag[i] ^ check_tag[i];
if( diff != 0 )
if( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 )
return( MBEDTLS_ERR_CIPHER_AUTH_FAILED );
return( 0 );
}
#endif /* MBEDTLS_GCM_C */
#if defined(MBEDTLS_CHACHAPOLY_C)
if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
{
/* Don't allow truncated MAC for Poly1305 */
if ( tag_len != sizeof( check_tag ) )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
ret = mbedtls_chachapoly_finish( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
check_tag );
if ( ret != 0 )
{
return( ret );
}
/* Check the tag in "constant-time" */
if( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 )
return( MBEDTLS_ERR_CIPHER_AUTH_FAILED );
return( 0 );
}
#endif /* MBEDTLS_CHACHAPOLY_C */
return( 0 );
}
#endif /* MBEDTLS_GCM_C */
#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */
/*
* Packet-oriented wrapper for non-AEAD modes
@ -870,6 +1015,21 @@ int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx,
tag, tag_len ) );
}
#endif /* MBEDTLS_CCM_C */
#if defined(MBEDTLS_CHACHAPOLY_C)
if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
{
/* ChachaPoly has fixed length nonce and MAC (tag) */
if ( ( iv_len != ctx->cipher_info->iv_size ) ||
( tag_len != 16U ) )
{
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
}
*olen = ilen;
return( mbedtls_chachapoly_encrypt_and_tag( ctx->cipher_ctx,
ilen, iv, ad, ad_len, input, output, tag ) );
}
#endif /* MBEDTLS_CHACHAPOLY_C */
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
}
@ -916,6 +1076,28 @@ int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx,
return( ret );
}
#endif /* MBEDTLS_CCM_C */
#if defined(MBEDTLS_CHACHAPOLY_C)
if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
{
int ret;
/* ChachaPoly has fixed length nonce and MAC (tag) */
if ( ( iv_len != ctx->cipher_info->iv_size ) ||
( tag_len != 16U ) )
{
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
}
*olen = ilen;
ret = mbedtls_chachapoly_auth_decrypt( ctx->cipher_ctx, ilen,
iv, ad, ad_len, tag, input, output );
if( ret == MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED )
ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
return( ret );
}
#endif /* MBEDTLS_CHACHAPOLY_C */
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
}

View file

@ -33,6 +33,10 @@
#include "mbedtls/cipher_internal.h"
#if defined(MBEDTLS_CHACHAPOLY_C)
#include "mbedtls/chachapoly.h"
#endif
#if defined(MBEDTLS_AES_C)
#include "mbedtls/aes.h"
#endif
@ -57,6 +61,10 @@
#include "mbedtls/blowfish.h"
#endif
#if defined(MBEDTLS_CHACHA20_C)
#include "mbedtls/chacha20.h"
#endif
#if defined(MBEDTLS_GCM_C)
#include "mbedtls/gcm.h"
#endif
@ -142,6 +150,15 @@ static int aes_crypt_cfb128_wrap( void *ctx, mbedtls_operation_t operation,
}
#endif /* MBEDTLS_CIPHER_MODE_CFB */
#if defined(MBEDTLS_CIPHER_MODE_OFB)
static int aes_crypt_ofb_wrap( void *ctx, size_t length, size_t *iv_off,
unsigned char *iv, const unsigned char *input, unsigned char *output )
{
return mbedtls_aes_crypt_ofb( (mbedtls_aes_context *) ctx, length, iv_off,
iv, input, output );
}
#endif /* MBEDTLS_CIPHER_MODE_OFB */
#if defined(MBEDTLS_CIPHER_MODE_CTR)
static int aes_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off,
unsigned char *nonce_counter, unsigned char *stream_block,
@ -152,6 +169,33 @@ static int aes_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off,
}
#endif /* MBEDTLS_CIPHER_MODE_CTR */
#if defined(MBEDTLS_CIPHER_MODE_XTS)
static int aes_crypt_xts_wrap( void *ctx, mbedtls_operation_t operation,
size_t length,
const unsigned char data_unit[16],
const unsigned char *input,
unsigned char *output )
{
mbedtls_aes_xts_context *xts_ctx = ctx;
int mode;
switch( operation )
{
case MBEDTLS_ENCRYPT:
mode = MBEDTLS_AES_ENCRYPT;
break;
case MBEDTLS_DECRYPT:
mode = MBEDTLS_AES_DECRYPT;
break;
default:
return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
}
return mbedtls_aes_crypt_xts( xts_ctx, mode, length,
data_unit, input, output );
}
#endif /* MBEDTLS_CIPHER_MODE_XTS */
static int aes_setkey_dec_wrap( void *ctx, const unsigned char *key,
unsigned int key_bitlen )
{
@ -191,9 +235,15 @@ static const mbedtls_cipher_base_t aes_info = {
#if defined(MBEDTLS_CIPHER_MODE_CFB)
aes_crypt_cfb128_wrap,
#endif
#if defined(MBEDTLS_CIPHER_MODE_OFB)
aes_crypt_ofb_wrap,
#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR)
aes_crypt_ctr_wrap,
#endif
#if defined(MBEDTLS_CIPHER_MODE_XTS)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_STREAM)
NULL,
#endif
@ -306,6 +356,41 @@ static const mbedtls_cipher_info_t aes_256_cfb128_info = {
};
#endif /* MBEDTLS_CIPHER_MODE_CFB */
#if defined(MBEDTLS_CIPHER_MODE_OFB)
static const mbedtls_cipher_info_t aes_128_ofb_info = {
MBEDTLS_CIPHER_AES_128_OFB,
MBEDTLS_MODE_OFB,
128,
"AES-128-OFB",
16,
0,
16,
&aes_info
};
static const mbedtls_cipher_info_t aes_192_ofb_info = {
MBEDTLS_CIPHER_AES_192_OFB,
MBEDTLS_MODE_OFB,
192,
"AES-192-OFB",
16,
0,
16,
&aes_info
};
static const mbedtls_cipher_info_t aes_256_ofb_info = {
MBEDTLS_CIPHER_AES_256_OFB,
MBEDTLS_MODE_OFB,
256,
"AES-256-OFB",
16,
0,
16,
&aes_info
};
#endif /* MBEDTLS_CIPHER_MODE_OFB */
#if defined(MBEDTLS_CIPHER_MODE_CTR)
static const mbedtls_cipher_info_t aes_128_ctr_info = {
MBEDTLS_CIPHER_AES_128_CTR,
@ -341,6 +426,92 @@ static const mbedtls_cipher_info_t aes_256_ctr_info = {
};
#endif /* MBEDTLS_CIPHER_MODE_CTR */
#if defined(MBEDTLS_CIPHER_MODE_XTS)
static int xts_aes_setkey_enc_wrap( void *ctx, const unsigned char *key,
unsigned int key_bitlen )
{
mbedtls_aes_xts_context *xts_ctx = ctx;
return( mbedtls_aes_xts_setkey_enc( xts_ctx, key, key_bitlen ) );
}
static int xts_aes_setkey_dec_wrap( void *ctx, const unsigned char *key,
unsigned int key_bitlen )
{
mbedtls_aes_xts_context *xts_ctx = ctx;
return( mbedtls_aes_xts_setkey_dec( xts_ctx, key, key_bitlen ) );
}
static void *xts_aes_ctx_alloc( void )
{
mbedtls_aes_xts_context *xts_ctx = mbedtls_calloc( 1, sizeof( *xts_ctx ) );
if( xts_ctx != NULL )
mbedtls_aes_xts_init( xts_ctx );
return( xts_ctx );
}
static void xts_aes_ctx_free( void *ctx )
{
mbedtls_aes_xts_context *xts_ctx = ctx;
if( xts_ctx == NULL )
return;
mbedtls_aes_xts_free( xts_ctx );
mbedtls_free( xts_ctx );
}
static const mbedtls_cipher_base_t xts_aes_info = {
MBEDTLS_CIPHER_ID_AES,
NULL,
#if defined(MBEDTLS_CIPHER_MODE_CBC)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_CFB)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_OFB)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_XTS)
aes_crypt_xts_wrap,
#endif
#if defined(MBEDTLS_CIPHER_MODE_STREAM)
NULL,
#endif
xts_aes_setkey_enc_wrap,
xts_aes_setkey_dec_wrap,
xts_aes_ctx_alloc,
xts_aes_ctx_free
};
static const mbedtls_cipher_info_t aes_128_xts_info = {
MBEDTLS_CIPHER_AES_128_XTS,
MBEDTLS_MODE_XTS,
256,
"AES-128-XTS",
16,
0,
16,
&xts_aes_info
};
static const mbedtls_cipher_info_t aes_256_xts_info = {
MBEDTLS_CIPHER_AES_256_XTS,
MBEDTLS_MODE_XTS,
512,
"AES-256-XTS",
16,
0,
16,
&xts_aes_info
};
#endif /* MBEDTLS_CIPHER_MODE_XTS */
#if defined(MBEDTLS_GCM_C)
static int gcm_aes_setkey_wrap( void *ctx, const unsigned char *key,
unsigned int key_bitlen )
@ -358,9 +529,15 @@ static const mbedtls_cipher_base_t gcm_aes_info = {
#if defined(MBEDTLS_CIPHER_MODE_CFB)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_OFB)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_XTS)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_STREAM)
NULL,
#endif
@ -421,9 +598,15 @@ static const mbedtls_cipher_base_t ccm_aes_info = {
#if defined(MBEDTLS_CIPHER_MODE_CFB)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_OFB)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_XTS)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_STREAM)
NULL,
#endif
@ -548,9 +731,15 @@ static const mbedtls_cipher_base_t camellia_info = {
#if defined(MBEDTLS_CIPHER_MODE_CFB)
camellia_crypt_cfb128_wrap,
#endif
#if defined(MBEDTLS_CIPHER_MODE_OFB)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR)
camellia_crypt_ctr_wrap,
#endif
#if defined(MBEDTLS_CIPHER_MODE_XTS)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_STREAM)
NULL,
#endif
@ -715,9 +904,15 @@ static const mbedtls_cipher_base_t gcm_camellia_info = {
#if defined(MBEDTLS_CIPHER_MODE_CFB)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_OFB)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_XTS)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_STREAM)
NULL,
#endif
@ -778,9 +973,15 @@ static const mbedtls_cipher_base_t ccm_camellia_info = {
#if defined(MBEDTLS_CIPHER_MODE_CFB)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_OFB)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_XTS)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_STREAM)
NULL,
#endif
@ -906,9 +1107,15 @@ static const mbedtls_cipher_base_t aria_info = {
#if defined(MBEDTLS_CIPHER_MODE_CFB)
aria_crypt_cfb128_wrap,
#endif
#if defined(MBEDTLS_CIPHER_MODE_OFB)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR)
aria_crypt_ctr_wrap,
#endif
#if defined(MBEDTLS_CIPHER_MODE_XTS)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_STREAM)
NULL,
#endif
@ -1073,9 +1280,15 @@ static const mbedtls_cipher_base_t gcm_aria_info = {
#if defined(MBEDTLS_CIPHER_MODE_CFB)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_OFB)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_XTS)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_STREAM)
NULL,
#endif
@ -1136,9 +1349,15 @@ static const mbedtls_cipher_base_t ccm_aria_info = {
#if defined(MBEDTLS_CIPHER_MODE_CFB)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_OFB)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_XTS)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_STREAM)
NULL,
#endif
@ -1312,9 +1531,15 @@ static const mbedtls_cipher_base_t des_info = {
#if defined(MBEDTLS_CIPHER_MODE_CFB)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_OFB)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_XTS)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_STREAM)
NULL,
#endif
@ -1357,9 +1582,15 @@ static const mbedtls_cipher_base_t des_ede_info = {
#if defined(MBEDTLS_CIPHER_MODE_CFB)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_OFB)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_XTS)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_STREAM)
NULL,
#endif
@ -1402,9 +1633,15 @@ static const mbedtls_cipher_base_t des_ede3_info = {
#if defined(MBEDTLS_CIPHER_MODE_CFB)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_OFB)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_XTS)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_STREAM)
NULL,
#endif
@ -1511,9 +1748,15 @@ static const mbedtls_cipher_base_t blowfish_info = {
#if defined(MBEDTLS_CIPHER_MODE_CFB)
blowfish_crypt_cfb64_wrap,
#endif
#if defined(MBEDTLS_CIPHER_MODE_OFB)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR)
blowfish_crypt_ctr_wrap,
#endif
#if defined(MBEDTLS_CIPHER_MODE_XTS)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_STREAM)
NULL,
#endif
@ -1621,9 +1864,15 @@ static const mbedtls_cipher_base_t arc4_base_info = {
#if defined(MBEDTLS_CIPHER_MODE_CFB)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_OFB)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_XTS)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_STREAM)
arc4_crypt_stream_wrap,
#endif
@ -1645,6 +1894,162 @@ static const mbedtls_cipher_info_t arc4_128_info = {
};
#endif /* MBEDTLS_ARC4_C */
#if defined(MBEDTLS_CHACHA20_C)
static int chacha20_setkey_wrap( void *ctx, const unsigned char *key,
unsigned int key_bitlen )
{
if( key_bitlen != 256U )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
if ( 0 != mbedtls_chacha20_setkey( (mbedtls_chacha20_context*)ctx, key ) )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
return( 0 );
}
static int chacha20_stream_wrap( void *ctx, size_t length,
const unsigned char *input,
unsigned char *output )
{
int ret;
ret = mbedtls_chacha20_update( ctx, length, input, output );
if( ret == MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
return( ret );
}
static void * chacha20_ctx_alloc( void )
{
mbedtls_chacha20_context *ctx;
ctx = mbedtls_calloc( 1, sizeof( mbedtls_chacha20_context ) );
if( ctx == NULL )
return( NULL );
mbedtls_chacha20_init( ctx );
return( ctx );
}
static void chacha20_ctx_free( void *ctx )
{
mbedtls_chacha20_free( (mbedtls_chacha20_context *) ctx );
mbedtls_free( ctx );
}
static const mbedtls_cipher_base_t chacha20_base_info = {
MBEDTLS_CIPHER_ID_CHACHA20,
NULL,
#if defined(MBEDTLS_CIPHER_MODE_CBC)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_CFB)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_OFB)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_XTS)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_STREAM)
chacha20_stream_wrap,
#endif
chacha20_setkey_wrap,
chacha20_setkey_wrap,
chacha20_ctx_alloc,
chacha20_ctx_free
};
static const mbedtls_cipher_info_t chacha20_info = {
MBEDTLS_CIPHER_CHACHA20,
MBEDTLS_MODE_STREAM,
256,
"CHACHA20",
12,
0,
1,
&chacha20_base_info
};
#endif /* MBEDTLS_CHACHA20_C */
#if defined(MBEDTLS_CHACHAPOLY_C)
static int chachapoly_setkey_wrap( void *ctx,
const unsigned char *key,
unsigned int key_bitlen )
{
if( key_bitlen != 256U )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
if ( 0 != mbedtls_chachapoly_setkey( (mbedtls_chachapoly_context*)ctx, key ) )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
return( 0 );
}
static void * chachapoly_ctx_alloc( void )
{
mbedtls_chachapoly_context *ctx;
ctx = mbedtls_calloc( 1, sizeof( mbedtls_chachapoly_context ) );
if( ctx == NULL )
return( NULL );
mbedtls_chachapoly_init( ctx );
return( ctx );
}
static void chachapoly_ctx_free( void *ctx )
{
mbedtls_chachapoly_free( (mbedtls_chachapoly_context *) ctx );
mbedtls_free( ctx );
}
static const mbedtls_cipher_base_t chachapoly_base_info = {
MBEDTLS_CIPHER_ID_CHACHA20,
NULL,
#if defined(MBEDTLS_CIPHER_MODE_CBC)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_CFB)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_OFB)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_XTS)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_STREAM)
NULL,
#endif
chachapoly_setkey_wrap,
chachapoly_setkey_wrap,
chachapoly_ctx_alloc,
chachapoly_ctx_free
};
static const mbedtls_cipher_info_t chachapoly_info = {
MBEDTLS_CIPHER_CHACHA20_POLY1305,
MBEDTLS_MODE_CHACHAPOLY,
256,
"CHACHA20-POLY1305",
12,
0,
1,
&chachapoly_base_info
};
#endif /* MBEDTLS_CHACHAPOLY_C */
#if defined(MBEDTLS_CIPHER_NULL_CIPHER)
static int null_crypt_stream( void *ctx, size_t length,
const unsigned char *input,
@ -1684,9 +2089,15 @@ static const mbedtls_cipher_base_t null_base_info = {
#if defined(MBEDTLS_CIPHER_MODE_CFB)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_OFB)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_XTS)
NULL,
#endif
#if defined(MBEDTLS_CIPHER_MODE_STREAM)
null_crypt_stream,
#endif
@ -1724,11 +2135,20 @@ const mbedtls_cipher_definition_t mbedtls_cipher_definitions[] =
{ MBEDTLS_CIPHER_AES_192_CFB128, &aes_192_cfb128_info },
{ MBEDTLS_CIPHER_AES_256_CFB128, &aes_256_cfb128_info },
#endif
#if defined(MBEDTLS_CIPHER_MODE_OFB)
{ MBEDTLS_CIPHER_AES_128_OFB, &aes_128_ofb_info },
{ MBEDTLS_CIPHER_AES_192_OFB, &aes_192_ofb_info },
{ MBEDTLS_CIPHER_AES_256_OFB, &aes_256_ofb_info },
#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR)
{ MBEDTLS_CIPHER_AES_128_CTR, &aes_128_ctr_info },
{ MBEDTLS_CIPHER_AES_192_CTR, &aes_192_ctr_info },
{ MBEDTLS_CIPHER_AES_256_CTR, &aes_256_ctr_info },
#endif
#if defined(MBEDTLS_CIPHER_MODE_XTS)
{ MBEDTLS_CIPHER_AES_128_XTS, &aes_128_xts_info },
{ MBEDTLS_CIPHER_AES_256_XTS, &aes_256_xts_info },
#endif
#if defined(MBEDTLS_GCM_C)
{ MBEDTLS_CIPHER_AES_128_GCM, &aes_128_gcm_info },
{ MBEDTLS_CIPHER_AES_192_GCM, &aes_192_gcm_info },
@ -1831,6 +2251,14 @@ const mbedtls_cipher_definition_t mbedtls_cipher_definitions[] =
#endif
#endif /* MBEDTLS_DES_C */
#if defined(MBEDTLS_CHACHA20_C)
{ MBEDTLS_CIPHER_CHACHA20, &chacha20_info },
#endif
#if defined(MBEDTLS_CHACHAPOLY_C)
{ MBEDTLS_CIPHER_CHACHA20_POLY1305, &chachapoly_info },
#endif
#if defined(MBEDTLS_CIPHER_NULL_CIPHER)
{ MBEDTLS_CIPHER_NULL, &null_cipher_info },
#endif /* MBEDTLS_CIPHER_NULL_CIPHER */

View file

@ -828,6 +828,7 @@ static int cmac_test_subkeys( int verbose,
mbedtls_cipher_free( &ctx );
}
ret = 0;
goto exit;
cleanup:
@ -883,6 +884,7 @@ static int cmac_test_wth_cipher( int verbose,
if( verbose != 0 )
mbedtls_printf( "passed\n" );
}
ret = 0;
exit:
return( ret );

View file

@ -19,19 +19,25 @@
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#if defined(__linux__)
/* Ensure that syscall() is available even when compiling with -std=c99 */
#define _GNU_SOURCE
#endif
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include <string.h>
#if defined(MBEDTLS_ENTROPY_C)
#include "mbedtls/entropy.h"
#include "mbedtls/entropy_poll.h"
#if defined(MBEDTLS_TIMING_C)
#include <string.h>
#include "mbedtls/timing.h"
#endif
#if defined(MBEDTLS_HAVEGE_C)
@ -44,7 +50,8 @@
#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY)
#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \
!defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__)
!defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \
!defined(__HAIKU__)
#error "Platform entropy sources only work on Unix and Windows, see MBEDTLS_NO_PLATFORM_ENTROPY in config.h"
#endif

View file

@ -0,0 +1,275 @@
/*
* Platform-specific and custom entropy polling functions
*
* Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#if defined(__linux__)
/* Ensure that syscall() is available even when compiling with -std=c99 */
#define _GNU_SOURCE
#endif
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include <string.h>
#if defined(MBEDTLS_ENTROPY_C)
#include "mbedtls/entropy.h"
#include "mbedtls/entropy_poll.h"
#if defined(MBEDTLS_TIMING_C)
#include "mbedtls/timing.h"
#endif
#if defined(MBEDTLS_HAVEGE_C)
#include "mbedtls/havege.h"
#endif
#if defined(MBEDTLS_ENTROPY_NV_SEED)
#include "mbedtls/platform.h"
#endif
#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY)
#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \
!defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \
!defined(__HAIKU__)
#error "Platform entropy sources only work on Unix and Windows, see MBEDTLS_NO_PLATFORM_ENTROPY in config.h"
#endif
#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
#if !defined(_WIN32_WINNT)
#define _WIN32_WINNT 0x0400
#endif
#include <windows.h>
#include <wincrypt.h>
int mbedtls_platform_entropy_poll( void *data, unsigned char *output, size_t len,
size_t *olen )
{
HCRYPTPROV provider;
((void) data);
*olen = 0;
if( CryptAcquireContext( &provider, NULL, NULL,
PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) == FALSE )
{
return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
}
if( CryptGenRandom( provider, (DWORD) len, output ) == FALSE )
{
CryptReleaseContext( provider, 0 );
return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
}
CryptReleaseContext( provider, 0 );
*olen = len;
return( 0 );
}
#else /* _WIN32 && !EFIX64 && !EFI32 */
/*
* Test for Linux getrandom() support.
* Since there is no wrapper in the libc yet, use the generic syscall wrapper
* available in GNU libc and compatible libc's (eg uClibc).
*/
#if defined(__linux__) && defined(__GLIBC__)
#include <unistd.h>
#include <sys/syscall.h>
#if defined(SYS_getrandom)
#define HAVE_GETRANDOM
static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags )
{
/* MemSan cannot understand that the syscall writes to the buffer */
#if defined(__has_feature)
#if __has_feature(memory_sanitizer)
memset( buf, 0, buflen );
#endif
#endif
return( syscall( SYS_getrandom, buf, buflen, flags ) );
}
#include <sys/utsname.h>
/* Check if version is at least 3.17.0 */
static int check_version_3_17_plus( void )
{
int minor;
struct utsname un;
const char *ver;
/* Get version information */
uname(&un);
ver = un.release;
/* Check major version; assume a single digit */
if( ver[0] < '3' || ver[0] > '9' || ver [1] != '.' )
return( -1 );
if( ver[0] - '0' > 3 )
return( 0 );
/* Ok, so now we know major == 3, check minor.
* Assume 1 or 2 digits. */
if( ver[2] < '0' || ver[2] > '9' )
return( -1 );
minor = ver[2] - '0';
if( ver[3] >= '0' && ver[3] <= '9' )
minor = 10 * minor + ver[3] - '0';
else if( ver [3] != '.' )
return( -1 );
if( minor < 17 )
return( -1 );
return( 0 );
}
static int has_getrandom = -1;
#endif /* SYS_getrandom */
#endif /* __linux__ */
#include <stdio.h>
int mbedtls_platform_entropy_poll( void *data,
unsigned char *output, size_t len, size_t *olen )
{
FILE *file;
size_t read_len;
((void) data);
#if defined(HAVE_GETRANDOM)
if( has_getrandom == -1 )
has_getrandom = ( check_version_3_17_plus() == 0 );
if( has_getrandom )
{
int ret;
if( ( ret = getrandom_wrapper( output, len, 0 ) ) < 0 )
return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
*olen = ret;
return( 0 );
}
#endif /* HAVE_GETRANDOM */
*olen = 0;
file = fopen( "/dev/urandom", "rb" );
if( file == NULL )
return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
read_len = fread( output, 1, len, file );
if( read_len != len )
{
fclose( file );
return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
}
fclose( file );
*olen = len;
return( 0 );
}
#endif /* _WIN32 && !EFIX64 && !EFI32 */
#endif /* !MBEDTLS_NO_PLATFORM_ENTROPY */
#if defined(MBEDTLS_TEST_NULL_ENTROPY)
int mbedtls_null_entropy_poll( void *data,
unsigned char *output, size_t len, size_t *olen )
{
((void) data);
((void) output);
*olen = 0;
if( len < sizeof(unsigned char) )
return( 0 );
*olen = sizeof(unsigned char);
return( 0 );
}
#endif
#if defined(MBEDTLS_TIMING_C)
int mbedtls_hardclock_poll( void *data,
unsigned char *output, size_t len, size_t *olen )
{
unsigned long timer = mbedtls_timing_hardclock();
((void) data);
*olen = 0;
if( len < sizeof(unsigned long) )
return( 0 );
memcpy( output, &timer, sizeof(unsigned long) );
*olen = sizeof(unsigned long);
return( 0 );
}
#endif /* MBEDTLS_TIMING_C */
#if defined(MBEDTLS_HAVEGE_C)
int mbedtls_havege_poll( void *data,
unsigned char *output, size_t len, size_t *olen )
{
mbedtls_havege_state *hs = (mbedtls_havege_state *) data;
*olen = 0;
if( mbedtls_havege_random( hs, output, len ) != 0 )
return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
*olen = len;
return( 0 );
}
#endif /* MBEDTLS_HAVEGE_C */
#if defined(MBEDTLS_ENTROPY_NV_SEED)
int mbedtls_nv_seed_poll( void *data,
unsigned char *output, size_t len, size_t *olen )
{
unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
size_t use_len = MBEDTLS_ENTROPY_BLOCK_SIZE;
((void) data);
memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
if( mbedtls_nv_seed_read( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) < 0 )
return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
if( len < use_len )
use_len = len;
memcpy( output, buf, use_len );
*olen = use_len;
return( 0 );
}
#endif /* MBEDTLS_ENTROPY_NV_SEED */
#endif /* MBEDTLS_ENTROPY_C */

View file

@ -73,6 +73,14 @@
#include "mbedtls/ccm.h"
#endif
#if defined(MBEDTLS_CHACHA20_C)
#include "mbedtls/chacha20.h"
#endif
#if defined(MBEDTLS_CHACHAPOLY_C)
#include "mbedtls/chachapoly.h"
#endif
#if defined(MBEDTLS_CIPHER_C)
#include "mbedtls/cipher.h"
#endif
@ -105,6 +113,10 @@
#include "mbedtls/gcm.h"
#endif
#if defined(MBEDTLS_HKDF_C)
#include "mbedtls/hkdf.h"
#endif
#if defined(MBEDTLS_HMAC_DRBG_C)
#include "mbedtls/hmac_drbg.h"
#endif
@ -153,6 +165,10 @@
#include "mbedtls/pkcs5.h"
#endif
#if defined(MBEDTLS_POLY1305_C)
#include "mbedtls/poly1305.h"
#endif
#if defined(MBEDTLS_RIPEMD160_C)
#include "mbedtls/ripemd160.h"
#endif
@ -497,6 +513,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
mbedtls_snprintf( buf, buflen, "SSL - Couldn't set the hash for verifying CertificateVerify" );
if( use_ret == -(MBEDTLS_ERR_SSL_CONTINUE_PROCESSING) )
mbedtls_snprintf( buf, buflen, "SSL - Internal-only message signaling that further message-processing should be done" );
if( use_ret == -(MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) )
mbedtls_snprintf( buf, buflen, "SSL - The asynchronous operation is not completed yet" );
#endif /* MBEDTLS_SSL_TLS_C */
#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C)
@ -670,6 +688,22 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
mbedtls_snprintf( buf, buflen, "CCM - CCM hardware accelerator failed" );
#endif /* MBEDTLS_CCM_C */
#if defined(MBEDTLS_CHACHA20_C)
if( use_ret == -(MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA) )
mbedtls_snprintf( buf, buflen, "CHACHA20 - Invalid input parameter(s)" );
if( use_ret == -(MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE) )
mbedtls_snprintf( buf, buflen, "CHACHA20 - Feature not available. For example, s part of the API is not implemented" );
if( use_ret == -(MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED) )
mbedtls_snprintf( buf, buflen, "CHACHA20 - Chacha20 hardware accelerator failed" );
#endif /* MBEDTLS_CHACHA20_C */
#if defined(MBEDTLS_CHACHAPOLY_C)
if( use_ret == -(MBEDTLS_ERR_CHACHAPOLY_BAD_STATE) )
mbedtls_snprintf( buf, buflen, "CHACHAPOLY - The requested operation is not permitted in the current state" );
if( use_ret == -(MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED) )
mbedtls_snprintf( buf, buflen, "CHACHAPOLY - Authenticated decryption failed: data was not authentic" );
#endif /* MBEDTLS_CHACHAPOLY_C */
#if defined(MBEDTLS_CMAC_C)
if( use_ret == -(MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED) )
mbedtls_snprintf( buf, buflen, "CMAC - CMAC hardware accelerator failed" );
@ -715,6 +749,11 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
mbedtls_snprintf( buf, buflen, "GCM - Bad input parameters to function" );
#endif /* MBEDTLS_GCM_C */
#if defined(MBEDTLS_HKDF_C)
if( use_ret == -(MBEDTLS_ERR_HKDF_BAD_INPUT_DATA) )
mbedtls_snprintf( buf, buflen, "HKDF - Bad input parameters to function" );
#endif /* MBEDTLS_HKDF_C */
#if defined(MBEDTLS_HMAC_DRBG_C)
if( use_ret == -(MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG) )
mbedtls_snprintf( buf, buflen, "HMAC_DRBG - Too many random requested in single call" );
@ -782,6 +821,15 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
mbedtls_snprintf( buf, buflen, "PADLOCK - Input data should be aligned" );
#endif /* MBEDTLS_PADLOCK_C */
#if defined(MBEDTLS_POLY1305_C)
if( use_ret == -(MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA) )
mbedtls_snprintf( buf, buflen, "POLY1305 - Invalid input parameter(s)" );
if( use_ret == -(MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE) )
mbedtls_snprintf( buf, buflen, "POLY1305 - Feature not available. For example, s part of the API is not implemented" );
if( use_ret == -(MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED) )
mbedtls_snprintf( buf, buflen, "POLY1305 - Poly1305 hardware accelerator failed" );
#endif /* MBEDTLS_POLY1305_C */
#if defined(MBEDTLS_RIPEMD160_C)
if( use_ret == -(MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED) )
mbedtls_snprintf( buf, buflen, "RIPEMD160 - RIPEMD160 hardware accelerator failed" );

192
thirdparty/mbedtls/library/hkdf.c vendored Normal file
View file

@ -0,0 +1,192 @@
/*
* HKDF implementation -- RFC 5869
*
* Copyright (C) 2016-2018, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_HKDF_C)
#include <string.h>
#include "mbedtls/hkdf.h"
#include "mbedtls/platform_util.h"
int mbedtls_hkdf( const mbedtls_md_info_t *md, const unsigned char *salt,
size_t salt_len, const unsigned char *ikm, size_t ikm_len,
const unsigned char *info, size_t info_len,
unsigned char *okm, size_t okm_len )
{
int ret;
unsigned char prk[MBEDTLS_MD_MAX_SIZE];
ret = mbedtls_hkdf_extract( md, salt, salt_len, ikm, ikm_len, prk );
if( ret == 0 )
{
ret = mbedtls_hkdf_expand( md, prk, mbedtls_md_get_size( md ),
info, info_len, okm, okm_len );
}
mbedtls_platform_zeroize( prk, sizeof( prk ) );
return( ret );
}
int mbedtls_hkdf_extract( const mbedtls_md_info_t *md,
const unsigned char *salt, size_t salt_len,
const unsigned char *ikm, size_t ikm_len,
unsigned char *prk )
{
unsigned char null_salt[MBEDTLS_MD_MAX_SIZE] = { '\0' };
if( salt == NULL )
{
size_t hash_len;
if( salt_len != 0 )
{
return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA;
}
hash_len = mbedtls_md_get_size( md );
if( hash_len == 0 )
{
return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA;
}
salt = null_salt;
salt_len = hash_len;
}
return( mbedtls_md_hmac( md, salt, salt_len, ikm, ikm_len, prk ) );
}
int mbedtls_hkdf_expand( const mbedtls_md_info_t *md, const unsigned char *prk,
size_t prk_len, const unsigned char *info,
size_t info_len, unsigned char *okm, size_t okm_len )
{
size_t hash_len;
size_t where = 0;
size_t n;
size_t t_len = 0;
size_t i;
int ret = 0;
mbedtls_md_context_t ctx;
unsigned char t[MBEDTLS_MD_MAX_SIZE];
if( okm == NULL )
{
return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA );
}
hash_len = mbedtls_md_get_size( md );
if( prk_len < hash_len || hash_len == 0 )
{
return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA );
}
if( info == NULL )
{
info = (const unsigned char *) "";
info_len = 0;
}
n = okm_len / hash_len;
if( (okm_len % hash_len) != 0 )
{
n++;
}
/*
* Per RFC 5869 Section 2.3, okm_len must not exceed
* 255 times the hash length
*/
if( n > 255 )
{
return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA );
}
mbedtls_md_init( &ctx );
if( (ret = mbedtls_md_setup( &ctx, md, 1) ) != 0 )
{
goto exit;
}
/*
* Compute T = T(1) | T(2) | T(3) | ... | T(N)
* Where T(N) is defined in RFC 5869 Section 2.3
*/
for( i = 1; i <= n; i++ )
{
size_t num_to_copy;
unsigned char c = i & 0xff;
ret = mbedtls_md_hmac_starts( &ctx, prk, prk_len );
if( ret != 0 )
{
goto exit;
}
ret = mbedtls_md_hmac_update( &ctx, t, t_len );
if( ret != 0 )
{
goto exit;
}
ret = mbedtls_md_hmac_update( &ctx, info, info_len );
if( ret != 0 )
{
goto exit;
}
/* The constant concatenated to the end of each T(n) is a single octet.
* */
ret = mbedtls_md_hmac_update( &ctx, &c, 1 );
if( ret != 0 )
{
goto exit;
}
ret = mbedtls_md_hmac_finish( &ctx, t );
if( ret != 0 )
{
goto exit;
}
num_to_copy = i != n ? hash_len : okm_len - where;
memcpy( okm + where, t, num_to_copy );
where += hash_len;
t_len = hash_len;
}
exit:
mbedtls_md_free( &ctx );
mbedtls_platform_zeroize( t, sizeof( t ) );
return( ret );
}
#endif /* MBEDTLS_HKDF_C */

View file

@ -309,14 +309,6 @@ void mbedtls_md5_update( mbedtls_md5_context *ctx,
}
#endif
static const unsigned char md5_padding[64] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
* MD5 final digest
*/
@ -324,26 +316,48 @@ int mbedtls_md5_finish_ret( mbedtls_md5_context *ctx,
unsigned char output[16] )
{
int ret;
uint32_t last, padn;
uint32_t used;
uint32_t high, low;
unsigned char msglen[8];
/*
* Add padding: 0x80 then 0x00 until 8 bytes remain for the length
*/
used = ctx->total[0] & 0x3F;
ctx->buffer[used++] = 0x80;
if( used <= 56 )
{
/* Enough room for padding + length in current block */
memset( ctx->buffer + used, 0, 56 - used );
}
else
{
/* We'll need an extra block */
memset( ctx->buffer + used, 0, 64 - used );
if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 )
return( ret );
memset( ctx->buffer, 0, 56 );
}
/*
* Add message length
*/
high = ( ctx->total[0] >> 29 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
PUT_UINT32_LE( low, msglen, 0 );
PUT_UINT32_LE( high, msglen, 4 );
PUT_UINT32_LE( low, ctx->buffer, 56 );
PUT_UINT32_LE( high, ctx->buffer, 60 );
last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
if( ( ret = mbedtls_md5_update_ret( ctx, md5_padding, padn ) ) != 0 )
return( ret );
if( ( ret = mbedtls_md5_update_ret( ctx, msglen, 8 ) ) != 0 )
return( ret );
if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 )
return( ret );
/*
* Output final state
*/
PUT_UINT32_LE( ctx->state[0], output, 0 );
PUT_UINT32_LE( ctx->state[1], output, 4 );
PUT_UINT32_LE( ctx->state[2], output, 8 );

View file

@ -518,7 +518,9 @@ void mbedtls_memory_buffer_alloc_status( void )
heap.alloc_count, heap.free_count );
if( heap.first->next == NULL )
{
mbedtls_fprintf( stderr, "All memory de-allocated in stack buffer\n" );
}
else
{
mbedtls_fprintf( stderr, "Memory currently allocated:\n" );

View file

@ -19,6 +19,11 @@
* This file is part of mbed TLS (https://tls.mbed.org)
*/
/* Enable definition of getaddrinfo() even when compiling with -std=c99. Must
* be set before config.h, which pulls in glibc's features.h indirectly.
* Harmless on other platforms. */
#define _POSIX_C_SOURCE 200112L
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
@ -28,7 +33,8 @@
#if defined(MBEDTLS_NET_C)
#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \
!defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__)
!defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \
!defined(__HAIKU__)
#error "This module only works on Unix and Windows, see MBEDTLS_NET_C in config.h"
#endif
@ -47,13 +53,11 @@
#define IS_EINTR( ret ) ( ( ret ) == WSAEINTR )
/* GODOT ADDITION */
#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0501)
#undef _WIN32_WINNT
/* Enables getaddrinfo() & Co */
#define _WIN32_WINNT 0x0501
#endif
/* END GODOT ADDITION */
#include <ws2tcpip.h>

755
thirdparty/mbedtls/library/nist_kw.c vendored Normal file
View file

@ -0,0 +1,755 @@
/*
* Implementation of NIST SP 800-38F key wrapping, supporting KW and KWP modes
* only
*
* Copyright (C) 2018, Arm Limited (or its affiliates), All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.
*
* This file is part of Mbed TLS (https://tls.mbed.org)
*/
/*
* Definition of Key Wrapping:
* https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf
* RFC 3394 "Advanced Encryption Standard (AES) Key Wrap Algorithm"
* RFC 5649 "Advanced Encryption Standard (AES) Key Wrap with Padding Algorithm"
*
* Note: RFC 3394 defines different methodology for intermediate operations for
* the wrapping and unwrapping operation than the definition in NIST SP 800-38F.
*/
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_NIST_KW_C)
#include "mbedtls/nist_kw.h"
#include "mbedtls/platform_util.h"
#include <stdint.h>
#include <string.h>
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#define mbedtls_printf printf
#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
#if !defined(MBEDTLS_NIST_KW_ALT)
#define KW_SEMIBLOCK_LENGTH 8
#define MIN_SEMIBLOCKS_COUNT 3
/* constant-time buffer comparison */
static inline unsigned char mbedtls_nist_kw_safer_memcmp( const void *a, const void *b, size_t n )
{
size_t i;
volatile const unsigned char *A = (volatile const unsigned char *) a;
volatile const unsigned char *B = (volatile const unsigned char *) b;
volatile unsigned char diff = 0;
for( i = 0; i < n; i++ )
{
/* Read volatile data in order before computing diff.
* This avoids IAR compiler warning:
* 'the order of volatile accesses is undefined ..' */
unsigned char x = A[i], y = B[i];
diff |= x ^ y;
}
return( diff );
}
/*! The 64-bit default integrity check value (ICV) for KW mode. */
static const unsigned char NIST_KW_ICV1[] = {0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6};
/*! The 32-bit default integrity check value (ICV) for KWP mode. */
static const unsigned char NIST_KW_ICV2[] = {0xA6, 0x59, 0x59, 0xA6};
#ifndef GET_UINT32_BE
#define GET_UINT32_BE(n,b,i) \
do { \
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \
| ( (uint32_t) (b)[(i) + 1] << 16 ) \
| ( (uint32_t) (b)[(i) + 2] << 8 ) \
| ( (uint32_t) (b)[(i) + 3] ); \
} while( 0 )
#endif
#ifndef PUT_UINT32_BE
#define PUT_UINT32_BE(n,b,i) \
do { \
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 3] = (unsigned char) ( (n) ); \
} while( 0 )
#endif
/*
* Initialize context
*/
void mbedtls_nist_kw_init( mbedtls_nist_kw_context *ctx )
{
memset( ctx, 0, sizeof( mbedtls_nist_kw_context ) );
}
int mbedtls_nist_kw_setkey( mbedtls_nist_kw_context *ctx,
mbedtls_cipher_id_t cipher,
const unsigned char *key,
unsigned int keybits,
const int is_wrap )
{
int ret;
const mbedtls_cipher_info_t *cipher_info;
cipher_info = mbedtls_cipher_info_from_values( cipher,
keybits,
MBEDTLS_MODE_ECB );
if( cipher_info == NULL )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
if( cipher_info->block_size != 16 )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
/*
* SP 800-38F currently defines AES cipher as the only block cipher allowed:
* "For KW and KWP, the underlying block cipher shall be approved, and the
* block size shall be 128 bits. Currently, the AES block cipher, with key
* lengths of 128, 192, or 256 bits, is the only block cipher that fits
* this profile."
* Currently we don't support other 128 bit block ciphers for key wrapping,
* such as Camellia and Aria.
*/
if( cipher != MBEDTLS_CIPHER_ID_AES )
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
mbedtls_cipher_free( &ctx->cipher_ctx );
if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 )
return( ret );
if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits,
is_wrap ? MBEDTLS_ENCRYPT :
MBEDTLS_DECRYPT )
) != 0 )
{
return( ret );
}
return( 0 );
}
/*
* Free context
*/
void mbedtls_nist_kw_free( mbedtls_nist_kw_context *ctx )
{
mbedtls_cipher_free( &ctx->cipher_ctx );
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_nist_kw_context ) );
}
/*
* Helper function for Xoring the uint64_t "t" with the encrypted A.
* Defined in NIST SP 800-38F section 6.1
*/
static void calc_a_xor_t( unsigned char A[KW_SEMIBLOCK_LENGTH], uint64_t t )
{
size_t i = 0;
for( i = 0; i < sizeof( t ); i++ )
{
A[i] ^= ( t >> ( ( sizeof( t ) - 1 - i ) * 8 ) ) & 0xff;
}
}
/*
* KW-AE as defined in SP 800-38F section 6.2
* KWP-AE as defined in SP 800-38F section 6.3
*/
int mbedtls_nist_kw_wrap( mbedtls_nist_kw_context *ctx,
mbedtls_nist_kw_mode_t mode,
const unsigned char *input, size_t in_len,
unsigned char *output, size_t *out_len, size_t out_size )
{
int ret = 0;
size_t semiblocks = 0;
size_t s;
size_t olen, padlen = 0;
uint64_t t = 0;
unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH;
unsigned char *A = output;
*out_len = 0;
/*
* Generate the String to work on
*/
if( mode == MBEDTLS_KW_MODE_KW )
{
if( out_size < in_len + KW_SEMIBLOCK_LENGTH )
{
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
}
/*
* According to SP 800-38F Table 1, the plaintext length for KW
* must be between 2 to 2^54-1 semiblocks inclusive.
*/
if( in_len < 16 ||
#if SIZE_MAX > 0x1FFFFFFFFFFFFF8
in_len > 0x1FFFFFFFFFFFFF8 ||
#endif
in_len % KW_SEMIBLOCK_LENGTH != 0 )
{
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
}
memcpy( output, NIST_KW_ICV1, KW_SEMIBLOCK_LENGTH );
memmove( output + KW_SEMIBLOCK_LENGTH, input, in_len );
}
else
{
if( in_len % 8 != 0 )
{
padlen = ( 8 - ( in_len % 8 ) );
}
if( out_size < in_len + KW_SEMIBLOCK_LENGTH + padlen )
{
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
}
/*
* According to SP 800-38F Table 1, the plaintext length for KWP
* must be between 1 and 2^32-1 octets inclusive.
*/
if( in_len < 1
#if SIZE_MAX > 0xFFFFFFFF
|| in_len > 0xFFFFFFFF
#endif
)
{
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
}
memcpy( output, NIST_KW_ICV2, KW_SEMIBLOCK_LENGTH / 2 );
PUT_UINT32_BE( ( in_len & 0xffffffff ), output,
KW_SEMIBLOCK_LENGTH / 2 );
memcpy( output + KW_SEMIBLOCK_LENGTH, input, in_len );
memset( output + KW_SEMIBLOCK_LENGTH + in_len, 0, padlen );
}
semiblocks = ( ( in_len + padlen ) / KW_SEMIBLOCK_LENGTH ) + 1;
s = 6 * ( semiblocks - 1 );
if( mode == MBEDTLS_KW_MODE_KWP
&& in_len <= KW_SEMIBLOCK_LENGTH )
{
memcpy( inbuff, output, 16 );
ret = mbedtls_cipher_update( &ctx->cipher_ctx,
inbuff, 16, output, &olen );
if( ret != 0 )
goto cleanup;
}
else
{
/*
* Do the wrapping function W, as defined in RFC 3394 section 2.2.1
*/
if( semiblocks < MIN_SEMIBLOCKS_COUNT )
{
ret = MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
goto cleanup;
}
/* Calculate intermediate values */
for( t = 1; t <= s; t++ )
{
memcpy( inbuff, A, KW_SEMIBLOCK_LENGTH );
memcpy( inbuff + KW_SEMIBLOCK_LENGTH, R2, KW_SEMIBLOCK_LENGTH );
ret = mbedtls_cipher_update( &ctx->cipher_ctx,
inbuff, 16, outbuff, &olen );
if( ret != 0 )
goto cleanup;
memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH );
calc_a_xor_t( A, t );
memcpy( R2, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH );
R2 += KW_SEMIBLOCK_LENGTH;
if( R2 >= output + ( semiblocks * KW_SEMIBLOCK_LENGTH ) )
R2 = output + KW_SEMIBLOCK_LENGTH;
}
}
*out_len = semiblocks * KW_SEMIBLOCK_LENGTH;
cleanup:
if( ret != 0)
{
memset( output, 0, semiblocks * KW_SEMIBLOCK_LENGTH );
}
mbedtls_platform_zeroize( inbuff, KW_SEMIBLOCK_LENGTH * 2 );
mbedtls_platform_zeroize( outbuff, KW_SEMIBLOCK_LENGTH * 2 );
mbedtls_cipher_finish( &ctx->cipher_ctx, NULL, &olen );
return( ret );
}
/*
* W-1 function as defined in RFC 3394 section 2.2.2
* This function assumes the following:
* 1. Output buffer is at least of size ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH.
* 2. The input buffer is of size semiblocks * KW_SEMIBLOCK_LENGTH.
* 3. Minimal number of semiblocks is 3.
* 4. A is a buffer to hold the first semiblock of the input buffer.
*/
static int unwrap( mbedtls_nist_kw_context *ctx,
const unsigned char *input, size_t semiblocks,
unsigned char A[KW_SEMIBLOCK_LENGTH],
unsigned char *output, size_t* out_len )
{
int ret = 0;
const size_t s = 6 * ( semiblocks - 1 );
size_t olen;
uint64_t t = 0;
unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
unsigned char *R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH;
*out_len = 0;
if( semiblocks < MIN_SEMIBLOCKS_COUNT )
{
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
}
memcpy( A, input, KW_SEMIBLOCK_LENGTH );
memmove( output, input + KW_SEMIBLOCK_LENGTH, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH );
/* Calculate intermediate values */
for( t = s; t >= 1; t-- )
{
calc_a_xor_t( A, t );
memcpy( inbuff, A, KW_SEMIBLOCK_LENGTH );
memcpy( inbuff + KW_SEMIBLOCK_LENGTH, R, KW_SEMIBLOCK_LENGTH );
ret = mbedtls_cipher_update( &ctx->cipher_ctx,
inbuff, 16, outbuff, &olen );
if( ret != 0 )
goto cleanup;
memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH );
/* Set R as LSB64 of outbuff */
memcpy( R, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH );
if( R == output )
R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH;
else
R -= KW_SEMIBLOCK_LENGTH;
}
*out_len = ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH;
cleanup:
if( ret != 0)
memset( output, 0, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH );
mbedtls_platform_zeroize( inbuff, sizeof( inbuff ) );
mbedtls_platform_zeroize( outbuff, sizeof( outbuff ) );
return( ret );
}
/*
* KW-AD as defined in SP 800-38F section 6.2
* KWP-AD as defined in SP 800-38F section 6.3
*/
int mbedtls_nist_kw_unwrap( mbedtls_nist_kw_context *ctx,
mbedtls_nist_kw_mode_t mode,
const unsigned char *input, size_t in_len,
unsigned char *output, size_t *out_len, size_t out_size )
{
int ret = 0;
size_t i, olen;
unsigned char A[KW_SEMIBLOCK_LENGTH];
unsigned char diff, bad_padding = 0;
*out_len = 0;
if( out_size < in_len - KW_SEMIBLOCK_LENGTH )
{
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
}
if( mode == MBEDTLS_KW_MODE_KW )
{
/*
* According to SP 800-38F Table 1, the ciphertext length for KW
* must be between 3 to 2^54 semiblocks inclusive.
*/
if( in_len < 24 ||
#if SIZE_MAX > 0x200000000000000
in_len > 0x200000000000000 ||
#endif
in_len % KW_SEMIBLOCK_LENGTH != 0 )
{
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
}
ret = unwrap( ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
A, output, out_len );
if( ret != 0 )
goto cleanup;
/* Check ICV in "constant-time" */
diff = mbedtls_nist_kw_safer_memcmp( NIST_KW_ICV1, A, KW_SEMIBLOCK_LENGTH );
if( diff != 0 )
{
ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
goto cleanup;
}
}
else if( mode == MBEDTLS_KW_MODE_KWP )
{
size_t padlen = 0;
uint32_t Plen;
/*
* According to SP 800-38F Table 1, the ciphertext length for KWP
* must be between 2 to 2^29 semiblocks inclusive.
*/
if( in_len < KW_SEMIBLOCK_LENGTH * 2 ||
#if SIZE_MAX > 0x100000000
in_len > 0x100000000 ||
#endif
in_len % KW_SEMIBLOCK_LENGTH != 0 )
{
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
}
if( in_len == KW_SEMIBLOCK_LENGTH * 2 )
{
unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
ret = mbedtls_cipher_update( &ctx->cipher_ctx,
input, 16, outbuff, &olen );
if( ret != 0 )
goto cleanup;
memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH );
memcpy( output, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH );
mbedtls_platform_zeroize( outbuff, sizeof( outbuff ) );
*out_len = KW_SEMIBLOCK_LENGTH;
}
else
{
/* in_len >= KW_SEMIBLOCK_LENGTH * 3 */
ret = unwrap( ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
A, output, out_len );
if( ret != 0 )
goto cleanup;
}
/* Check ICV in "constant-time" */
diff = mbedtls_nist_kw_safer_memcmp( NIST_KW_ICV2, A, KW_SEMIBLOCK_LENGTH / 2 );
if( diff != 0 )
{
ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
}
GET_UINT32_BE( Plen, A, KW_SEMIBLOCK_LENGTH / 2 );
/*
* Plen is the length of the plaintext, when the input is valid.
* If Plen is larger than the plaintext and padding, padlen will be
* larger than 8, because of the type wrap around.
*/
padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen;
if ( padlen > 7 )
{
padlen &= 7;
ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
}
/* Check padding in "constant-time" */
for( diff = 0, i = 0; i < KW_SEMIBLOCK_LENGTH; i++ )
{
if( i >= KW_SEMIBLOCK_LENGTH - padlen )
diff |= output[*out_len - KW_SEMIBLOCK_LENGTH + i];
else
bad_padding |= output[*out_len - KW_SEMIBLOCK_LENGTH + i];
}
if( diff != 0 )
{
ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
}
if( ret != 0 )
{
goto cleanup;
}
memset( output + Plen, 0, padlen );
*out_len = Plen;
}
else
{
ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
goto cleanup;
}
cleanup:
if( ret != 0 )
{
memset( output, 0, *out_len );
*out_len = 0;
}
mbedtls_platform_zeroize( &bad_padding, sizeof( bad_padding) );
mbedtls_platform_zeroize( &diff, sizeof( diff ) );
mbedtls_platform_zeroize( A, sizeof( A ) );
mbedtls_cipher_finish( &ctx->cipher_ctx, NULL, &olen );
return( ret );
}
#endif /* !MBEDTLS_NIST_KW_ALT */
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
#define KW_TESTS 3
/*
* Test vectors taken from NIST
* https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES#KW
*/
static const unsigned int key_len[KW_TESTS] = { 16, 24, 32 };
static const unsigned char kw_key[KW_TESTS][32] = {
{ 0x75, 0x75, 0xda, 0x3a, 0x93, 0x60, 0x7c, 0xc2,
0xbf, 0xd8, 0xce, 0xc7, 0xaa, 0xdf, 0xd9, 0xa6 },
{ 0x2d, 0x85, 0x26, 0x08, 0x1d, 0x02, 0xfb, 0x5b,
0x85, 0xf6, 0x9a, 0xc2, 0x86, 0xec, 0xd5, 0x7d,
0x40, 0xdf, 0x5d, 0xf3, 0x49, 0x47, 0x44, 0xd3 },
{ 0x11, 0x2a, 0xd4, 0x1b, 0x48, 0x56, 0xc7, 0x25,
0x4a, 0x98, 0x48, 0xd3, 0x0f, 0xdd, 0x78, 0x33,
0x5b, 0x03, 0x9a, 0x48, 0xa8, 0x96, 0x2c, 0x4d,
0x1c, 0xb7, 0x8e, 0xab, 0xd5, 0xda, 0xd7, 0x88 }
};
static const unsigned char kw_msg[KW_TESTS][40] = {
{ 0x42, 0x13, 0x6d, 0x3c, 0x38, 0x4a, 0x3e, 0xea,
0xc9, 0x5a, 0x06, 0x6f, 0xd2, 0x8f, 0xed, 0x3f },
{ 0x95, 0xc1, 0x1b, 0xf5, 0x35, 0x3a, 0xfe, 0xdb,
0x98, 0xfd, 0xd6, 0xc8, 0xca, 0x6f, 0xdb, 0x6d,
0xa5, 0x4b, 0x74, 0xb4, 0x99, 0x0f, 0xdc, 0x45,
0xc0, 0x9d, 0x15, 0x8f, 0x51, 0xce, 0x62, 0x9d,
0xe2, 0xaf, 0x26, 0xe3, 0x25, 0x0e, 0x6b, 0x4c },
{ 0x1b, 0x20, 0xbf, 0x19, 0x90, 0xb0, 0x65, 0xd7,
0x98, 0xe1, 0xb3, 0x22, 0x64, 0xad, 0x50, 0xa8,
0x74, 0x74, 0x92, 0xba, 0x09, 0xa0, 0x4d, 0xd1 }
};
static const size_t kw_msg_len[KW_TESTS] = { 16, 40, 24 };
static const size_t kw_out_len[KW_TESTS] = { 24, 48, 32 };
static const unsigned char kw_res[KW_TESTS][48] = {
{ 0x03, 0x1f, 0x6b, 0xd7, 0xe6, 0x1e, 0x64, 0x3d,
0xf6, 0x85, 0x94, 0x81, 0x6f, 0x64, 0xca, 0xa3,
0xf5, 0x6f, 0xab, 0xea, 0x25, 0x48, 0xf5, 0xfb },
{ 0x44, 0x3c, 0x6f, 0x15, 0x09, 0x83, 0x71, 0x91,
0x3e, 0x5c, 0x81, 0x4c, 0xa1, 0xa0, 0x42, 0xec,
0x68, 0x2f, 0x7b, 0x13, 0x6d, 0x24, 0x3a, 0x4d,
0x6c, 0x42, 0x6f, 0xc6, 0x97, 0x15, 0x63, 0xe8,
0xa1, 0x4a, 0x55, 0x8e, 0x09, 0x64, 0x16, 0x19,
0xbf, 0x03, 0xfc, 0xaf, 0x90, 0xb1, 0xfc, 0x2d },
{ 0xba, 0x8a, 0x25, 0x9a, 0x47, 0x1b, 0x78, 0x7d,
0xd5, 0xd5, 0x40, 0xec, 0x25, 0xd4, 0x3d, 0x87,
0x20, 0x0f, 0xda, 0xdc, 0x6d, 0x1f, 0x05, 0xd9,
0x16, 0x58, 0x4f, 0xa9, 0xf6, 0xcb, 0xf5, 0x12 }
};
static const unsigned char kwp_key[KW_TESTS][32] = {
{ 0x78, 0x65, 0xe2, 0x0f, 0x3c, 0x21, 0x65, 0x9a,
0xb4, 0x69, 0x0b, 0x62, 0x9c, 0xdf, 0x3c, 0xc4 },
{ 0xf5, 0xf8, 0x96, 0xa3, 0xbd, 0x2f, 0x4a, 0x98,
0x23, 0xef, 0x16, 0x2b, 0x00, 0xb8, 0x05, 0xd7,
0xde, 0x1e, 0xa4, 0x66, 0x26, 0x96, 0xa2, 0x58 },
{ 0x95, 0xda, 0x27, 0x00, 0xca, 0x6f, 0xd9, 0xa5,
0x25, 0x54, 0xee, 0x2a, 0x8d, 0xf1, 0x38, 0x6f,
0x5b, 0x94, 0xa1, 0xa6, 0x0e, 0xd8, 0xa4, 0xae,
0xf6, 0x0a, 0x8d, 0x61, 0xab, 0x5f, 0x22, 0x5a }
};
static const unsigned char kwp_msg[KW_TESTS][31] = {
{ 0xbd, 0x68, 0x43, 0xd4, 0x20, 0x37, 0x8d, 0xc8,
0x96 },
{ 0x6c, 0xcd, 0xd5, 0x85, 0x18, 0x40, 0x97, 0xeb,
0xd5, 0xc3, 0xaf, 0x3e, 0x47, 0xd0, 0x2c, 0x19,
0x14, 0x7b, 0x4d, 0x99, 0x5f, 0x96, 0x43, 0x66,
0x91, 0x56, 0x75, 0x8c, 0x13, 0x16, 0x8f },
{ 0xd1 }
};
static const size_t kwp_msg_len[KW_TESTS] = { 9, 31, 1 };
static const unsigned char kwp_res[KW_TESTS][48] = {
{ 0x41, 0xec, 0xa9, 0x56, 0xd4, 0xaa, 0x04, 0x7e,
0xb5, 0xcf, 0x4e, 0xfe, 0x65, 0x96, 0x61, 0xe7,
0x4d, 0xb6, 0xf8, 0xc5, 0x64, 0xe2, 0x35, 0x00 },
{ 0x4e, 0x9b, 0xc2, 0xbc, 0xbc, 0x6c, 0x1e, 0x13,
0xd3, 0x35, 0xbc, 0xc0, 0xf7, 0x73, 0x6a, 0x88,
0xfa, 0x87, 0x53, 0x66, 0x15, 0xbb, 0x8e, 0x63,
0x8b, 0xcc, 0x81, 0x66, 0x84, 0x68, 0x17, 0x90,
0x67, 0xcf, 0xa9, 0x8a, 0x9d, 0x0e, 0x33, 0x26 },
{ 0x06, 0xba, 0x7a, 0xe6, 0xf3, 0x24, 0x8c, 0xfd,
0xcf, 0x26, 0x75, 0x07, 0xfa, 0x00, 0x1b, 0xc4 }
};
static const size_t kwp_out_len[KW_TESTS] = { 24, 40, 16 };
int mbedtls_nist_kw_self_test( int verbose )
{
mbedtls_nist_kw_context ctx;
unsigned char out[48];
size_t olen;
int i;
int ret = 0;
mbedtls_nist_kw_init( &ctx );
for( i = 0; i < KW_TESTS; i++ )
{
if( verbose != 0 )
mbedtls_printf( " KW-AES-%u ", (unsigned int) key_len[i] * 8 );
ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES,
kw_key[i], key_len[i] * 8, 1 );
if( ret != 0 )
{
if( verbose != 0 )
mbedtls_printf( " KW: setup failed " );
goto end;
}
ret = mbedtls_nist_kw_wrap( &ctx, MBEDTLS_KW_MODE_KW, kw_msg[i],
kw_msg_len[i], out, &olen, sizeof( out ) );
if( ret != 0 || kw_out_len[i] != olen ||
memcmp( out, kw_res[i], kw_out_len[i] ) != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed. ");
ret = 1;
goto end;
}
if( ( ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES,
kw_key[i], key_len[i] * 8, 0 ) )
!= 0 )
{
if( verbose != 0 )
mbedtls_printf( " KW: setup failed ");
goto end;
}
ret = mbedtls_nist_kw_unwrap( &ctx, MBEDTLS_KW_MODE_KW,
out, olen, out, &olen, sizeof( out ) );
if( ret != 0 || olen != kw_msg_len[i] ||
memcmp( out, kw_msg[i], kw_msg_len[i] ) != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
ret = 1;
goto end;
}
if( verbose != 0 )
mbedtls_printf( " passed\n" );
}
for( i = 0; i < KW_TESTS; i++ )
{
olen = sizeof( out );
if( verbose != 0 )
mbedtls_printf( " KWP-AES-%u ", (unsigned int) key_len[i] * 8 );
ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i],
key_len[i] * 8, 1 );
if( ret != 0 )
{
if( verbose != 0 )
mbedtls_printf( " KWP: setup failed " );
goto end;
}
ret = mbedtls_nist_kw_wrap( &ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i],
kwp_msg_len[i], out, &olen, sizeof( out ) );
if( ret != 0 || kwp_out_len[i] != olen ||
memcmp( out, kwp_res[i], kwp_out_len[i] ) != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed. ");
ret = 1;
goto end;
}
if( ( ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES,
kwp_key[i], key_len[i] * 8, 0 ) )
!= 0 )
{
if( verbose != 0 )
mbedtls_printf( " KWP: setup failed ");
goto end;
}
ret = mbedtls_nist_kw_unwrap( &ctx, MBEDTLS_KW_MODE_KWP, out,
olen, out, &olen, sizeof( out ) );
if( ret != 0 || olen != kwp_msg_len[i] ||
memcmp( out, kwp_msg[i], kwp_msg_len[i] ) != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed. ");
ret = 1;
goto end;
}
if( verbose != 0 )
mbedtls_printf( " passed\n" );
}
end:
mbedtls_nist_kw_free( &ctx );
if( verbose != 0 )
mbedtls_printf( "\n" );
return( ret );
}
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
#endif /* MBEDTLS_NIST_KW_C */

View file

@ -249,8 +249,10 @@ int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx, const unsigned char *p
memset( counter, 0, 4 );
counter[3] = 1;
#if UINT_MAX > 0xFFFFFFFF
if( iteration_count > 0xFFFFFFFF )
return( MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA );
#endif
while( key_length )
{

View file

@ -1261,7 +1261,6 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk,
return( ret );
#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */
#else
((void) ret);
((void) pwd);
((void) pwdlen);
#endif /* MBEDTLS_PEM_PARSE_C */

View file

@ -51,14 +51,24 @@ static void platform_free_uninit( void *ptr )
#define MBEDTLS_PLATFORM_STD_FREE platform_free_uninit
#endif /* !MBEDTLS_PLATFORM_STD_FREE */
void * (*mbedtls_calloc)( size_t, size_t ) = MBEDTLS_PLATFORM_STD_CALLOC;
void (*mbedtls_free)( void * ) = MBEDTLS_PLATFORM_STD_FREE;
static void * (*mbedtls_calloc_func)( size_t, size_t ) = MBEDTLS_PLATFORM_STD_CALLOC;
static void (*mbedtls_free_func)( void * ) = MBEDTLS_PLATFORM_STD_FREE;
void * mbedtls_calloc( size_t nmemb, size_t size )
{
return (*mbedtls_calloc_func)( nmemb, size );
}
void mbedtls_free( void * ptr )
{
(*mbedtls_free_func)( ptr );
}
int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ),
void (*free_func)( void * ) )
{
mbedtls_calloc = calloc_func;
mbedtls_free = free_func;
mbedtls_calloc_func = calloc_func;
mbedtls_free_func = free_func;
return( 0 );
}
#endif /* MBEDTLS_PLATFORM_MEMORY */

563
thirdparty/mbedtls/library/poly1305.c vendored Normal file
View file

@ -0,0 +1,563 @@
/**
* \file poly1305.c
*
* \brief Poly1305 authentication algorithm.
*
* Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_POLY1305_C)
#include "mbedtls/poly1305.h"
#include "mbedtls/platform_util.h"
#include <string.h>
#if defined(MBEDTLS_SELF_TEST)
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#define mbedtls_printf printf
#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST */
#if !defined(MBEDTLS_POLY1305_ALT)
#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
!defined(inline) && !defined(__cplusplus)
#define inline __inline
#endif
#define POLY1305_BLOCK_SIZE_BYTES ( 16U )
#define BYTES_TO_U32_LE( data, offset ) \
( (uint32_t) data[offset] \
| (uint32_t) ( (uint32_t) data[( offset ) + 1] << 8 ) \
| (uint32_t) ( (uint32_t) data[( offset ) + 2] << 16 ) \
| (uint32_t) ( (uint32_t) data[( offset ) + 3] << 24 ) \
)
/*
* Our implementation is tuned for 32-bit platforms with a 64-bit multiplier.
* However we provided an alternative for platforms without such a multiplier.
*/
#if defined(MBEDTLS_NO_64BIT_MULTIPLICATION)
static uint64_t mul64( uint32_t a, uint32_t b )
{
/* a = al + 2**16 ah, b = bl + 2**16 bh */
const uint16_t al = (uint16_t) a;
const uint16_t bl = (uint16_t) b;
const uint16_t ah = a >> 16;
const uint16_t bh = b >> 16;
/* ab = al*bl + 2**16 (ah*bl + bl*bh) + 2**32 ah*bh */
const uint32_t lo = (uint32_t) al * bl;
const uint64_t me = (uint64_t)( (uint32_t) ah * bl ) + (uint32_t) al * bh;
const uint32_t hi = (uint32_t) ah * bh;
return( lo + ( me << 16 ) + ( (uint64_t) hi << 32 ) );
}
#else
static inline uint64_t mul64( uint32_t a, uint32_t b )
{
return( (uint64_t) a * b );
}
#endif
/**
* \brief Process blocks with Poly1305.
*
* \param ctx The Poly1305 context.
* \param nblocks Number of blocks to process. Note that this
* function only processes full blocks.
* \param input Buffer containing the input block(s).
* \param needs_padding Set to 0 if the padding bit has already been
* applied to the input data before calling this
* function. Otherwise, set this parameter to 1.
*/
static void poly1305_process( mbedtls_poly1305_context *ctx,
size_t nblocks,
const unsigned char *input,
uint32_t needs_padding )
{
uint64_t d0, d1, d2, d3;
uint32_t acc0, acc1, acc2, acc3, acc4;
uint32_t r0, r1, r2, r3;
uint32_t rs1, rs2, rs3;
size_t offset = 0U;
size_t i;
r0 = ctx->r[0];
r1 = ctx->r[1];
r2 = ctx->r[2];
r3 = ctx->r[3];
rs1 = r1 + ( r1 >> 2U );
rs2 = r2 + ( r2 >> 2U );
rs3 = r3 + ( r3 >> 2U );
acc0 = ctx->acc[0];
acc1 = ctx->acc[1];
acc2 = ctx->acc[2];
acc3 = ctx->acc[3];
acc4 = ctx->acc[4];
/* Process full blocks */
for( i = 0U; i < nblocks; i++ )
{
/* The input block is treated as a 128-bit little-endian integer */
d0 = BYTES_TO_U32_LE( input, offset + 0 );
d1 = BYTES_TO_U32_LE( input, offset + 4 );
d2 = BYTES_TO_U32_LE( input, offset + 8 );
d3 = BYTES_TO_U32_LE( input, offset + 12 );
/* Compute: acc += (padded) block as a 130-bit integer */
d0 += (uint64_t) acc0;
d1 += (uint64_t) acc1 + ( d0 >> 32U );
d2 += (uint64_t) acc2 + ( d1 >> 32U );
d3 += (uint64_t) acc3 + ( d2 >> 32U );
acc0 = (uint32_t) d0;
acc1 = (uint32_t) d1;
acc2 = (uint32_t) d2;
acc3 = (uint32_t) d3;
acc4 += (uint32_t) ( d3 >> 32U ) + needs_padding;
/* Compute: acc *= r */
d0 = mul64( acc0, r0 ) +
mul64( acc1, rs3 ) +
mul64( acc2, rs2 ) +
mul64( acc3, rs1 );
d1 = mul64( acc0, r1 ) +
mul64( acc1, r0 ) +
mul64( acc2, rs3 ) +
mul64( acc3, rs2 ) +
mul64( acc4, rs1 );
d2 = mul64( acc0, r2 ) +
mul64( acc1, r1 ) +
mul64( acc2, r0 ) +
mul64( acc3, rs3 ) +
mul64( acc4, rs2 );
d3 = mul64( acc0, r3 ) +
mul64( acc1, r2 ) +
mul64( acc2, r1 ) +
mul64( acc3, r0 ) +
mul64( acc4, rs3 );
acc4 *= r0;
/* Compute: acc %= (2^130 - 5) (partial remainder) */
d1 += ( d0 >> 32 );
d2 += ( d1 >> 32 );
d3 += ( d2 >> 32 );
acc0 = (uint32_t) d0;
acc1 = (uint32_t) d1;
acc2 = (uint32_t) d2;
acc3 = (uint32_t) d3;
acc4 = (uint32_t) ( d3 >> 32 ) + acc4;
d0 = (uint64_t) acc0 + ( acc4 >> 2 ) + ( acc4 & 0xFFFFFFFCU );
acc4 &= 3U;
acc0 = (uint32_t) d0;
d0 = (uint64_t) acc1 + ( d0 >> 32U );
acc1 = (uint32_t) d0;
d0 = (uint64_t) acc2 + ( d0 >> 32U );
acc2 = (uint32_t) d0;
d0 = (uint64_t) acc3 + ( d0 >> 32U );
acc3 = (uint32_t) d0;
d0 = (uint64_t) acc4 + ( d0 >> 32U );
acc4 = (uint32_t) d0;
offset += POLY1305_BLOCK_SIZE_BYTES;
}
ctx->acc[0] = acc0;
ctx->acc[1] = acc1;
ctx->acc[2] = acc2;
ctx->acc[3] = acc3;
ctx->acc[4] = acc4;
}
/**
* \brief Compute the Poly1305 MAC
*
* \param ctx The Poly1305 context.
* \param mac The buffer to where the MAC is written. Must be
* big enough to contain the 16-byte MAC.
*/
static void poly1305_compute_mac( const mbedtls_poly1305_context *ctx,
unsigned char mac[16] )
{
uint64_t d;
uint32_t g0, g1, g2, g3, g4;
uint32_t acc0, acc1, acc2, acc3, acc4;
uint32_t mask;
uint32_t mask_inv;
acc0 = ctx->acc[0];
acc1 = ctx->acc[1];
acc2 = ctx->acc[2];
acc3 = ctx->acc[3];
acc4 = ctx->acc[4];
/* Before adding 's' we ensure that the accumulator is mod 2^130 - 5.
* We do this by calculating acc - (2^130 - 5), then checking if
* the 131st bit is set. If it is, then reduce: acc -= (2^130 - 5)
*/
/* Calculate acc + -(2^130 - 5) */
d = ( (uint64_t) acc0 + 5U );
g0 = (uint32_t) d;
d = ( (uint64_t) acc1 + ( d >> 32 ) );
g1 = (uint32_t) d;
d = ( (uint64_t) acc2 + ( d >> 32 ) );
g2 = (uint32_t) d;
d = ( (uint64_t) acc3 + ( d >> 32 ) );
g3 = (uint32_t) d;
g4 = acc4 + (uint32_t) ( d >> 32U );
/* mask == 0xFFFFFFFF if 131st bit is set, otherwise mask == 0 */
mask = (uint32_t) 0U - ( g4 >> 2U );
mask_inv = ~mask;
/* If 131st bit is set then acc=g, otherwise, acc is unmodified */
acc0 = ( acc0 & mask_inv ) | ( g0 & mask );
acc1 = ( acc1 & mask_inv ) | ( g1 & mask );
acc2 = ( acc2 & mask_inv ) | ( g2 & mask );
acc3 = ( acc3 & mask_inv ) | ( g3 & mask );
/* Add 's' */
d = (uint64_t) acc0 + ctx->s[0];
acc0 = (uint32_t) d;
d = (uint64_t) acc1 + ctx->s[1] + ( d >> 32U );
acc1 = (uint32_t) d;
d = (uint64_t) acc2 + ctx->s[2] + ( d >> 32U );
acc2 = (uint32_t) d;
acc3 += ctx->s[3] + (uint32_t) ( d >> 32U );
/* Compute MAC (128 least significant bits of the accumulator) */
mac[ 0] = (unsigned char)( acc0 );
mac[ 1] = (unsigned char)( acc0 >> 8 );
mac[ 2] = (unsigned char)( acc0 >> 16 );
mac[ 3] = (unsigned char)( acc0 >> 24 );
mac[ 4] = (unsigned char)( acc1 );
mac[ 5] = (unsigned char)( acc1 >> 8 );
mac[ 6] = (unsigned char)( acc1 >> 16 );
mac[ 7] = (unsigned char)( acc1 >> 24 );
mac[ 8] = (unsigned char)( acc2 );
mac[ 9] = (unsigned char)( acc2 >> 8 );
mac[10] = (unsigned char)( acc2 >> 16 );
mac[11] = (unsigned char)( acc2 >> 24 );
mac[12] = (unsigned char)( acc3 );
mac[13] = (unsigned char)( acc3 >> 8 );
mac[14] = (unsigned char)( acc3 >> 16 );
mac[15] = (unsigned char)( acc3 >> 24 );
}
void mbedtls_poly1305_init( mbedtls_poly1305_context *ctx )
{
if( ctx != NULL )
{
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_poly1305_context ) );
}
}
void mbedtls_poly1305_free( mbedtls_poly1305_context *ctx )
{
if( ctx != NULL )
{
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_poly1305_context ) );
}
}
int mbedtls_poly1305_starts( mbedtls_poly1305_context *ctx,
const unsigned char key[32] )
{
if( ctx == NULL || key == NULL )
{
return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
}
/* r &= 0x0ffffffc0ffffffc0ffffffc0fffffff */
ctx->r[0] = BYTES_TO_U32_LE( key, 0 ) & 0x0FFFFFFFU;
ctx->r[1] = BYTES_TO_U32_LE( key, 4 ) & 0x0FFFFFFCU;
ctx->r[2] = BYTES_TO_U32_LE( key, 8 ) & 0x0FFFFFFCU;
ctx->r[3] = BYTES_TO_U32_LE( key, 12 ) & 0x0FFFFFFCU;
ctx->s[0] = BYTES_TO_U32_LE( key, 16 );
ctx->s[1] = BYTES_TO_U32_LE( key, 20 );
ctx->s[2] = BYTES_TO_U32_LE( key, 24 );
ctx->s[3] = BYTES_TO_U32_LE( key, 28 );
/* Initial accumulator state */
ctx->acc[0] = 0U;
ctx->acc[1] = 0U;
ctx->acc[2] = 0U;
ctx->acc[3] = 0U;
ctx->acc[4] = 0U;
/* Queue initially empty */
mbedtls_platform_zeroize( ctx->queue, sizeof( ctx->queue ) );
ctx->queue_len = 0U;
return( 0 );
}
int mbedtls_poly1305_update( mbedtls_poly1305_context *ctx,
const unsigned char *input,
size_t ilen )
{
size_t offset = 0U;
size_t remaining = ilen;
size_t queue_free_len;
size_t nblocks;
if( ctx == NULL )
{
return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
}
else if( ( ilen > 0U ) && ( input == NULL ) )
{
/* input pointer is allowed to be NULL only if ilen == 0 */
return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
}
if( ( remaining > 0U ) && ( ctx->queue_len > 0U ) )
{
queue_free_len = ( POLY1305_BLOCK_SIZE_BYTES - ctx->queue_len );
if( ilen < queue_free_len )
{
/* Not enough data to complete the block.
* Store this data with the other leftovers.
*/
memcpy( &ctx->queue[ctx->queue_len],
input,
ilen );
ctx->queue_len += ilen;
remaining = 0U;
}
else
{
/* Enough data to produce a complete block */
memcpy( &ctx->queue[ctx->queue_len],
input,
queue_free_len );
ctx->queue_len = 0U;
poly1305_process( ctx, 1U, ctx->queue, 1U ); /* add padding bit */
offset += queue_free_len;
remaining -= queue_free_len;
}
}
if( remaining >= POLY1305_BLOCK_SIZE_BYTES )
{
nblocks = remaining / POLY1305_BLOCK_SIZE_BYTES;
poly1305_process( ctx, nblocks, &input[offset], 1U );
offset += nblocks * POLY1305_BLOCK_SIZE_BYTES;
remaining %= POLY1305_BLOCK_SIZE_BYTES;
}
if( remaining > 0U )
{
/* Store partial block */
ctx->queue_len = remaining;
memcpy( ctx->queue, &input[offset], remaining );
}
return( 0 );
}
int mbedtls_poly1305_finish( mbedtls_poly1305_context *ctx,
unsigned char mac[16] )
{
if( ( ctx == NULL ) || ( mac == NULL ) )
{
return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
}
/* Process any leftover data */
if( ctx->queue_len > 0U )
{
/* Add padding bit */
ctx->queue[ctx->queue_len] = 1U;
ctx->queue_len++;
/* Pad with zeroes */
memset( &ctx->queue[ctx->queue_len],
0,
POLY1305_BLOCK_SIZE_BYTES - ctx->queue_len );
poly1305_process( ctx, 1U, /* Process 1 block */
ctx->queue, 0U ); /* Already padded above */
}
poly1305_compute_mac( ctx, mac );
return( 0 );
}
int mbedtls_poly1305_mac( const unsigned char key[32],
const unsigned char *input,
size_t ilen,
unsigned char mac[16] )
{
mbedtls_poly1305_context ctx;
int ret;
mbedtls_poly1305_init( &ctx );
ret = mbedtls_poly1305_starts( &ctx, key );
if( ret != 0 )
goto cleanup;
ret = mbedtls_poly1305_update( &ctx, input, ilen );
if( ret != 0 )
goto cleanup;
ret = mbedtls_poly1305_finish( &ctx, mac );
cleanup:
mbedtls_poly1305_free( &ctx );
return( ret );
}
#endif /* MBEDTLS_POLY1305_ALT */
#if defined(MBEDTLS_SELF_TEST)
static const unsigned char test_keys[2][32] =
{
{
0x85, 0xd6, 0xbe, 0x78, 0x57, 0x55, 0x6d, 0x33,
0x7f, 0x44, 0x52, 0xfe, 0x42, 0xd5, 0x06, 0xa8,
0x01, 0x03, 0x80, 0x8a, 0xfb, 0x0d, 0xb2, 0xfd,
0x4a, 0xbf, 0xf6, 0xaf, 0x41, 0x49, 0xf5, 0x1b
},
{
0x1c, 0x92, 0x40, 0xa5, 0xeb, 0x55, 0xd3, 0x8a,
0xf3, 0x33, 0x88, 0x86, 0x04, 0xf6, 0xb5, 0xf0,
0x47, 0x39, 0x17, 0xc1, 0x40, 0x2b, 0x80, 0x09,
0x9d, 0xca, 0x5c, 0xbc, 0x20, 0x70, 0x75, 0xc0
}
};
static const unsigned char test_data[2][127] =
{
{
0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x67, 0x72,
0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x46, 0x6f,
0x72, 0x75, 0x6d, 0x20, 0x52, 0x65, 0x73, 0x65,
0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6f,
0x75, 0x70
},
{
0x27, 0x54, 0x77, 0x61, 0x73, 0x20, 0x62, 0x72,
0x69, 0x6c, 0x6c, 0x69, 0x67, 0x2c, 0x20, 0x61,
0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
0x6c, 0x69, 0x74, 0x68, 0x79, 0x20, 0x74, 0x6f,
0x76, 0x65, 0x73, 0x0a, 0x44, 0x69, 0x64, 0x20,
0x67, 0x79, 0x72, 0x65, 0x20, 0x61, 0x6e, 0x64,
0x20, 0x67, 0x69, 0x6d, 0x62, 0x6c, 0x65, 0x20,
0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77,
0x61, 0x62, 0x65, 0x3a, 0x0a, 0x41, 0x6c, 0x6c,
0x20, 0x6d, 0x69, 0x6d, 0x73, 0x79, 0x20, 0x77,
0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20,
0x62, 0x6f, 0x72, 0x6f, 0x67, 0x6f, 0x76, 0x65,
0x73, 0x2c, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
0x68, 0x65, 0x20, 0x6d, 0x6f, 0x6d, 0x65, 0x20,
0x72, 0x61, 0x74, 0x68, 0x73, 0x20, 0x6f, 0x75,
0x74, 0x67, 0x72, 0x61, 0x62, 0x65, 0x2e
}
};
static const size_t test_data_len[2] =
{
34U,
127U
};
static const unsigned char test_mac[2][16] =
{
{
0xa8, 0x06, 0x1d, 0xc1, 0x30, 0x51, 0x36, 0xc6,
0xc2, 0x2b, 0x8b, 0xaf, 0x0c, 0x01, 0x27, 0xa9
},
{
0x45, 0x41, 0x66, 0x9a, 0x7e, 0xaa, 0xee, 0x61,
0xe7, 0x08, 0xdc, 0x7c, 0xbc, 0xc5, 0xeb, 0x62
}
};
#define ASSERT( cond, args ) \
do \
{ \
if( ! ( cond ) ) \
{ \
if( verbose != 0 ) \
mbedtls_printf args; \
\
return( -1 ); \
} \
} \
while( 0 )
int mbedtls_poly1305_self_test( int verbose )
{
unsigned char mac[16];
unsigned i;
int ret;
for( i = 0U; i < 2U; i++ )
{
if( verbose != 0 )
mbedtls_printf( " Poly1305 test %u ", i );
ret = mbedtls_poly1305_mac( test_keys[i],
test_data[i],
test_data_len[i],
mac );
ASSERT( 0 == ret, ( "error code: %i\n", ret ) );
ASSERT( 0 == memcmp( mac, test_mac[i], 16U ), ( "failed (mac)\n" ) );
if( verbose != 0 )
mbedtls_printf( "passed\n" );
}
if( verbose != 0 )
mbedtls_printf( "\n" );
return( 0 );
}
#endif /* MBEDTLS_SELF_TEST */
#endif /* MBEDTLS_POLY1305_C */

View file

@ -342,14 +342,6 @@ void mbedtls_sha1_update( mbedtls_sha1_context *ctx,
}
#endif
static const unsigned char sha1_padding[64] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
* SHA-1 final digest
*/
@ -357,25 +349,48 @@ int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx,
unsigned char output[20] )
{
int ret;
uint32_t last, padn;
uint32_t used;
uint32_t high, low;
unsigned char msglen[8];
/*
* Add padding: 0x80 then 0x00 until 8 bytes remain for the length
*/
used = ctx->total[0] & 0x3F;
ctx->buffer[used++] = 0x80;
if( used <= 56 )
{
/* Enough room for padding + length in current block */
memset( ctx->buffer + used, 0, 56 - used );
}
else
{
/* We'll need an extra block */
memset( ctx->buffer + used, 0, 64 - used );
if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 )
return( ret );
memset( ctx->buffer, 0, 56 );
}
/*
* Add message length
*/
high = ( ctx->total[0] >> 29 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
PUT_UINT32_BE( high, msglen, 0 );
PUT_UINT32_BE( low, msglen, 4 );
PUT_UINT32_BE( high, ctx->buffer, 56 );
PUT_UINT32_BE( low, ctx->buffer, 60 );
last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
if( ( ret = mbedtls_sha1_update_ret( ctx, sha1_padding, padn ) ) != 0 )
return( ret );
if( ( ret = mbedtls_sha1_update_ret( ctx, msglen, 8 ) ) != 0 )
if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 )
return( ret );
/*
* Output final state
*/
PUT_UINT32_BE( ctx->state[0], output, 0 );
PUT_UINT32_BE( ctx->state[1], output, 4 );
PUT_UINT32_BE( ctx->state[2], output, 8 );

View file

@ -311,14 +311,6 @@ void mbedtls_sha256_update( mbedtls_sha256_context *ctx,
}
#endif
static const unsigned char sha256_padding[64] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
* SHA-256 final digest
*/
@ -326,26 +318,48 @@ int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx,
unsigned char output[32] )
{
int ret;
uint32_t last, padn;
uint32_t used;
uint32_t high, low;
unsigned char msglen[8];
/*
* Add padding: 0x80 then 0x00 until 8 bytes remain for the length
*/
used = ctx->total[0] & 0x3F;
ctx->buffer[used++] = 0x80;
if( used <= 56 )
{
/* Enough room for padding + length in current block */
memset( ctx->buffer + used, 0, 56 - used );
}
else
{
/* We'll need an extra block */
memset( ctx->buffer + used, 0, 64 - used );
if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 )
return( ret );
memset( ctx->buffer, 0, 56 );
}
/*
* Add message length
*/
high = ( ctx->total[0] >> 29 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
PUT_UINT32_BE( high, msglen, 0 );
PUT_UINT32_BE( low, msglen, 4 );
PUT_UINT32_BE( high, ctx->buffer, 56 );
PUT_UINT32_BE( low, ctx->buffer, 60 );
last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
if( ( ret = mbedtls_sha256_update_ret( ctx, sha256_padding, padn ) ) != 0 )
return( ret );
if( ( ret = mbedtls_sha256_update_ret( ctx, msglen, 8 ) ) != 0 )
if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 )
return( ret );
/*
* Output final state
*/
PUT_UINT32_BE( ctx->state[0], output, 0 );
PUT_UINT32_BE( ctx->state[1], output, 4 );
PUT_UINT32_BE( ctx->state[2], output, 8 );

View file

@ -341,18 +341,6 @@ void mbedtls_sha512_update( mbedtls_sha512_context *ctx,
}
#endif
static const unsigned char sha512_padding[128] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
* SHA-512 final digest
*/
@ -360,26 +348,48 @@ int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx,
unsigned char output[64] )
{
int ret;
size_t last, padn;
unsigned used;
uint64_t high, low;
unsigned char msglen[16];
/*
* Add padding: 0x80 then 0x00 until 16 bytes remain for the length
*/
used = ctx->total[0] & 0x7F;
ctx->buffer[used++] = 0x80;
if( used <= 112 )
{
/* Enough room for padding + length in current block */
memset( ctx->buffer + used, 0, 112 - used );
}
else
{
/* We'll need an extra block */
memset( ctx->buffer + used, 0, 128 - used );
if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 )
return( ret );
memset( ctx->buffer, 0, 112 );
}
/*
* Add message length
*/
high = ( ctx->total[0] >> 61 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
PUT_UINT64_BE( high, msglen, 0 );
PUT_UINT64_BE( low, msglen, 8 );
PUT_UINT64_BE( high, ctx->buffer, 112 );
PUT_UINT64_BE( low, ctx->buffer, 120 );
last = (size_t)( ctx->total[0] & 0x7F );
padn = ( last < 112 ) ? ( 112 - last ) : ( 240 - last );
if( ( ret = mbedtls_sha512_update_ret( ctx, sha512_padding, padn ) ) != 0 )
return( ret );
if( ( ret = mbedtls_sha512_update_ret( ctx, msglen, 16 ) ) != 0 )
return( ret );
if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 )
return( ret );
/*
* Output final state
*/
PUT_UINT64_BE( ctx->state[0], output, 0 );
PUT_UINT64_BE( ctx->state[1], output, 8 );
PUT_UINT64_BE( ctx->state[2], output, 16 );

View file

@ -47,7 +47,7 @@
* 1. By key exchange:
* Forward-secure non-PSK > forward-secure PSK > ECJPAKE > other non-PSK > other PSK
* 2. By key length and cipher:
* AES-256 > Camellia-256 > ARIA-256 > AES-128 > Camellia-128 > ARIA-128 > 3DES
* ChaCha > AES-256 > Camellia-256 > ARIA-256 > AES-128 > Camellia-128 > ARIA-128 > 3DES
* 3. By cipher mode when relevant GCM > CCM > CBC > CCM_8
* 4. By hash function used when relevant
* 5. By key exchange/auth again: EC > non-EC
@ -57,6 +57,11 @@ static const int ciphersuite_preference[] =
#if defined(MBEDTLS_SSL_CIPHERSUITES)
MBEDTLS_SSL_CIPHERSUITES,
#else
/* Chacha-Poly ephemeral suites */
MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
/* All AES-256 ephemeral suites */
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
@ -127,6 +132,8 @@ static const int ciphersuite_preference[] =
MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
/* The PSK ephemeral suites */
MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384,
MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM,
MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
@ -227,6 +234,7 @@ static const int ciphersuite_preference[] =
MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
/* The RSA PSK suites */
MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256,
MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384,
MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384,
MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA,
@ -246,6 +254,7 @@ static const int ciphersuite_preference[] =
MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA,
/* The PSK suites */
MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256,
MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384,
MBEDTLS_TLS_PSK_WITH_AES_256_CCM,
MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384,
@ -312,6 +321,75 @@ static const int ciphersuite_preference[] =
static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
{
#if defined(MBEDTLS_CHACHAPOLY_C) && \
defined(MBEDTLS_SHA256_C) && \
defined(MBEDTLS_SSL_PROTO_TLS1_2)
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED)
{ MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
"TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256",
MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,
MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
0 },
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
{ MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
"TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256",
MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,
MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
0 },
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED)
{ MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
"TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256",
MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,
MBEDTLS_KEY_EXCHANGE_DHE_RSA,
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
0 },
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
{ MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256,
"TLS-PSK-WITH-CHACHA20-POLY1305-SHA256",
MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,
MBEDTLS_KEY_EXCHANGE_PSK,
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
0 },
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
{ MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
"TLS-ECDHE-PSK-WITH-CHACHA20-POLY1305-SHA256",
MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,
MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
0 },
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
{ MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
"TLS-DHE-PSK-WITH-CHACHA20-POLY1305-SHA256",
MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,
MBEDTLS_KEY_EXCHANGE_DHE_PSK,
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
0 },
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
{ MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256,
"TLS-RSA-PSK-WITH-CHACHA20-POLY1305-SHA256",
MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,
MBEDTLS_KEY_EXCHANGE_RSA_PSK,
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
0 },
#endif
#endif /* MBEDTLS_CHACHAPOLY_C &&
MBEDTLS_SHA256_C &&
MBEDTLS_SSL_PROTO_TLS1_2 */
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
#if defined(MBEDTLS_AES_C)
#if defined(MBEDTLS_SHA1_C)

View file

@ -57,7 +57,7 @@ static void ssl_write_hostname_ext( mbedtls_ssl_context *ssl,
size_t *olen )
{
unsigned char *p = buf;
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
size_t hostname_len;
*olen = 0;
@ -127,7 +127,7 @@ static void ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl,
size_t *olen )
{
unsigned char *p = buf;
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
*olen = 0;
@ -171,7 +171,7 @@ static void ssl_write_signature_algorithms_ext( mbedtls_ssl_context *ssl,
size_t *olen )
{
unsigned char *p = buf;
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
size_t sig_alg_len = 0;
const int *md;
#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C)
@ -256,7 +256,7 @@ static void ssl_write_supported_elliptic_curves_ext( mbedtls_ssl_context *ssl,
size_t *olen )
{
unsigned char *p = buf;
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
unsigned char *elliptic_curve_list = p + 6;
size_t elliptic_curve_len = 0;
const mbedtls_ecp_curve_info *info;
@ -329,7 +329,7 @@ static void ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl,
size_t *olen )
{
unsigned char *p = buf;
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
*olen = 0;
@ -362,7 +362,7 @@ static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl,
{
int ret;
unsigned char *p = buf;
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
size_t kkpp_len;
*olen = 0;
@ -439,7 +439,7 @@ static void ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl,
size_t *olen )
{
unsigned char *p = buf;
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
*olen = 0;
@ -472,7 +472,7 @@ static void ssl_write_truncated_hmac_ext( mbedtls_ssl_context *ssl,
unsigned char *buf, size_t *olen )
{
unsigned char *p = buf;
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
*olen = 0;
@ -504,7 +504,7 @@ static void ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl,
unsigned char *buf, size_t *olen )
{
unsigned char *p = buf;
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
*olen = 0;
@ -538,7 +538,7 @@ static void ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl,
unsigned char *buf, size_t *olen )
{
unsigned char *p = buf;
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
*olen = 0;
@ -572,7 +572,7 @@ static void ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl,
unsigned char *buf, size_t *olen )
{
unsigned char *p = buf;
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
size_t tlen = ssl->session_negotiate->ticket_len;
*olen = 0;
@ -616,7 +616,7 @@ static void ssl_write_alpn_ext( mbedtls_ssl_context *ssl,
unsigned char *buf, size_t *olen )
{
unsigned char *p = buf;
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
size_t alpnlen = 0;
const char **cur;
@ -1247,14 +1247,14 @@ static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl,
size_t list_size;
const unsigned char *p;
list_size = buf[0];
if( list_size + 1 != len )
if( len == 0 || (size_t)( buf[0] + 1 ) != len )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
}
list_size = buf[0];
p = buf + 1;
while( list_size > 0 )
@ -2117,7 +2117,7 @@ static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl,
size_t len_bytes = ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ? 0 : 2;
unsigned char *p = ssl->handshake->premaster + pms_offset;
if( offset + len_bytes > MBEDTLS_SSL_MAX_CONTENT_LEN )
if( offset + len_bytes > MBEDTLS_SSL_OUT_CONTENT_LEN )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small for encrypted pms" ) );
return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
@ -2160,7 +2160,7 @@ static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl,
if( ( ret = mbedtls_pk_encrypt( &ssl->session_negotiate->peer_cert->pk,
p, ssl->handshake->pmslen,
ssl->out_msg + offset + len_bytes, olen,
MBEDTLS_SSL_MAX_CONTENT_LEN - offset - len_bytes,
MBEDTLS_SSL_OUT_CONTENT_LEN - offset - len_bytes,
ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_rsa_pkcs1_encrypt", ret );
@ -2544,10 +2544,9 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
defined(MBEDTLS_SSL_PROTO_TLS1_2)
if( md_alg != MBEDTLS_MD_NONE )
{
/* Info from md_alg will be used instead */
hashlen = 0;
ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash, params,
params_len, md_alg );
ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash, &hashlen,
params, params_len,
md_alg );
if( ret != 0 )
return( ret );
}
@ -2559,8 +2558,7 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen != 0 ? hashlen :
(unsigned int) ( mbedtls_md_get_size( mbedtls_md_info_from_type( md_alg ) ) ) );
MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen );
if( ssl->session_negotiate->peer_cert == NULL )
{
@ -2711,7 +2709,7 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl )
* therefore the buffer length at this point must be greater than that
* regardless of the actual code path.
*/
if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n )
if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
@ -2928,7 +2926,7 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
i = 4;
n = ssl->conf->psk_identity_len;
if( i + 2 + n > MBEDTLS_SSL_MAX_CONTENT_LEN )
if( i + 2 + n > MBEDTLS_SSL_OUT_CONTENT_LEN )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "psk identity too long or "
"SSL buffer too short" ) );
@ -2964,7 +2962,7 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
*/
n = ssl->handshake->dhm_ctx.len;
if( i + 2 + n > MBEDTLS_SSL_MAX_CONTENT_LEN )
if( i + 2 + n > MBEDTLS_SSL_OUT_CONTENT_LEN )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "psk identity or DHM size too long"
" or SSL buffer too short" ) );
@ -2993,7 +2991,7 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
* ClientECDiffieHellmanPublic public;
*/
ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx, &n,
&ssl->out_msg[i], MBEDTLS_SSL_MAX_CONTENT_LEN - i,
&ssl->out_msg[i], MBEDTLS_SSL_OUT_CONTENT_LEN - i,
ssl->conf->f_rng, ssl->conf->p_rng );
if( ret != 0 )
{
@ -3034,7 +3032,7 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
i = 4;
ret = mbedtls_ecjpake_write_round_two( &ssl->handshake->ecjpake_ctx,
ssl->out_msg + i, MBEDTLS_SSL_MAX_CONTENT_LEN - i, &n,
ssl->out_msg + i, MBEDTLS_SSL_OUT_CONTENT_LEN - i, &n,
ssl->conf->f_rng, ssl->conf->p_rng );
if( ret != 0 )
{

View file

@ -91,6 +91,13 @@ static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl,
MBEDTLS_SSL_DEBUG_MSG( 3, ( "parse ServerName extension" ) );
if( len < 2 )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
servername_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) );
if( servername_list_size + 2 != len )
{
@ -101,7 +108,7 @@ static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl,
}
p = buf + 2;
while( servername_list_size > 0 )
while( servername_list_size > 2 )
{
hostname_len = ( ( p[1] << 8 ) | p[2] );
if( hostname_len + 3 > servername_list_size )
@ -205,6 +212,12 @@ static int ssl_parse_signature_algorithms_ext( mbedtls_ssl_context *ssl,
mbedtls_md_type_t md_cur;
mbedtls_pk_type_t sig_cur;
if ( len < 2 ) {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
sig_alg_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) );
if( sig_alg_list_size + 2 != len ||
sig_alg_list_size % 2 != 0 )
@ -273,6 +286,12 @@ static int ssl_parse_supported_elliptic_curves( mbedtls_ssl_context *ssl,
const unsigned char *p;
const mbedtls_ecp_curve_info *curve_info, **curves;
if ( len < 2 ) {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
list_size = ( ( buf[0] << 8 ) | ( buf[1] ) );
if( list_size + 2 != len ||
list_size % 2 != 0 )
@ -332,14 +351,14 @@ static int ssl_parse_supported_point_formats( mbedtls_ssl_context *ssl,
size_t list_size;
const unsigned char *p;
list_size = buf[0];
if( list_size + 1 != len )
if( len == 0 || (size_t)( buf[0] + 1 ) != len )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
list_size = buf[0];
p = buf + 1;
while( list_size > 0 )
@ -709,7 +728,7 @@ static int ssl_pick_cert( mbedtls_ssl_context *ssl,
MBEDTLS_SSL_DEBUG_CRT( 3, "candidate certificate chain, certificate",
cur->cert );
if( ! mbedtls_pk_can_do( cur->key, pk_alg ) )
if( ! mbedtls_pk_can_do( &cur->cert->pk, pk_alg ) )
{
MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: key type" ) );
continue;
@ -733,7 +752,7 @@ static int ssl_pick_cert( mbedtls_ssl_context *ssl,
#if defined(MBEDTLS_ECDSA_C)
if( pk_alg == MBEDTLS_PK_ECDSA &&
ssl_check_key_curve( cur->key, ssl->handshake->curves ) != 0 )
ssl_check_key_curve( &cur->cert->pk, ssl->handshake->curves ) != 0 )
{
MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: elliptic curve" ) );
continue;
@ -1303,7 +1322,7 @@ read_record_header:
else
#endif
{
if( msg_len > MBEDTLS_SSL_MAX_CONTENT_LEN )
if( msg_len > MBEDTLS_SSL_IN_CONTENT_LEN )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
@ -1656,10 +1675,16 @@ read_record_header:
while( ext_len != 0 )
{
unsigned int ext_id = ( ( ext[0] << 8 )
| ( ext[1] ) );
unsigned int ext_size = ( ( ext[2] << 8 )
| ( ext[3] ) );
unsigned int ext_id;
unsigned int ext_size;
if ( ext_len < 4 ) {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
ext_id = ( ( ext[0] << 8 ) | ( ext[1] ) );
ext_size = ( ( ext[2] << 8 ) | ( ext[3] ) );
if( ext_size + 4 > ext_len )
{
@ -2235,7 +2260,7 @@ static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl,
{
int ret;
unsigned char *p = buf;
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
size_t kkpp_len;
*olen = 0;
@ -2342,7 +2367,7 @@ static int ssl_write_hello_verify_request( mbedtls_ssl_context *ssl )
cookie_len_byte = p++;
if( ( ret = ssl->conf->f_cookie_write( ssl->conf->p_cookie,
&p, ssl->out_buf + MBEDTLS_SSL_BUFFER_LEN,
&p, ssl->out_buf + MBEDTLS_SSL_OUT_BUFFER_LEN,
ssl->cli_id, ssl->cli_id_len ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "f_cookie_write", ret );
@ -2638,7 +2663,7 @@ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl )
size_t dn_size, total_dn_size; /* excluding length bytes */
size_t ct_len, sa_len; /* including length bytes */
unsigned char *buf, *p;
const unsigned char * const end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
const unsigned char * const end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
const mbedtls_x509_crt *crt;
int authmode;
@ -2828,54 +2853,56 @@ static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl )
#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||
MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) && \
defined(MBEDTLS_SSL_ASYNC_PRIVATE)
static int ssl_resume_server_key_exchange( mbedtls_ssl_context *ssl,
size_t *signature_len )
{
/* Append the signature to ssl->out_msg, leaving 2 bytes for the
* signature length which will be added in ssl_write_server_key_exchange
* after the call to ssl_prepare_server_key_exchange.
* ssl_write_server_key_exchange also takes care of incrementing
* ssl->out_msglen. */
unsigned char *sig_start = ssl->out_msg + ssl->out_msglen + 2;
size_t sig_max_len = ( ssl->out_buf + MBEDTLS_SSL_OUT_CONTENT_LEN
- sig_start );
int ret = ssl->conf->f_async_resume( ssl,
sig_start, signature_len, sig_max_len );
if( ret != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS )
{
ssl->handshake->async_in_progress = 0;
mbedtls_ssl_set_async_operation_data( ssl, NULL );
}
MBEDTLS_SSL_DEBUG_RET( 2, "ssl_resume_server_key_exchange", ret );
return( ret );
}
#endif /* defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) &&
defined(MBEDTLS_SSL_ASYNC_PRIVATE) */
/* Prepare the ServerKeyExchange message, up to and including
* calculating the signature if any, but excluding formatting the
* signature and sending the message. */
static int ssl_prepare_server_key_exchange( mbedtls_ssl_context *ssl,
size_t *signature_len )
{
int ret;
size_t n = 0;
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
ssl->transform_negotiate->ciphersuite_info;
#if defined(MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED)
unsigned char *p = ssl->out_msg + 4;
size_t len;
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED)
unsigned char *dig_signed = p;
size_t dig_signed_len = 0;
unsigned char *dig_signed = NULL;
#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */
#endif /* MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED */
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) );
(void) ciphersuite_info; /* unused in some configurations */
#if !defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED)
(void) signature_len;
#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */
ssl->out_msglen = 4; /* header (type:1, length:3) to be written later */
/*
*
* Part 1: Extract static ECDH parameters and abort
* if ServerKeyExchange not needed.
*
*/
/* For suites involving ECDH, extract DH parameters
* from certificate at this point. */
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED)
if( mbedtls_ssl_ciphersuite_uses_ecdh( ciphersuite_info ) )
{
ssl_get_ecdh_params_from_cert( ssl );
}
#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED */
/* Key exchanges not involving ephemeral keys don't use
* ServerKeyExchange, so end here. */
#if defined(MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED)
if( mbedtls_ssl_ciphersuite_no_pfs( ciphersuite_info ) )
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) );
ssl->state++;
return( 0 );
}
#endif /* MBEDTLS_KEY_EXCHANGE__NON_PFS__ENABLED */
/*
*
* Part 2: Provide key exchange parameters for chosen ciphersuite.
* Part 1: Provide key exchange parameters for chosen ciphersuite.
*
*/
@ -2885,18 +2912,21 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
{
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
int ret;
size_t len = 0;
ret = mbedtls_ecjpake_write_round_two( &ssl->handshake->ecjpake_ctx,
p, end - p, &len, ssl->conf->f_rng, ssl->conf->p_rng );
ret = mbedtls_ecjpake_write_round_two(
&ssl->handshake->ecjpake_ctx,
ssl->out_msg + ssl->out_msglen,
MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen, &len,
ssl->conf->f_rng, ssl->conf->p_rng );
if( ret != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_write_round_two", ret );
return( ret );
}
p += len;
n += len;
ssl->out_msglen += len;
}
#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
@ -2910,10 +2940,8 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK )
{
*(p++) = 0x00;
*(p++) = 0x00;
n += 2;
ssl->out_msg[ssl->out_msglen++] = 0x00;
ssl->out_msg[ssl->out_msglen++] = 0x00;
}
#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED ||
MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
@ -2924,6 +2952,9 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED)
if( mbedtls_ssl_ciphersuite_uses_dhe( ciphersuite_info ) )
{
int ret;
size_t len = 0;
if( ssl->conf->dhm_P.p == NULL || ssl->conf->dhm_G.p == NULL )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "no DH parameters set" ) );
@ -2947,21 +2978,21 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
return( ret );
}
if( ( ret = mbedtls_dhm_make_params( &ssl->handshake->dhm_ctx,
(int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ),
p, &len, ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
if( ( ret = mbedtls_dhm_make_params(
&ssl->handshake->dhm_ctx,
(int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ),
ssl->out_msg + ssl->out_msglen, &len,
ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_params", ret );
return( ret );
}
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED)
dig_signed = p;
dig_signed_len = len;
dig_signed = ssl->out_msg + ssl->out_msglen;
#endif
p += len;
n += len;
ssl->out_msglen += len;
MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X );
MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P );
@ -2986,6 +3017,8 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
*/
const mbedtls_ecp_curve_info **curve = NULL;
const mbedtls_ecp_group_id *gid;
int ret;
size_t len = 0;
/* Match our preference list against the offered curves */
for( gid = ssl->conf->curve_list; *gid != MBEDTLS_ECP_DP_NONE; gid++ )
@ -3009,21 +3042,21 @@ curve_matching_done:
return( ret );
}
if( ( ret = mbedtls_ecdh_make_params( &ssl->handshake->ecdh_ctx, &len,
p, MBEDTLS_SSL_MAX_CONTENT_LEN - n,
ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
if( ( ret = mbedtls_ecdh_make_params(
&ssl->handshake->ecdh_ctx, &len,
ssl->out_msg + ssl->out_msglen,
MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen,
ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_params", ret );
return( ret );
}
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED)
dig_signed = p;
dig_signed_len = len;
dig_signed = ssl->out_msg + ssl->out_msglen;
#endif
p += len;
n += len;
ssl->out_msglen += len;
MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q ", &ssl->handshake->ecdh_ctx.Q );
}
@ -3031,19 +3064,20 @@ curve_matching_done:
/*
*
* Part 3: For key exchanges involving the server signing the
* Part 2: For key exchanges involving the server signing the
* exchange parameters, compute and add the signature here.
*
*/
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED)
if( mbedtls_ssl_ciphersuite_uses_server_signature( ciphersuite_info ) )
{
size_t signature_len = 0;
unsigned int hashlen = 0;
unsigned char hash[64];
size_t dig_signed_len = ssl->out_msg + ssl->out_msglen - dig_signed;
size_t hashlen = 0;
unsigned char hash[MBEDTLS_MD_MAX_SIZE];
int ret;
/*
* 3.1: Choose hash algorithm:
* 2.1: Choose hash algorithm:
* A: For TLS 1.2, obey signature-hash-algorithm extension
* to choose appropriate hash.
* B: For SSL3, TLS1.0, TLS1.1 and ECDHE_ECDSA, use SHA1
@ -3090,7 +3124,7 @@ curve_matching_done:
MBEDTLS_SSL_DEBUG_MSG( 3, ( "pick hash algorithm %d for signing", md_alg ) );
/*
* 3.2: Compute the hash to be signed
* 2.2: Compute the hash to be signed
*/
#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
defined(MBEDTLS_SSL_PROTO_TLS1_1)
@ -3110,9 +3144,7 @@ curve_matching_done:
defined(MBEDTLS_SSL_PROTO_TLS1_2)
if( md_alg != MBEDTLS_MD_NONE )
{
/* Info from md_alg will be used instead */
hashlen = 0;
ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash,
ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash, &hashlen,
dig_signed,
dig_signed_len,
md_alg );
@ -3127,18 +3159,11 @@ curve_matching_done:
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen != 0 ? hashlen :
(unsigned int) ( mbedtls_md_get_size( mbedtls_md_info_from_type( md_alg ) ) ) );
MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen );
/*
* 3.3: Compute and add the signature
* 2.3: Compute and add the signature
*/
if( mbedtls_ssl_own_key( ssl ) == NULL )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key" ) );
return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED );
}
#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
{
@ -3158,33 +3183,150 @@ curve_matching_done:
*
*/
*(p++) = mbedtls_ssl_hash_from_md_alg( md_alg );
*(p++) = mbedtls_ssl_sig_from_pk_alg( sig_alg );
n += 2;
ssl->out_msg[ssl->out_msglen++] =
mbedtls_ssl_hash_from_md_alg( md_alg );
ssl->out_msg[ssl->out_msglen++] =
mbedtls_ssl_sig_from_pk_alg( sig_alg );
}
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ), md_alg, hash, hashlen,
p + 2 , &signature_len, ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
if( ssl->conf->f_async_sign_start != NULL )
{
ret = ssl->conf->f_async_sign_start( ssl,
mbedtls_ssl_own_cert( ssl ),
md_alg, hash, hashlen );
switch( ret )
{
case MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH:
/* act as if f_async_sign was null */
break;
case 0:
ssl->handshake->async_in_progress = 1;
return( ssl_resume_server_key_exchange( ssl, signature_len ) );
case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS:
ssl->handshake->async_in_progress = 1;
return( MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS );
default:
MBEDTLS_SSL_DEBUG_RET( 1, "f_async_sign_start", ret );
return( ret );
}
}
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
if( mbedtls_ssl_own_key( ssl ) == NULL )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key" ) );
return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED );
}
/* Append the signature to ssl->out_msg, leaving 2 bytes for the
* signature length which will be added in ssl_write_server_key_exchange
* after the call to ssl_prepare_server_key_exchange.
* ssl_write_server_key_exchange also takes care of incrementing
* ssl->out_msglen. */
if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ),
md_alg, hash, hashlen,
ssl->out_msg + ssl->out_msglen + 2,
signature_len,
ssl->conf->f_rng,
ssl->conf->p_rng ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret );
return( ret );
}
*(p++) = (unsigned char)( signature_len >> 8 );
*(p++) = (unsigned char)( signature_len );
n += 2;
MBEDTLS_SSL_DEBUG_BUF( 3, "my signature", p, signature_len );
n += signature_len;
}
#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */
/* Done with actual work; add header and send. */
return( 0 );
}
ssl->out_msglen = 4 + n;
/* Prepare the ServerKeyExchange message and send it. For ciphersuites
* that do not include a ServerKeyExchange message, do nothing. Either
* way, if successful, move on to the next step in the SSL state
* machine. */
static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
{
int ret;
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;
#endif /* MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED */
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) );
#if defined(MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED)
/* Extract static ECDH parameters and abort if ServerKeyExchange
* is not needed. */
if( mbedtls_ssl_ciphersuite_no_pfs( ciphersuite_info ) )
{
/* For suites involving ECDH, extract DH parameters
* from certificate at this point. */
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED)
if( mbedtls_ssl_ciphersuite_uses_ecdh( ciphersuite_info ) )
{
ssl_get_ecdh_params_from_cert( ssl );
}
#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED */
/* Key exchanges not involving ephemeral keys don't use
* ServerKeyExchange, so end here. */
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) );
ssl->state++;
return( 0 );
}
#endif /* MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED */
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) && \
defined(MBEDTLS_SSL_ASYNC_PRIVATE)
/* If we have already prepared the message and there is an ongoing
* signature operation, resume signing. */
if( ssl->handshake->async_in_progress != 0 )
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "resuming signature operation" ) );
ret = ssl_resume_server_key_exchange( ssl, &signature_len );
}
else
#endif /* defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) &&
defined(MBEDTLS_SSL_ASYNC_PRIVATE) */
{
/* ServerKeyExchange is needed. Prepare the message. */
ret = ssl_prepare_server_key_exchange( ssl, &signature_len );
}
if( ret != 0 )
{
/* If we're starting to write a new message, set ssl->out_msglen
* to 0. But if we're resuming after an asynchronous message,
* out_msglen is the amount of data written so far and mst be
* preserved. */
if( ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS )
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server key exchange (pending)" ) );
else
ssl->out_msglen = 0;
return( ret );
}
/* If there is a signature, write its length.
* ssl_prepare_server_key_exchange already wrote the signature
* itself at its proper place in the output buffer. */
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED)
if( signature_len != 0 )
{
ssl->out_msg[ssl->out_msglen++] = (unsigned char)( signature_len >> 8 );
ssl->out_msg[ssl->out_msglen++] = (unsigned char)( signature_len );
MBEDTLS_SSL_DEBUG_BUF( 3, "my signature",
ssl->out_msg + ssl->out_msglen,
signature_len );
/* Skip over the already-written signature */
ssl->out_msglen += signature_len;
}
#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */
/* Add header and send. */
ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE;
@ -3197,7 +3339,6 @@ curve_matching_done:
}
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server key exchange" ) );
return( 0 );
}
@ -3272,33 +3413,59 @@ static int ssl_parse_client_dh_public( mbedtls_ssl_context *ssl, unsigned char *
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl,
const unsigned char *p,
const unsigned char *end,
size_t pms_offset )
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
static int ssl_resume_decrypt_pms( mbedtls_ssl_context *ssl,
unsigned char *peer_pms,
size_t *peer_pmslen,
size_t peer_pmssize )
{
int ret = ssl->conf->f_async_resume( ssl,
peer_pms, peer_pmslen, peer_pmssize );
if( ret != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS )
{
ssl->handshake->async_in_progress = 0;
mbedtls_ssl_set_async_operation_data( ssl, NULL );
}
MBEDTLS_SSL_DEBUG_RET( 2, "ssl_decrypt_encrypted_pms", ret );
return( ret );
}
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
static int ssl_decrypt_encrypted_pms( mbedtls_ssl_context *ssl,
const unsigned char *p,
const unsigned char *end,
unsigned char *peer_pms,
size_t *peer_pmslen,
size_t peer_pmssize )
{
int ret;
size_t len = mbedtls_pk_get_len( mbedtls_ssl_own_key( ssl ) );
unsigned char *pms = ssl->handshake->premaster + pms_offset;
unsigned char ver[2];
unsigned char fake_pms[48], peer_pms[48];
unsigned char mask;
size_t i, peer_pmslen;
unsigned int diff;
mbedtls_pk_context *private_key = mbedtls_ssl_own_key( ssl );
mbedtls_pk_context *public_key = &mbedtls_ssl_own_cert( ssl )->pk;
size_t len = mbedtls_pk_get_len( public_key );
if( ! mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_RSA ) )
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
/* If we have already started decoding the message and there is an ongoing
* decryption operation, resume signing. */
if( ssl->handshake->async_in_progress != 0 )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no RSA private key" ) );
return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED );
MBEDTLS_SSL_DEBUG_MSG( 2, ( "resuming decryption operation" ) );
return( ssl_resume_decrypt_pms( ssl,
peer_pms, peer_pmslen, peer_pmssize ) );
}
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
/*
* Decrypt the premaster using own private RSA key
* Prepare to decrypt the premaster using own private RSA key
*/
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
defined(MBEDTLS_SSL_PROTO_TLS1_2)
if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 )
{
if ( p + 2 > end ) {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
}
if( *p++ != ( ( len >> 8 ) & 0xFF ) ||
*p++ != ( ( len ) & 0xFF ) )
{
@ -3314,30 +3481,120 @@ static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl,
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
}
/*
* Decrypt the premaster secret
*/
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
if( ssl->conf->f_async_decrypt_start != NULL )
{
ret = ssl->conf->f_async_decrypt_start( ssl,
mbedtls_ssl_own_cert( ssl ),
p, len );
switch( ret )
{
case MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH:
/* act as if f_async_decrypt_start was null */
break;
case 0:
ssl->handshake->async_in_progress = 1;
return( ssl_resume_decrypt_pms( ssl,
peer_pms,
peer_pmslen,
peer_pmssize ) );
case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS:
ssl->handshake->async_in_progress = 1;
return( MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS );
default:
MBEDTLS_SSL_DEBUG_RET( 1, "f_async_decrypt_start", ret );
return( ret );
}
}
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
if( ! mbedtls_pk_can_do( private_key, MBEDTLS_PK_RSA ) )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no RSA private key" ) );
return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED );
}
ret = mbedtls_pk_decrypt( private_key, p, len,
peer_pms, peer_pmslen, peer_pmssize,
ssl->conf->f_rng, ssl->conf->p_rng );
return( ret );
}
static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl,
const unsigned char *p,
const unsigned char *end,
size_t pms_offset )
{
int ret;
unsigned char *pms = ssl->handshake->premaster + pms_offset;
unsigned char ver[2];
unsigned char fake_pms[48], peer_pms[48];
unsigned char mask;
size_t i, peer_pmslen;
unsigned int diff;
/* In case of a failure in decryption, the decryption may write less than
* 2 bytes of output, but we always read the first two bytes. It doesn't
* matter in the end because diff will be nonzero in that case due to
* peer_pmslen being less than 48, and we only care whether diff is 0.
* But do initialize peer_pms for robustness anyway. This also makes
* memory analyzers happy (don't access uninitialized memory, even
* if it's an unsigned char). */
peer_pms[0] = peer_pms[1] = ~0;
ret = ssl_decrypt_encrypted_pms( ssl, p, end,
peer_pms,
&peer_pmslen,
sizeof( peer_pms ) );
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
if ( ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS )
return( ret );
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
mbedtls_ssl_write_version( ssl->handshake->max_major_ver,
ssl->handshake->max_minor_ver,
ssl->conf->transport, ver );
ssl->handshake->max_minor_ver,
ssl->conf->transport, ver );
/* Avoid data-dependent branches while checking for invalid
* padding, to protect against timing-based Bleichenbacher-type
* attacks. */
diff = (unsigned int) ret;
diff |= peer_pmslen ^ 48;
diff |= peer_pms[0] ^ ver[0];
diff |= peer_pms[1] ^ ver[1];
/* mask = diff ? 0xff : 0x00 using bit operations to avoid branches */
/* MSVC has a warning about unary minus on unsigned, but this is
* well-defined and precisely what we want to do here */
#if defined(_MSC_VER)
#pragma warning( push )
#pragma warning( disable : 4146 )
#endif
mask = - ( ( diff | - diff ) >> ( sizeof( unsigned int ) * 8 - 1 ) );
#if defined(_MSC_VER)
#pragma warning( pop )
#endif
/*
* Protection against Bleichenbacher's attack: invalid PKCS#1 v1.5 padding
* must not cause the connection to end immediately; instead, send a
* bad_record_mac later in the handshake.
* Also, avoid data-dependant branches here to protect against
* timing-based variants.
* To protect against timing-based variants of the attack, we must
* not have any branch that depends on whether the decryption was
* successful. In particular, always generate the fake premaster secret,
* regardless of whether it will ultimately influence the output or not.
*/
ret = ssl->conf->f_rng( ssl->conf->p_rng, fake_pms, sizeof( fake_pms ) );
if( ret != 0 )
{
/* It's ok to abort on an RNG failure, since this does not reveal
* anything about the RSA decryption. */
return( ret );
ret = mbedtls_pk_decrypt( mbedtls_ssl_own_key( ssl ), p, len,
peer_pms, &peer_pmslen,
sizeof( peer_pms ),
ssl->conf->f_rng, ssl->conf->p_rng );
diff = (unsigned int) ret;
diff |= peer_pmslen ^ 48;
diff |= peer_pms[0] ^ ver[0];
diff |= peer_pms[1] ^ ver[1];
}
#if defined(MBEDTLS_SSL_DEBUG_ALL)
if( diff != 0 )
@ -3352,18 +3609,8 @@ static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl,
}
ssl->handshake->pmslen = 48;
/* mask = diff ? 0xff : 0x00 using bit operations to avoid branches */
/* MSVC has a warning about unary minus on unsigned, but this is
* well-defined and precisely what we want to do here */
#if defined(_MSC_VER)
#pragma warning( push )
#pragma warning( disable : 4146 )
#endif
mask = - ( ( diff | - diff ) >> ( sizeof( unsigned int ) * 8 - 1 ) );
#if defined(_MSC_VER)
#pragma warning( pop )
#endif
/* Set pms to either the true or the fake PMS, without
* data-dependent branches. */
for( i = 0; i < ssl->handshake->pmslen; i++ )
pms[i] = ( mask & fake_pms[i] ) | ( (~mask) & peer_pms[i] );
@ -3445,6 +3692,20 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client key exchange" ) );
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) && \
( defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) )
if( ( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) &&
( ssl->handshake->async_in_progress != 0 ) )
{
/* We've already read a record and there is an asynchronous
* operation in progress to decrypt it. So skip reading the
* record. */
MBEDTLS_SSL_DEBUG_MSG( 3, ( "will resume decryption of previously-read record" ) );
}
else
#endif
if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
@ -3557,6 +3818,19 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK )
{
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
if ( ssl->handshake->async_in_progress != 0 )
{
/* There is an asynchronous operation in progress to
* decrypt the encrypted premaster secret, so skip
* directly to resuming this operation. */
MBEDTLS_SSL_DEBUG_MSG( 3, ( "PSK identity already parsed" ) );
/* Update p to skip the PSK identity. ssl_parse_encrypted_pms
* won't actually use it, but maintain p anyway for robustness. */
p += ssl->conf->psk_identity_len + 2;
}
else
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret );
@ -3926,7 +4200,7 @@ static int ssl_write_new_session_ticket( mbedtls_ssl_context *ssl )
if( ( ret = ssl->conf->f_ticket_write( ssl->conf->p_ticket,
ssl->session_negotiate,
ssl->out_msg + 10,
ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN,
ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN,
&tlen, &lifetime ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_ticket_write", ret );

View file

@ -141,14 +141,24 @@ static void ssl_reset_retransmit_timeout( mbedtls_ssl_context *ssl )
* } MaxFragmentLength;
* and we add 0 -> extension unused
*/
static unsigned int mfl_code_to_length[MBEDTLS_SSL_MAX_FRAG_LEN_INVALID] =
static unsigned int ssl_mfl_code_to_length( int mfl )
{
MBEDTLS_SSL_MAX_CONTENT_LEN, /* MBEDTLS_SSL_MAX_FRAG_LEN_NONE */
512, /* MBEDTLS_SSL_MAX_FRAG_LEN_512 */
1024, /* MBEDTLS_SSL_MAX_FRAG_LEN_1024 */
2048, /* MBEDTLS_SSL_MAX_FRAG_LEN_2048 */
4096, /* MBEDTLS_SSL_MAX_FRAG_LEN_4096 */
};
switch( mfl )
{
case MBEDTLS_SSL_MAX_FRAG_LEN_NONE:
return ( MBEDTLS_TLS_EXT_ADV_CONTENT_LEN );
case MBEDTLS_SSL_MAX_FRAG_LEN_512:
return 512;
case MBEDTLS_SSL_MAX_FRAG_LEN_1024:
return 1024;
case MBEDTLS_SSL_MAX_FRAG_LEN_2048:
return 2048;
case MBEDTLS_SSL_MAX_FRAG_LEN_4096:
return 4096;
default:
return ( MBEDTLS_TLS_EXT_ADV_CONTENT_LEN );
}
}
#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
#if defined(MBEDTLS_SSL_CLI_C)
@ -688,18 +698,32 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl )
transform->keylen = cipher_info->key_bitlen / 8;
if( cipher_info->mode == MBEDTLS_MODE_GCM ||
cipher_info->mode == MBEDTLS_MODE_CCM )
cipher_info->mode == MBEDTLS_MODE_CCM ||
cipher_info->mode == MBEDTLS_MODE_CHACHAPOLY )
{
size_t taglen, explicit_ivlen;
transform->maclen = 0;
mac_key_len = 0;
/* All modes haves 96-bit IVs;
* GCM and CCM has 4 implicit and 8 explicit bytes
* ChachaPoly has all 12 bytes implicit
*/
transform->ivlen = 12;
transform->fixed_ivlen = 4;
if( cipher_info->mode == MBEDTLS_MODE_CHACHAPOLY )
transform->fixed_ivlen = 12;
else
transform->fixed_ivlen = 4;
/* Minimum length is expicit IV + tag */
transform->minlen = transform->ivlen - transform->fixed_ivlen
+ ( transform->ciphersuite_info->flags &
MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16 );
/* All modes have 128-bit tags, except CCM_8 (ciphersuite flag) */
taglen = transform->ciphersuite_info->flags &
MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16;
/* Minimum length of encrypted record */
explicit_ivlen = transform->ivlen - transform->fixed_ivlen;
transform->minlen = explicit_ivlen + taglen;
}
else
{
@ -956,11 +980,11 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl )
if( ssl->compress_buf == NULL )
{
MBEDTLS_SSL_DEBUG_MSG( 3, ( "Allocating compression buffer" ) );
ssl->compress_buf = mbedtls_calloc( 1, MBEDTLS_SSL_BUFFER_LEN );
ssl->compress_buf = mbedtls_calloc( 1, MBEDTLS_SSL_COMPRESS_BUFFER_LEN );
if( ssl->compress_buf == NULL )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed",
MBEDTLS_SSL_BUFFER_LEN ) );
MBEDTLS_SSL_COMPRESS_BUFFER_LEN ) );
return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
}
}
@ -1151,6 +1175,9 @@ int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exch
* other_secret already set by the ClientKeyExchange message,
* and is 48 bytes long
*/
if( end - p < 2 )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
*p++ = 0;
*p++ = 48;
p += 48;
@ -1276,6 +1303,27 @@ static void ssl_mac( mbedtls_md_context_t *md_ctx,
#define SSL_SOME_MODES_USE_MAC
#endif
/* The function below is only used in the Lucky 13 counter-measure in
* ssl_decrypt_buf(). These are the defines that guard the call site. */
#if defined(SSL_SOME_MODES_USE_MAC) && \
( defined(MBEDTLS_SSL_PROTO_TLS1) || \
defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
defined(MBEDTLS_SSL_PROTO_TLS1_2) )
/* This function makes sure every byte in the memory region is accessed
* (in ascending addresses order) */
static void ssl_read_memory( unsigned char *p, size_t len )
{
unsigned char acc = 0;
volatile unsigned char force;
for( ; len != 0; p++, len-- )
acc ^= *p;
force = acc;
(void) force;
}
#endif /* SSL_SOME_MODES_USE_MAC && ( TLS1 || TLS1_1 || TLS1_2 ) */
/*
* Encryption/decryption functions
*/
@ -1297,11 +1345,11 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_BUF( 4, "before encrypt: output payload",
ssl->out_msg, ssl->out_msglen );
if( ssl->out_msglen > MBEDTLS_SSL_MAX_CONTENT_LEN )
if( ssl->out_msglen > MBEDTLS_SSL_OUT_CONTENT_LEN )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record content %u too large, maximum %d",
(unsigned) ssl->out_msglen,
MBEDTLS_SSL_MAX_CONTENT_LEN ) );
MBEDTLS_SSL_OUT_CONTENT_LEN ) );
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
}
@ -1394,17 +1442,26 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl )
}
else
#endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */
#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C)
#if defined(MBEDTLS_GCM_C) || \
defined(MBEDTLS_CCM_C) || \
defined(MBEDTLS_CHACHAPOLY_C)
if( mode == MBEDTLS_MODE_GCM ||
mode == MBEDTLS_MODE_CCM )
mode == MBEDTLS_MODE_CCM ||
mode == MBEDTLS_MODE_CHACHAPOLY )
{
int ret;
size_t enc_msglen, olen;
unsigned char *enc_msg;
unsigned char add_data[13];
unsigned char taglen = ssl->transform_out->ciphersuite_info->flags &
unsigned char iv[12];
mbedtls_ssl_transform *transform = ssl->transform_out;
unsigned char taglen = transform->ciphersuite_info->flags &
MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16;
size_t explicit_ivlen = transform->ivlen - transform->fixed_ivlen;
/*
* Prepare additional authenticated data
*/
memcpy( add_data, ssl->out_ctr, 8 );
add_data[8] = ssl->out_msgtype;
mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver,
@ -1412,44 +1469,57 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl )
add_data[11] = ( ssl->out_msglen >> 8 ) & 0xFF;
add_data[12] = ssl->out_msglen & 0xFF;
MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD",
add_data, 13 );
MBEDTLS_SSL_DEBUG_BUF( 4, "additional data for AEAD", add_data, 13 );
/*
* Generate IV
*/
if( ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen != 8 )
if( transform->ivlen == 12 && transform->fixed_ivlen == 4 )
{
/* GCM and CCM: fixed || explicit (=seqnum) */
memcpy( iv, transform->iv_enc, transform->fixed_ivlen );
memcpy( iv + transform->fixed_ivlen, ssl->out_ctr, 8 );
memcpy( ssl->out_iv, ssl->out_ctr, 8 );
}
else if( transform->ivlen == 12 && transform->fixed_ivlen == 12 )
{
/* ChachaPoly: fixed XOR sequence number */
unsigned char i;
memcpy( iv, transform->iv_enc, transform->fixed_ivlen );
for( i = 0; i < 8; i++ )
iv[i+4] ^= ssl->out_ctr[i];
}
else
{
/* Reminder if we ever add an AEAD mode with a different size */
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
memcpy( ssl->transform_out->iv_enc + ssl->transform_out->fixed_ivlen,
ssl->out_ctr, 8 );
memcpy( ssl->out_iv, ssl->out_ctr, 8 );
MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", ssl->out_iv,
ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen );
MBEDTLS_SSL_DEBUG_BUF( 4, "IV used (internal)",
iv, transform->ivlen );
MBEDTLS_SSL_DEBUG_BUF( 4, "IV used (transmitted)",
ssl->out_iv, explicit_ivlen );
/*
* Fix pointer positions and message length with added IV
* Fix message length with added IV
*/
enc_msg = ssl->out_msg;
enc_msglen = ssl->out_msglen;
ssl->out_msglen += ssl->transform_out->ivlen -
ssl->transform_out->fixed_ivlen;
ssl->out_msglen += explicit_ivlen;
MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, "
"including %d bytes of padding",
ssl->out_msglen, 0 ) );
"including 0 bytes of padding",
ssl->out_msglen ) );
/*
* Encrypt and authenticate
*/
if( ( ret = mbedtls_cipher_auth_encrypt( &ssl->transform_out->cipher_ctx_enc,
ssl->transform_out->iv_enc,
ssl->transform_out->ivlen,
if( ( ret = mbedtls_cipher_auth_encrypt( &transform->cipher_ctx_enc,
iv, transform->ivlen,
add_data, 13,
enc_msg, enc_msglen,
enc_msg, &olen,
@ -1609,7 +1679,6 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl )
static int ssl_decrypt_buf( mbedtls_ssl_context *ssl )
{
size_t i;
mbedtls_cipher_mode_t mode;
int auth_done = 0;
#if defined(SSL_SOME_MODES_USE_MAC)
@ -1659,20 +1728,27 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl )
}
else
#endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */
#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C)
#if defined(MBEDTLS_GCM_C) || \
defined(MBEDTLS_CCM_C) || \
defined(MBEDTLS_CHACHAPOLY_C)
if( mode == MBEDTLS_MODE_GCM ||
mode == MBEDTLS_MODE_CCM )
mode == MBEDTLS_MODE_CCM ||
mode == MBEDTLS_MODE_CHACHAPOLY )
{
int ret;
size_t dec_msglen, olen;
unsigned char *dec_msg;
unsigned char *dec_msg_result;
unsigned char add_data[13];
unsigned char taglen = ssl->transform_in->ciphersuite_info->flags &
unsigned char iv[12];
mbedtls_ssl_transform *transform = ssl->transform_in;
unsigned char taglen = transform->ciphersuite_info->flags &
MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16;
size_t explicit_iv_len = ssl->transform_in->ivlen -
ssl->transform_in->fixed_ivlen;
size_t explicit_iv_len = transform->ivlen - transform->fixed_ivlen;
/*
* Compute and update sizes
*/
if( ssl->in_msglen < explicit_iv_len + taglen )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < explicit_iv_len (%d) "
@ -1686,6 +1762,9 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl )
dec_msg_result = ssl->in_msg;
ssl->in_msglen = dec_msglen;
/*
* Prepare additional authenticated data
*/
memcpy( add_data, ssl->in_ctr, 8 );
add_data[8] = ssl->in_msgtype;
mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver,
@ -1693,23 +1772,43 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl )
add_data[11] = ( ssl->in_msglen >> 8 ) & 0xFF;
add_data[12] = ssl->in_msglen & 0xFF;
MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD",
add_data, 13 );
MBEDTLS_SSL_DEBUG_BUF( 4, "additional data for AEAD", add_data, 13 );
memcpy( ssl->transform_in->iv_dec + ssl->transform_in->fixed_ivlen,
ssl->in_iv,
ssl->transform_in->ivlen - ssl->transform_in->fixed_ivlen );
/*
* Prepare IV
*/
if( transform->ivlen == 12 && transform->fixed_ivlen == 4 )
{
/* GCM and CCM: fixed || explicit (transmitted) */
memcpy( iv, transform->iv_dec, transform->fixed_ivlen );
memcpy( iv + transform->fixed_ivlen, ssl->in_iv, 8 );
MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", ssl->transform_in->iv_dec,
ssl->transform_in->ivlen );
}
else if( transform->ivlen == 12 && transform->fixed_ivlen == 12 )
{
/* ChachaPoly: fixed XOR sequence number */
unsigned char i;
memcpy( iv, transform->iv_dec, transform->fixed_ivlen );
for( i = 0; i < 8; i++ )
iv[i+4] ^= ssl->in_ctr[i];
}
else
{
/* Reminder if we ever add an AEAD mode with a different size */
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", iv, transform->ivlen );
MBEDTLS_SSL_DEBUG_BUF( 4, "TAG used", dec_msg + dec_msglen, taglen );
/*
* Decrypt and authenticate
*/
if( ( ret = mbedtls_cipher_auth_decrypt( &ssl->transform_in->cipher_ctx_dec,
ssl->transform_in->iv_dec,
ssl->transform_in->ivlen,
iv, transform->ivlen,
add_data, 13,
dec_msg, dec_msglen,
dec_msg_result, &olen,
@ -1827,6 +1926,7 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl )
*/
if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
{
unsigned char i;
dec_msglen -= ssl->transform_in->ivlen;
ssl->in_msglen -= ssl->transform_in->ivlen;
@ -1900,27 +2000,28 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl )
* and fake check up to 256 bytes of padding
*/
size_t pad_count = 0, real_count = 1;
size_t padding_idx = ssl->in_msglen - padlen - 1;
size_t padding_idx = ssl->in_msglen - padlen;
size_t i;
/*
* Padding is guaranteed to be incorrect if:
* 1. padlen >= ssl->in_msglen
* 1. padlen > ssl->in_msglen
*
* 2. padding_idx >= MBEDTLS_SSL_MAX_CONTENT_LEN +
* 2. padding_idx > MBEDTLS_SSL_IN_CONTENT_LEN +
* ssl->transform_in->maclen
*
* In both cases we reset padding_idx to a safe value (0) to
* prevent out-of-buffer reads.
*/
correct &= ( ssl->in_msglen >= padlen + 1 );
correct &= ( padding_idx < MBEDTLS_SSL_MAX_CONTENT_LEN +
correct &= ( padlen <= ssl->in_msglen );
correct &= ( padding_idx <= MBEDTLS_SSL_IN_CONTENT_LEN +
ssl->transform_in->maclen );
padding_idx *= correct;
for( i = 1; i <= 256; i++ )
for( i = 0; i < 256; i++ )
{
real_count &= ( i <= padlen );
real_count &= ( i < padlen );
pad_count += real_count *
( ssl->in_msg[padding_idx + i] == padlen - 1 );
}
@ -1951,8 +2052,10 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
#if defined(MBEDTLS_SSL_DEBUG_ALL)
MBEDTLS_SSL_DEBUG_BUF( 4, "raw buffer after decryption",
ssl->in_msg, ssl->in_msglen );
#endif
/*
* Authenticate if not done yet.
@ -1985,20 +2088,69 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl )
{
/*
* Process MAC and always update for padlen afterwards to make
* total time independent of padlen
*
* extra_run compensates MAC check for padlen
* total time independent of padlen.
*
* Known timing attacks:
* - Lucky Thirteen (http://www.isg.rhul.ac.uk/tls/TLStiming.pdf)
*
* We use ( ( Lx + 8 ) / 64 ) to handle 'negative Lx' values
* correctly. (We round down instead of up, so -56 is the correct
* value for our calculations instead of -55)
* To compensate for different timings for the MAC calculation
* depending on how much padding was removed (which is determined
* by padlen), process extra_run more blocks through the hash
* function.
*
* The formula in the paper is
* extra_run = ceil( (L1-55) / 64 ) - ceil( (L2-55) / 64 )
* where L1 is the size of the header plus the decrypted message
* plus CBC padding and L2 is the size of the header plus the
* decrypted message. This is for an underlying hash function
* with 64-byte blocks.
* We use ( (Lx+8) / 64 ) to handle 'negative Lx' values
* correctly. We round down instead of up, so -56 is the correct
* value for our calculations instead of -55.
*
* Repeat the formula rather than defining a block_size variable.
* This avoids requiring division by a variable at runtime
* (which would be marginally less efficient and would require
* linking an extra division function in some builds).
*/
size_t j, extra_run = 0;
extra_run = ( 13 + ssl->in_msglen + padlen + 8 ) / 64 -
( 13 + ssl->in_msglen + 8 ) / 64;
/*
* The next two sizes are the minimum and maximum values of
* in_msglen over all padlen values.
*
* They're independent of padlen, since we previously did
* in_msglen -= padlen.
*
* Note that max_len + maclen is never more than the buffer
* length, as we previously did in_msglen -= maclen too.
*/
const size_t max_len = ssl->in_msglen + padlen;
const size_t min_len = ( max_len > 256 ) ? max_len - 256 : 0;
switch( ssl->transform_in->ciphersuite_info->mac )
{
#if defined(MBEDTLS_MD5_C) || defined(MBEDTLS_SHA1_C) || \
defined(MBEDTLS_SHA256_C)
case MBEDTLS_MD_MD5:
case MBEDTLS_MD_SHA1:
case MBEDTLS_MD_SHA256:
/* 8 bytes of message size, 64-byte compression blocks */
extra_run = ( 13 + ssl->in_msglen + padlen + 8 ) / 64 -
( 13 + ssl->in_msglen + 8 ) / 64;
break;
#endif
#if defined(MBEDTLS_SHA512_C)
case MBEDTLS_MD_SHA384:
/* 16 bytes of message size, 128-byte compression blocks */
extra_run = ( 13 + ssl->in_msglen + padlen + 16 ) / 128 -
( 13 + ssl->in_msglen + 16 ) / 128;
break;
#endif
default:
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
extra_run &= correct * 0xFF;
@ -2007,12 +2159,25 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl )
mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_len, 2 );
mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_msg,
ssl->in_msglen );
/* Make sure we access everything even when padlen > 0. This
* makes the synchronisation requirements for just-in-time
* Prime+Probe attacks much tighter and hopefully impractical. */
ssl_read_memory( ssl->in_msg + ssl->in_msglen, padlen );
mbedtls_md_hmac_finish( &ssl->transform_in->md_ctx_dec, mac_expect );
/* Call mbedtls_md_process at least once due to cache attacks */
/* Call mbedtls_md_process at least once due to cache attacks
* that observe whether md_process() was called of not */
for( j = 0; j < extra_run + 1; j++ )
mbedtls_md_process( &ssl->transform_in->md_ctx_dec, ssl->in_msg );
mbedtls_md_hmac_reset( &ssl->transform_in->md_ctx_dec );
/* Make sure we access all the memory that could contain the MAC,
* before we check it in the next code block. This makes the
* synchronisation requirements for just-in-time Prime+Probe
* attacks much tighter and hopefully impractical. */
ssl_read_memory( ssl->in_msg + min_len,
max_len - min_len + ssl->transform_in->maclen );
}
else
#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \
@ -2022,9 +2187,11 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
#if defined(MBEDTLS_SSL_DEBUG_ALL)
MBEDTLS_SSL_DEBUG_BUF( 4, "expected mac", mac_expect, ssl->transform_in->maclen );
MBEDTLS_SSL_DEBUG_BUF( 4, "message mac", ssl->in_msg + ssl->in_msglen,
ssl->transform_in->maclen );
#endif
if( mbedtls_ssl_safer_memcmp( ssl->in_msg + ssl->in_msglen, mac_expect,
ssl->transform_in->maclen ) != 0 )
@ -2053,6 +2220,16 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl )
if( ssl->in_msglen == 0 )
{
#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3
&& ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA )
{
/* TLS v1.2 explicitly disallows zero-length messages which are not application data */
MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid zero-length message type: %d", ssl->in_msgtype ) );
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
}
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
ssl->nb_zero++;
/*
@ -2077,6 +2254,7 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl )
else
#endif
{
unsigned char i;
for( i = 8; i > ssl_ep_len( ssl ); i-- )
if( ++ssl->in_ctr[i - 1] != 0 )
break;
@ -2126,7 +2304,7 @@ static int ssl_compress_buf( mbedtls_ssl_context *ssl )
ssl->transform_out->ctx_deflate.next_in = msg_pre;
ssl->transform_out->ctx_deflate.avail_in = len_pre;
ssl->transform_out->ctx_deflate.next_out = msg_post;
ssl->transform_out->ctx_deflate.avail_out = MBEDTLS_SSL_BUFFER_LEN - bytes_written;
ssl->transform_out->ctx_deflate.avail_out = MBEDTLS_SSL_OUT_BUFFER_LEN - bytes_written;
ret = deflate( &ssl->transform_out->ctx_deflate, Z_SYNC_FLUSH );
if( ret != Z_OK )
@ -2135,7 +2313,7 @@ static int ssl_compress_buf( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED );
}
ssl->out_msglen = MBEDTLS_SSL_BUFFER_LEN -
ssl->out_msglen = MBEDTLS_SSL_OUT_BUFFER_LEN -
ssl->transform_out->ctx_deflate.avail_out - bytes_written;
MBEDTLS_SSL_DEBUG_MSG( 3, ( "after compression: msglen = %d, ",
@ -2173,7 +2351,7 @@ static int ssl_decompress_buf( mbedtls_ssl_context *ssl )
ssl->transform_in->ctx_inflate.next_in = msg_pre;
ssl->transform_in->ctx_inflate.avail_in = len_pre;
ssl->transform_in->ctx_inflate.next_out = msg_post;
ssl->transform_in->ctx_inflate.avail_out = MBEDTLS_SSL_BUFFER_LEN -
ssl->transform_in->ctx_inflate.avail_out = MBEDTLS_SSL_IN_BUFFER_LEN -
header_bytes;
ret = inflate( &ssl->transform_in->ctx_inflate, Z_SYNC_FLUSH );
@ -2183,7 +2361,7 @@ static int ssl_decompress_buf( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED );
}
ssl->in_msglen = MBEDTLS_SSL_BUFFER_LEN -
ssl->in_msglen = MBEDTLS_SSL_IN_BUFFER_LEN -
ssl->transform_in->ctx_inflate.avail_out - header_bytes;
MBEDTLS_SSL_DEBUG_MSG( 3, ( "after decompression: msglen = %d, ",
@ -2258,7 +2436,7 @@ int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
}
if( nb_want > MBEDTLS_SSL_BUFFER_LEN - (size_t)( ssl->in_hdr - ssl->in_buf ) )
if( nb_want > MBEDTLS_SSL_IN_BUFFER_LEN - (size_t)( ssl->in_hdr - ssl->in_buf ) )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "requesting more data than fits" ) );
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
@ -2344,7 +2522,7 @@ int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want )
}
else
{
len = MBEDTLS_SSL_BUFFER_LEN - ( ssl->in_hdr - ssl->in_buf );
len = MBEDTLS_SSL_IN_BUFFER_LEN - ( ssl->in_hdr - ssl->in_buf );
if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
timeout = ssl->handshake->retransmit_timeout;
@ -2798,12 +2976,12 @@ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl )
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
{
/* Make room for the additional DTLS fields */
if( MBEDTLS_SSL_MAX_CONTENT_LEN - ssl->out_msglen < 8 )
if( MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen < 8 )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS handshake message too large: "
"size %u, maximum %u",
(unsigned) ( ssl->in_hslen - 4 ),
(unsigned) ( MBEDTLS_SSL_MAX_CONTENT_LEN - 12 ) ) );
(unsigned) ( MBEDTLS_SSL_OUT_CONTENT_LEN - 12 ) ) );
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
}
@ -3016,7 +3194,7 @@ static int ssl_reassemble_dtls_handshake( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialize reassembly, total length = %d",
msg_len ) );
if( ssl->in_hslen > MBEDTLS_SSL_MAX_CONTENT_LEN )
if( ssl->in_hslen > MBEDTLS_SSL_IN_CONTENT_LEN )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake message too large" ) );
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
@ -3120,7 +3298,7 @@ static int ssl_reassemble_dtls_handshake( mbedtls_ssl_context *ssl )
ssl->next_record_offset = new_remain - ssl->in_hdr;
ssl->in_left = ssl->next_record_offset + remain_len;
if( ssl->in_left > MBEDTLS_SSL_BUFFER_LEN -
if( ssl->in_left > MBEDTLS_SSL_IN_BUFFER_LEN -
(size_t)( ssl->in_hdr - ssl->in_buf ) )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "reassembled message too large for buffer" ) );
@ -3496,7 +3674,7 @@ static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl )
ssl->conf->p_cookie,
ssl->cli_id, ssl->cli_id_len,
ssl->in_buf, ssl->in_left,
ssl->out_buf, MBEDTLS_SSL_MAX_CONTENT_LEN, &len );
ssl->out_buf, MBEDTLS_SSL_OUT_CONTENT_LEN, &len );
MBEDTLS_SSL_DEBUG_RET( 2, "ssl_check_dtls_clihlo_cookie", ret );
@ -3593,7 +3771,7 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl )
}
/* Check length against the size of our buffer */
if( ssl->in_msglen > MBEDTLS_SSL_BUFFER_LEN
if( ssl->in_msglen > MBEDTLS_SSL_IN_BUFFER_LEN
- (size_t)( ssl->in_msg - ssl->in_buf ) )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
@ -3687,7 +3865,7 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl )
if( ssl->transform_in == NULL )
{
if( ssl->in_msglen < 1 ||
ssl->in_msglen > MBEDTLS_SSL_MAX_CONTENT_LEN )
ssl->in_msglen > MBEDTLS_SSL_IN_CONTENT_LEN )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
@ -3703,7 +3881,7 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_SSL_PROTO_SSL3)
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 &&
ssl->in_msglen > ssl->transform_in->minlen + MBEDTLS_SSL_MAX_CONTENT_LEN )
ssl->in_msglen > ssl->transform_in->minlen + MBEDTLS_SSL_IN_CONTENT_LEN )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
@ -3716,7 +3894,7 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl )
*/
if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 &&
ssl->in_msglen > ssl->transform_in->minlen +
MBEDTLS_SSL_MAX_CONTENT_LEN + 256 )
MBEDTLS_SSL_IN_CONTENT_LEN + 256 )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
@ -3764,7 +3942,7 @@ static int ssl_prepare_record_content( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_BUF( 4, "input payload after decrypt",
ssl->in_msg, ssl->in_msglen );
if( ssl->in_msglen > MBEDTLS_SSL_MAX_CONTENT_LEN )
if( ssl->in_msglen > MBEDTLS_SSL_IN_CONTENT_LEN )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
@ -4096,6 +4274,16 @@ int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl )
if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT )
{
if( ssl->in_msglen != 2 )
{
/* Note: Standard allows for more than one 2 byte alert
to be packed in a single message, but Mbed TLS doesn't
currently support this. */
MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid alert message, len: %d",
ssl->in_msglen ) );
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
}
MBEDTLS_SSL_DEBUG_MSG( 2, ( "got an alert message, type: [%d:%d]",
ssl->in_msg[0], ssl->in_msg[1] ) );
@ -4325,10 +4513,10 @@ int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl )
while( crt != NULL )
{
n = crt->raw.len;
if( n > MBEDTLS_SSL_MAX_CONTENT_LEN - 3 - i )
if( n > MBEDTLS_SSL_OUT_CONTENT_LEN - 3 - i )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "certificate too large, %d > %d",
i + 3 + n, MBEDTLS_SSL_MAX_CONTENT_LEN ) );
i + 3 + n, MBEDTLS_SSL_OUT_CONTENT_LEN ) );
return( MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE );
}
@ -4528,6 +4716,12 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
while( i < ssl->in_hslen )
{
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 );
}
if( ssl->in_msg[i] != 0 )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
@ -5202,7 +5396,7 @@ static void ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl )
/*
* Free our handshake params
*/
mbedtls_ssl_handshake_free( ssl->handshake );
mbedtls_ssl_handshake_free( ssl );
mbedtls_free( ssl->handshake );
ssl->handshake = NULL;
@ -5557,7 +5751,7 @@ static int ssl_handshake_init( mbedtls_ssl_context *ssl )
if( ssl->session_negotiate )
mbedtls_ssl_session_free( ssl->session_negotiate );
if( ssl->handshake )
mbedtls_ssl_handshake_free( ssl->handshake );
mbedtls_ssl_handshake_free( ssl );
/*
* Either the pointers are now NULL or cleared properly and can be freed.
@ -5662,17 +5856,23 @@ int mbedtls_ssl_setup( mbedtls_ssl_context *ssl,
const mbedtls_ssl_config *conf )
{
int ret;
const size_t len = MBEDTLS_SSL_BUFFER_LEN;
ssl->conf = conf;
/*
* Prepare base structures
*/
if( ( ssl-> in_buf = mbedtls_calloc( 1, len ) ) == NULL ||
( ssl->out_buf = mbedtls_calloc( 1, len ) ) == NULL )
ssl->in_buf = mbedtls_calloc( 1, MBEDTLS_SSL_IN_BUFFER_LEN );
if( ssl->in_buf == NULL )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", len ) );
MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", MBEDTLS_SSL_IN_BUFFER_LEN) );
return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
}
ssl->out_buf = mbedtls_calloc( 1, MBEDTLS_SSL_OUT_BUFFER_LEN );
if( ssl->out_buf == NULL )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", MBEDTLS_SSL_OUT_BUFFER_LEN) );
mbedtls_free( ssl->in_buf );
ssl->in_buf = NULL;
return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
@ -5773,9 +5973,9 @@ static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial )
ssl->transform_in = NULL;
ssl->transform_out = NULL;
memset( ssl->out_buf, 0, MBEDTLS_SSL_BUFFER_LEN );
memset( ssl->out_buf, 0, MBEDTLS_SSL_OUT_BUFFER_LEN );
if( partial == 0 )
memset( ssl->in_buf, 0, MBEDTLS_SSL_BUFFER_LEN );
memset( ssl->in_buf, 0, MBEDTLS_SSL_IN_BUFFER_LEN );
#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
if( mbedtls_ssl_hw_record_reset != NULL )
@ -5995,27 +6195,27 @@ static int ssl_append_key_cert( mbedtls_ssl_key_cert **head,
mbedtls_x509_crt *cert,
mbedtls_pk_context *key )
{
mbedtls_ssl_key_cert *new;
mbedtls_ssl_key_cert *new_cert;
new = mbedtls_calloc( 1, sizeof( mbedtls_ssl_key_cert ) );
if( new == NULL )
new_cert = mbedtls_calloc( 1, sizeof( mbedtls_ssl_key_cert ) );
if( new_cert == NULL )
return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
new->cert = cert;
new->key = key;
new->next = NULL;
new_cert->cert = cert;
new_cert->key = key;
new_cert->next = NULL;
/* Update head is the list was null, else add to the end */
if( *head == NULL )
{
*head = new;
*head = new_cert;
}
else
{
mbedtls_ssl_key_cert *cur = *head;
while( cur->next != NULL )
cur = cur->next;
cur->next = new;
cur->next = new_cert;
}
return( 0 );
@ -6100,7 +6300,7 @@ int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf,
/* Identity len will be encoded on two bytes */
if( ( psk_identity_len >> 16 ) != 0 ||
psk_identity_len > MBEDTLS_SSL_MAX_CONTENT_LEN )
psk_identity_len > MBEDTLS_SSL_OUT_CONTENT_LEN )
{
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
}
@ -6401,7 +6601,7 @@ void mbedtls_ssl_conf_arc4_support( mbedtls_ssl_config *conf, char arc4 )
int mbedtls_ssl_conf_max_frag_len( mbedtls_ssl_config *conf, unsigned char mfl_code )
{
if( mfl_code >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID ||
mfl_code_to_length[mfl_code] > MBEDTLS_SSL_MAX_CONTENT_LEN )
ssl_mfl_code_to_length( mfl_code ) > MBEDTLS_TLS_EXT_ADV_CONTENT_LEN )
{
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
}
@ -6480,6 +6680,43 @@ void mbedtls_ssl_conf_export_keys_cb( mbedtls_ssl_config *conf,
}
#endif
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
void mbedtls_ssl_conf_async_private_cb(
mbedtls_ssl_config *conf,
mbedtls_ssl_async_sign_t *f_async_sign,
mbedtls_ssl_async_decrypt_t *f_async_decrypt,
mbedtls_ssl_async_resume_t *f_async_resume,
mbedtls_ssl_async_cancel_t *f_async_cancel,
void *async_config_data )
{
conf->f_async_sign_start = f_async_sign;
conf->f_async_decrypt_start = f_async_decrypt;
conf->f_async_resume = f_async_resume;
conf->f_async_cancel = f_async_cancel;
conf->p_async_config_data = async_config_data;
}
void *mbedtls_ssl_conf_get_async_config_data( const mbedtls_ssl_config *conf )
{
return( conf->p_async_config_data );
}
void *mbedtls_ssl_get_async_operation_data( const mbedtls_ssl_context *ssl )
{
if( ssl->handshake == NULL )
return( NULL );
else
return( ssl->handshake->user_async_ctx );
}
void mbedtls_ssl_set_async_operation_data( mbedtls_ssl_context *ssl,
void *ctx )
{
if( ssl->handshake != NULL )
ssl->handshake->user_async_ctx = ctx;
}
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
/*
* SSL get accessors
*/
@ -6642,15 +6879,15 @@ size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl )
/*
* Assume mfl_code is correct since it was checked when set
*/
max_len = mfl_code_to_length[ssl->conf->mfl_code];
max_len = ssl_mfl_code_to_length( ssl->conf->mfl_code );
/*
* Check if a smaller max length was negotiated
*/
if( ssl->session_out != NULL &&
mfl_code_to_length[ssl->session_out->mfl_code] < max_len )
ssl_mfl_code_to_length( ssl->session_out->mfl_code ) < max_len )
{
max_len = mfl_code_to_length[ssl->session_out->mfl_code];
max_len = ssl_mfl_code_to_length( ssl->session_out->mfl_code );
}
return max_len;
@ -7194,8 +7431,16 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
}
/*
* Send application data to be encrypted by the SSL layer,
* taking care of max fragment length and buffer size
* Send application data to be encrypted by the SSL layer, taking care of max
* fragment length and buffer size.
*
* According to RFC 5246 Section 6.2.1:
*
* Zero-length fragments of Application data MAY be sent as they are
* potentially useful as a traffic analysis countermeasure.
*
* Therefore, it is possible that the input message length is 0 and the
* corresponding return code is 0 on success.
*/
static int ssl_write_real( mbedtls_ssl_context *ssl,
const unsigned char *buf, size_t len )
@ -7204,7 +7449,7 @@ static int ssl_write_real( mbedtls_ssl_context *ssl,
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
size_t max_len = mbedtls_ssl_get_max_frag_len( ssl );
#else
size_t max_len = MBEDTLS_SSL_MAX_CONTENT_LEN;
size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN;
#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
if( len > max_len )
{
@ -7223,6 +7468,12 @@ static int ssl_write_real( mbedtls_ssl_context *ssl,
if( ssl->out_left != 0 )
{
/*
* The user has previously tried to send the data and
* MBEDTLS_ERR_SSL_WANT_WRITE or the message was only partially
* written. In this case, we expect the high-level write function
* (e.g. mbedtls_ssl_write()) to be called with the same parameters
*/
if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret );
@ -7231,6 +7482,11 @@ static int ssl_write_real( mbedtls_ssl_context *ssl,
}
else
{
/*
* The user is trying to send a message the first time, so we need to
* copy the data into the internal buffers and setup the data structure
* to keep track of partial writes
*/
ssl->out_msglen = len;
ssl->out_msgtype = MBEDTLS_SSL_MSG_APPLICATION_DATA;
memcpy( ssl->out_msg, buf, len );
@ -7387,11 +7643,21 @@ static void ssl_key_cert_free( mbedtls_ssl_key_cert *key_cert )
}
#endif /* MBEDTLS_X509_CRT_PARSE_C */
void mbedtls_ssl_handshake_free( mbedtls_ssl_handshake_params *handshake )
void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl )
{
mbedtls_ssl_handshake_params *handshake = ssl->handshake;
if( handshake == NULL )
return;
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
if( ssl->conf->f_async_cancel != NULL && handshake->async_in_progress != 0 )
{
ssl->conf->f_async_cancel( ssl );
handshake->async_in_progress = 0;
}
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
defined(MBEDTLS_SSL_PROTO_TLS1_1)
mbedtls_md5_free( &handshake->fin_md5 );
@ -7496,20 +7762,20 @@ void mbedtls_ssl_free( mbedtls_ssl_context *ssl )
if( ssl->out_buf != NULL )
{
mbedtls_platform_zeroize( ssl->out_buf, MBEDTLS_SSL_BUFFER_LEN );
mbedtls_platform_zeroize( ssl->out_buf, MBEDTLS_SSL_OUT_BUFFER_LEN );
mbedtls_free( ssl->out_buf );
}
if( ssl->in_buf != NULL )
{
mbedtls_platform_zeroize( ssl->in_buf, MBEDTLS_SSL_BUFFER_LEN );
mbedtls_platform_zeroize( ssl->in_buf, MBEDTLS_SSL_IN_BUFFER_LEN );
mbedtls_free( ssl->in_buf );
}
#if defined(MBEDTLS_ZLIB_SUPPORT)
if( ssl->compress_buf != NULL )
{
mbedtls_platform_zeroize( ssl->compress_buf, MBEDTLS_SSL_BUFFER_LEN );
mbedtls_platform_zeroize( ssl->compress_buf, MBEDTLS_SSL_COMPRESS_BUFFER_LEN );
mbedtls_free( ssl->compress_buf );
}
#endif
@ -7522,7 +7788,7 @@ void mbedtls_ssl_free( mbedtls_ssl_context *ssl )
if( ssl->handshake )
{
mbedtls_ssl_handshake_free( ssl->handshake );
mbedtls_ssl_handshake_free( ssl );
mbedtls_ssl_transform_free( ssl->transform_negotiate );
mbedtls_ssl_session_free( ssl->session_negotiate );
@ -8289,13 +8555,14 @@ exit:
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
defined(MBEDTLS_SSL_PROTO_TLS1_2)
int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl,
unsigned char *output,
unsigned char *data, size_t data_len,
mbedtls_md_type_t md_alg )
unsigned char *hash, size_t *hashlen,
unsigned char *data, size_t data_len,
mbedtls_md_type_t md_alg )
{
int ret = 0;
mbedtls_md_context_t ctx;
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg );
*hashlen = mbedtls_md_get_size( md_info );
mbedtls_md_init( &ctx );
@ -8326,7 +8593,7 @@ int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl,
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_update", ret );
goto exit;
}
if( ( ret = mbedtls_md_finish( &ctx, output ) ) != 0 )
if( ( ret = mbedtls_md_finish( &ctx, hash ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_finish", ret );
goto exit;

View file

@ -114,9 +114,6 @@ void mbedtls_threading_set_alt( void (*mutex_init)( mbedtls_threading_mutex_t *
#if defined(MBEDTLS_FS_IO)
mbedtls_mutex_init( &mbedtls_threading_readdir_mutex );
#endif
#if defined(MBEDTLS_HAVE_TIME_DATE)
mbedtls_mutex_init( &mbedtls_threading_gmtime_mutex );
#endif
}
/*
@ -127,9 +124,6 @@ void mbedtls_threading_free_alt( void )
#if defined(MBEDTLS_FS_IO)
mbedtls_mutex_free( &mbedtls_threading_readdir_mutex );
#endif
#if defined(MBEDTLS_HAVE_TIME_DATE)
mbedtls_mutex_free( &mbedtls_threading_gmtime_mutex );
#endif
}
#endif /* MBEDTLS_THREADING_ALT */
@ -142,8 +136,5 @@ void mbedtls_threading_free_alt( void )
#if defined(MBEDTLS_FS_IO)
mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex MUTEX_INIT;
#endif
#if defined(MBEDTLS_HAVE_TIME_DATE)
mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex MUTEX_INIT;
#endif
#endif /* MBEDTLS_THREADING_C */

View file

@ -39,7 +39,8 @@
#if !defined(MBEDTLS_TIMING_ALT)
#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \
!defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__)
!defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \
!defined(__HAIKU__)
#error "This module only works on Unix and Windows, see MBEDTLS_TIMING_C in config.h"
#endif

View file

@ -39,6 +39,9 @@ static const char *features[] = {
#if defined(MBEDTLS_NO_UDBL_DIVISION)
"MBEDTLS_NO_UDBL_DIVISION",
#endif /* MBEDTLS_NO_UDBL_DIVISION */
#if defined(MBEDTLS_NO_64BIT_MULTIPLICATION)
"MBEDTLS_NO_64BIT_MULTIPLICATION",
#endif /* MBEDTLS_NO_64BIT_MULTIPLICATION */
#if defined(MBEDTLS_HAVE_SSE2)
"MBEDTLS_HAVE_SSE2",
#endif /* MBEDTLS_HAVE_SSE2 */
@ -102,6 +105,12 @@ static const char *features[] = {
#if defined(MBEDTLS_CCM_ALT)
"MBEDTLS_CCM_ALT",
#endif /* MBEDTLS_CCM_ALT */
#if defined(MBEDTLS_CHACHA20_ALT)
"MBEDTLS_CHACHA20_ALT",
#endif /* MBEDTLS_CHACHA20_ALT */
#if defined(MBEDTLS_CHACHAPOLY_ALT)
"MBEDTLS_CHACHAPOLY_ALT",
#endif /* MBEDTLS_CHACHAPOLY_ALT */
#if defined(MBEDTLS_CMAC_ALT)
"MBEDTLS_CMAC_ALT",
#endif /* MBEDTLS_CMAC_ALT */
@ -117,6 +126,9 @@ static const char *features[] = {
#if defined(MBEDTLS_GCM_ALT)
"MBEDTLS_GCM_ALT",
#endif /* MBEDTLS_GCM_ALT */
#if defined(MBEDTLS_NIST_KW_ALT)
"MBEDTLS_NIST_KW_ALT",
#endif /* MBEDTLS_NIST_KW_ALT */
#if defined(MBEDTLS_MD2_ALT)
"MBEDTLS_MD2_ALT",
#endif /* MBEDTLS_MD2_ALT */
@ -126,6 +138,9 @@ static const char *features[] = {
#if defined(MBEDTLS_MD5_ALT)
"MBEDTLS_MD5_ALT",
#endif /* MBEDTLS_MD5_ALT */
#if defined(MBEDTLS_POLY1305_ALT)
"MBEDTLS_POLY1305_ALT",
#endif /* MBEDTLS_POLY1305_ALT */
#if defined(MBEDTLS_RIPEMD160_ALT)
"MBEDTLS_RIPEMD160_ALT",
#endif /* MBEDTLS_RIPEMD160_ALT */
@ -255,6 +270,12 @@ static const char *features[] = {
#if defined(MBEDTLS_CIPHER_MODE_CTR)
"MBEDTLS_CIPHER_MODE_CTR",
#endif /* MBEDTLS_CIPHER_MODE_CTR */
#if defined(MBEDTLS_CIPHER_MODE_OFB)
"MBEDTLS_CIPHER_MODE_OFB",
#endif /* MBEDTLS_CIPHER_MODE_OFB */
#if defined(MBEDTLS_CIPHER_MODE_XTS)
"MBEDTLS_CIPHER_MODE_XTS",
#endif /* MBEDTLS_CIPHER_MODE_XTS */
#if defined(MBEDTLS_CIPHER_NULL_CIPHER)
"MBEDTLS_CIPHER_NULL_CIPHER",
#endif /* MBEDTLS_CIPHER_NULL_CIPHER */
@ -405,6 +426,9 @@ static const char *features[] = {
#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES)
"MBEDTLS_SSL_ALL_ALERT_MESSAGES",
#endif /* MBEDTLS_SSL_ALL_ALERT_MESSAGES */
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
"MBEDTLS_SSL_ASYNC_PRIVATE",
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
#if defined(MBEDTLS_SSL_DEBUG_ALL)
"MBEDTLS_SSL_DEBUG_ALL",
#endif /* MBEDTLS_SSL_DEBUG_ALL */
@ -543,6 +567,12 @@ static const char *features[] = {
#if defined(MBEDTLS_CERTS_C)
"MBEDTLS_CERTS_C",
#endif /* MBEDTLS_CERTS_C */
#if defined(MBEDTLS_CHACHA20_C)
"MBEDTLS_CHACHA20_C",
#endif /* MBEDTLS_CHACHA20_C */
#if defined(MBEDTLS_CHACHAPOLY_C)
"MBEDTLS_CHACHAPOLY_C",
#endif /* MBEDTLS_CHACHAPOLY_C */
#if defined(MBEDTLS_CIPHER_C)
"MBEDTLS_CIPHER_C",
#endif /* MBEDTLS_CIPHER_C */
@ -585,9 +615,15 @@ static const char *features[] = {
#if defined(MBEDTLS_HAVEGE_C)
"MBEDTLS_HAVEGE_C",
#endif /* MBEDTLS_HAVEGE_C */
#if defined(MBEDTLS_HKDF_C)
"MBEDTLS_HKDF_C",
#endif /* MBEDTLS_HKDF_C */
#if defined(MBEDTLS_HMAC_DRBG_C)
"MBEDTLS_HMAC_DRBG_C",
#endif /* MBEDTLS_HMAC_DRBG_C */
#if defined(MBEDTLS_NIST_KW_C)
"MBEDTLS_NIST_KW_C",
#endif /* MBEDTLS_NIST_KW_C */
#if defined(MBEDTLS_MD_C)
"MBEDTLS_MD_C",
#endif /* MBEDTLS_MD_C */
@ -639,6 +675,9 @@ static const char *features[] = {
#if defined(MBEDTLS_PLATFORM_C)
"MBEDTLS_PLATFORM_C",
#endif /* MBEDTLS_PLATFORM_C */
#if defined(MBEDTLS_POLY1305_C)
"MBEDTLS_POLY1305_C",
#endif /* MBEDTLS_POLY1305_C */
#if defined(MBEDTLS_RIPEMD160_C)
"MBEDTLS_RIPEMD160_C",
#endif /* MBEDTLS_RIPEMD160_C */

View file

@ -29,6 +29,10 @@
* http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
*/
/* Ensure gmtime_r is available even with -std=c99; must be included before
* config.h, which pulls in glibc's features.h. Harmless on other platforms. */
#define _POSIX_C_SOURCE 200112L
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
@ -59,26 +63,13 @@
#define mbedtls_snprintf snprintf
#endif
#if defined(MBEDTLS_HAVE_TIME)
#include "mbedtls/platform_time.h"
#endif
#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
#include <windows.h>
#else
#if defined(MBEDTLS_HAVE_TIME_DATE)
#include <time.h>
#endif
#if defined(MBEDTLS_FS_IO)
#include <stdio.h>
#if !defined(_WIN32)
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#endif
#endif
#define CHECK(code) if( ( ret = code ) != 0 ){ return( ret ); }
#define CHECK_RANGE(min, max, val) if( val < min || val > max ){ return( ret ); }
@ -903,36 +894,18 @@ int mbedtls_x509_key_size_helper( char *buf, size_t buf_size, const char *name )
* Set the time structure to the current time.
* Return 0 on success, non-zero on failure.
*/
#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
static int x509_get_current_time( mbedtls_x509_time *now )
{
SYSTEMTIME st;
GetSystemTime( &st );
now->year = st.wYear;
now->mon = st.wMonth;
now->day = st.wDay;
now->hour = st.wHour;
now->min = st.wMinute;
now->sec = st.wSecond;
return( 0 );
}
#else
static int x509_get_current_time( mbedtls_x509_time *now )
{
struct tm *lt;
struct tm *lt, tm_buf;
mbedtls_time_t tt;
int ret = 0;
#if defined(MBEDTLS_THREADING_C)
if( mbedtls_mutex_lock( &mbedtls_threading_gmtime_mutex ) != 0 )
return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
#endif
tt = mbedtls_time( NULL );
lt = gmtime( &tt );
#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
lt = gmtime_s( &tm_buf, &tt ) == 0 ? &tm_buf : NULL;
#else
lt = gmtime_r( &tt, &tm_buf );
#endif
if( lt == NULL )
ret = -1;
@ -946,14 +919,8 @@ static int x509_get_current_time( mbedtls_x509_time *now )
now->sec = lt->tm_sec;
}
#if defined(MBEDTLS_THREADING_C)
if( mbedtls_mutex_unlock( &mbedtls_threading_gmtime_mutex ) != 0 )
return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
#endif
return( ret );
}
#endif /* _WIN32 && !EFIX64 && !EFI32 */
/*
* Return 0 if before <= after, 1 otherwise

View file

@ -1139,7 +1139,7 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path )
char filename[MAX_PATH];
char *p;
size_t len = strlen( path );
int lengthAsInt = 0;
int length_as_int = 0;
WIN32_FIND_DATAW file_data;
HANDLE hFind;
@ -1154,7 +1154,7 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path )
p = filename + len;
filename[len++] = '*';
if ( FAILED ( SizeTToInt( len, &lengthAsInt ) ) )
if ( FAILED ( SizeTToInt( len, &length_as_int ) ) )
return( MBEDTLS_ERR_X509_FILE_IO_ERROR );
/*
@ -1165,7 +1165,7 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path )
* incoming string are less than MAX_PATH to avoid a buffer overrun with
* MultiByteToWideChar().
*/
w_ret = MultiByteToWideChar( CP_ACP, 0, filename, lengthAsInt, szDir,
w_ret = MultiByteToWideChar( CP_ACP, 0, filename, length_as_int, szDir,
MAX_PATH - 3 );
if( w_ret == 0 )
return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
@ -1182,11 +1182,11 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path )
if( file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
continue;
if ( FAILED( SizeTToInt( wcslen( file_data.cFileName ), &lengthAsInt ) ) )
if ( FAILED( SizeTToInt( wcslen( file_data.cFileName ), &length_as_int ) ) )
return( MBEDTLS_ERR_X509_FILE_IO_ERROR );
w_ret = WideCharToMultiByte( CP_ACP, 0, file_data.cFileName,
lengthAsInt,
length_as_int,
p, (int) len - 1,
NULL, NULL );
if( w_ret == 0 )

View file

@ -274,34 +274,25 @@ int mbedtls_x509_csr_parse( mbedtls_x509_csr *csr, const unsigned char *buf, siz
return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
#if defined(MBEDTLS_PEM_PARSE_C)
mbedtls_pem_init( &pem );
/* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
if( buf[buflen - 1] != '\0' )
ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
else
if( buf[buflen - 1] == '\0' )
{
mbedtls_pem_init( &pem );
ret = mbedtls_pem_read_buffer( &pem,
"-----BEGIN CERTIFICATE REQUEST-----",
"-----END CERTIFICATE REQUEST-----",
buf, NULL, 0, &use_len );
if( ret == 0 )
{
/*
* Was PEM encoded, parse the result
*/
if( ( ret = mbedtls_x509_csr_parse_der( csr, pem.buf, pem.buflen ) ) != 0 )
return( ret );
if( ret == 0 )
/*
* Was PEM encoded, parse the result
*/
ret = mbedtls_x509_csr_parse_der( csr, pem.buf, pem.buflen );
mbedtls_pem_free( &pem );
return( 0 );
if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
return( ret );
}
else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
{
mbedtls_pem_free( &pem );
return( ret );
}
else
#endif /* MBEDTLS_PEM_PARSE_C */
return( mbedtls_x509_csr_parse_der( csr, buf, buflen ) );
}