Merge commit '01b34fb316a5' into development

Merge a development version of Mbed TLS 2.16.0 that doesn't have
parameter validation into development.

The following conflicts were resolved:

- Update ChangeLog to include release notes merged from development so
  far, with a version of "2.14.0+01b34fb316a5" and release date of
  "xxxx-xx-xx" to show this is not a released version, but instead a
  snapshot of the development branch equivalent to version of the 2.14.0
  with additional commits from the mbedtls/development branch up through
  01b34fb316 included. Entries added for unreleased versions of Mbed
  Crypto remain at the top of the file for Mbed TLS 2.xx.x.
- Replace the Mbed Crypto version of
  mbedtls_rsa_rsaes_pkcs1_v15_decrypt() with the version from Mbed TLS
  which fixes timing variations and memory access variations that could
  lead to a Bleichenbacher-style padding oracle attack. This will
  prevent using psa_asymmetric_decrypt() with zero-length output buffers
  until a follow up commit is made to restore this capability.
- In ssl_srv.c, include changes for both the new ECDH interface and
  opaque PSK as already added to development previously.
This commit is contained in:
Jaeden Amero 2019-02-05 12:05:16 +00:00
commit 68933640f5
46 changed files with 1605 additions and 394 deletions

View File

@ -4,6 +4,13 @@ compiler:
- gcc - gcc
sudo: false sudo: false
cache: ccache cache: ccache
# blocklist
branches:
except:
- development-psa
- coverity_scan
script: script:
- tests/scripts/recursion.pl library/*.c - tests/scripts/recursion.pl library/*.c
- tests/scripts/check-generated-files.sh - tests/scripts/check-generated-files.sh
@ -34,7 +41,7 @@ addons:
coverity_scan: coverity_scan:
project: project:
name: "ARMmbed/mbedtls" name: "ARMmbed/mbedtls"
notification_email: p.j.bakker@polarssl.org notification_email: simon.butcher@arm.com
build_command_prepend: build_command_prepend:
build_command: make build_command: make
branch_pattern: coverity_scan branch_pattern: coverity_scan

View File

@ -6,6 +6,58 @@ Changes
* Add unit tests for AES-GCM when called through mbedtls_cipher_auth_xxx() * Add unit tests for AES-GCM when called through mbedtls_cipher_auth_xxx()
from the cipher abstraction layer. Fixes #2198. from the cipher abstraction layer. Fixes #2198.
= mbed TLS 2.14.0+01b34fb316a5 branch released xxxx-xx-xx
Security
* Fix timing variations and memory access variations in RSA PKCS#1 v1.5
decryption that could lead to a Bleichenbacher-style padding oracle
attack. In TLS, this affects servers that accept ciphersuites based on
RSA decryption (i.e. ciphersuites whose name contains RSA but not
(EC)DH(E)). Discovered by Eyal Ronen (Weizmann Institute), Robert Gillham
(University of Adelaide), Daniel Genkin (University of Michigan),
Adi Shamir (Weizmann Institute), David Wong (NCC Group), and Yuval Yarom
(University of Adelaide, Data61). The attack is described in more detail
in the paper available here: http://cat.eyalro.net/cat.pdf CVE-2018-19608
* In mbedtls_mpi_write_binary(), don't leak the exact size of the number
via branching and memory access patterns. An attacker who could submit
a plaintext for RSA PKCS#1 v1.5 decryption but only observe the timing
of the decryption and not its result could nonetheless decrypt RSA
plaintexts and forge RSA signatures. Other asymmetric algorithms may
have been similarly vulnerable. Reported by Eyal Ronen, Robert Gillham,
Daniel Genkin, Adi Shamir, David Wong and Yuval Yarom.
* Wipe sensitive buffers on the stack in the CTR_DRBG and HMAC_DRBG
modules.
API Changes
* The following functions in the random generator modules have been
deprecated and replaced as shown below. The new functions change
the return type from void to int to allow returning error codes when
using MBEDTLS_<MODULE>_ALT for the underlying AES or message digest
primitive. Fixes #1798.
mbedtls_ctr_drbg_update() -> mbedtls_ctr_drbg_update_ret()
mbedtls_hmac_drbg_update() -> mbedtls_hmac_drbg_update_ret()
* Extend ECDH interface to enable alternative implementations.
New deprecations
* Deprecate mbedtls_ctr_drbg_update and mbedtls_hmac_drbg_update
in favor of functions that can return an error code.
Bugfix
* Fix for Clang, which was reporting a warning for the bignum.c inline
assembly for AMD64 targets creating string literals greater than those
permitted by the ISO C99 standard. Found by Aaron Jones. Fixes #482.
* Fix runtime error in `mbedtls_platform_entropy_poll()` when run
through qemu user emulation. Reported and fix suggested by randombit
in #1212. Fixes #1212.
* Fix an unsafe bounds check when restoring an SSL session from a ticket.
This could lead to a buffer overflow, but only in case ticket authentication
was broken. Reported and fix suggested by Guido Vranken in #659.
* Add explicit integer to enumeration type casts to example program
programs/pkey/gen_key which previously led to compilation failure
on some toolchains. Reported by phoenixmcallister. Fixes #2170.
* Fix double initialization of ECC hardware that made some accelerators
hang.
= mbed TLS 2.14.0 branch released 2018-11-19 = mbed TLS 2.14.0 branch released 2018-11-19
Security Security

View File

@ -170,19 +170,19 @@
#define MULADDC_INIT \ #define MULADDC_INIT \
asm( \ asm( \
"xorq %%r8, %%r8 \n\t" "xorq %%r8, %%r8\n"
#define MULADDC_CORE \ #define MULADDC_CORE \
"movq (%%rsi), %%rax \n\t" \ "movq (%%rsi), %%rax\n" \
"mulq %%rbx \n\t" \ "mulq %%rbx\n" \
"addq $8, %%rsi \n\t" \ "addq $8, %%rsi\n" \
"addq %%rcx, %%rax \n\t" \ "addq %%rcx, %%rax\n" \
"movq %%r8, %%rcx \n\t" \ "movq %%r8, %%rcx\n" \
"adcq $0, %%rdx \n\t" \ "adcq $0, %%rdx\n" \
"nop \n\t" \ "nop \n" \
"addq %%rax, (%%rdi) \n\t" \ "addq %%rax, (%%rdi)\n" \
"adcq %%rdx, %%rcx \n\t" \ "adcq %%rdx, %%rcx\n" \
"addq $8, %%rdi \n\t" "addq $8, %%rdi\n"
#define MULADDC_STOP \ #define MULADDC_STOP \
: "+c" (c), "+D" (d), "+S" (s) \ : "+c" (c), "+D" (d), "+S" (s) \

View File

@ -114,6 +114,7 @@
defined(MBEDTLS_ECDSA_SIGN_ALT) || \ defined(MBEDTLS_ECDSA_SIGN_ALT) || \
defined(MBEDTLS_ECDSA_VERIFY_ALT) || \ defined(MBEDTLS_ECDSA_VERIFY_ALT) || \
defined(MBEDTLS_ECDSA_GENKEY_ALT) || \ defined(MBEDTLS_ECDSA_GENKEY_ALT) || \
defined(MBEDTLS_ECP_INTERNAL_ALT) || \
defined(MBEDTLS_ECP_ALT) ) defined(MBEDTLS_ECP_ALT) )
#error "MBEDTLS_ECP_RESTARTABLE defined, but it cannot coexist with an alternative ECP implementation" #error "MBEDTLS_ECP_RESTARTABLE defined, but it cannot coexist with an alternative ECP implementation"
#endif #endif
@ -137,6 +138,10 @@
#error "MBEDTLS_ECP_C defined, but not all prerequisites" #error "MBEDTLS_ECP_C defined, but not all prerequisites"
#endif #endif
#if defined(MBEDTLS_PK_PARSE_C) && !defined(MBEDTLS_ASN1_PARSE_C)
#error "MBEDTLS_PK_PARSE_C defined, but not all prerequesites"
#endif
#if defined(MBEDTLS_ENTROPY_C) && (!defined(MBEDTLS_SHA512_C) && \ #if defined(MBEDTLS_ENTROPY_C) && (!defined(MBEDTLS_SHA512_C) && \
!defined(MBEDTLS_SHA256_C)) !defined(MBEDTLS_SHA256_C))
#error "MBEDTLS_ENTROPY_C defined, but not all prerequisites" #error "MBEDTLS_ENTROPY_C defined, but not all prerequisites"

View File

@ -414,11 +414,11 @@
* unsigned char mbedtls_internal_ecp_grp_capable( * unsigned char mbedtls_internal_ecp_grp_capable(
* const mbedtls_ecp_group *grp ) * const mbedtls_ecp_group *grp )
* int mbedtls_internal_ecp_init( const mbedtls_ecp_group *grp ) * int mbedtls_internal_ecp_init( const mbedtls_ecp_group *grp )
* void mbedtls_internal_ecp_deinit( const mbedtls_ecp_group *grp ) * void mbedtls_internal_ecp_free( const mbedtls_ecp_group *grp )
* The mbedtls_internal_ecp_grp_capable function should return 1 if the * The mbedtls_internal_ecp_grp_capable function should return 1 if the
* replacement functions implement arithmetic for the given group and 0 * replacement functions implement arithmetic for the given group and 0
* otherwise. * otherwise.
* The functions mbedtls_internal_ecp_init and mbedtls_internal_ecp_deinit are * The functions mbedtls_internal_ecp_init and mbedtls_internal_ecp_free are
* called before and after each point operation and provide an opportunity to * called before and after each point operation and provide an opportunity to
* implement optimized set up and tear down instructions. * implement optimized set up and tear down instructions.
* *

View File

@ -239,18 +239,20 @@ int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
/** /**
* \brief This function updates the state of the CTR_DRBG context. * \brief This function updates the state of the CTR_DRBG context.
* *
* \note If \p add_len is greater than
* #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT, only the first
* #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT Bytes are used.
* The remaining Bytes are silently discarded.
*
* \param ctx The CTR_DRBG context. * \param ctx The CTR_DRBG context.
* \param additional The data to update the state with. * \param additional The data to update the state with.
* \param add_len Length of \p additional data. * \param add_len Length of \p additional in bytes. This must be at
* most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT.
* *
* \return \c 0 on success.
* \return #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if
* \p add_len is more than
* #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT.
* \return An error from the underlying AES cipher on failure.
*/ */
void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
const unsigned char *additional, size_t add_len ); const unsigned char *additional,
size_t add_len );
/** /**
* \brief This function updates a CTR_DRBG instance with additional * \brief This function updates a CTR_DRBG instance with additional
@ -290,6 +292,35 @@ int mbedtls_ctr_drbg_random_with_add( void *p_rng,
int mbedtls_ctr_drbg_random( void *p_rng, int mbedtls_ctr_drbg_random( void *p_rng,
unsigned char *output, size_t output_len ); unsigned char *output, size_t output_len );
#if ! defined(MBEDTLS_DEPRECATED_REMOVED)
#if defined(MBEDTLS_DEPRECATED_WARNING)
#define MBEDTLS_DEPRECATED __attribute__((deprecated))
#else
#define MBEDTLS_DEPRECATED
#endif
/**
* \brief This function updates the state of the CTR_DRBG context.
*
* \deprecated Superseded by mbedtls_ctr_drbg_update_ret()
* in 2.16.0.
*
* \note If \p add_len is greater than
* #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT, only the first
* #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT Bytes are used.
* The remaining Bytes are silently discarded.
*
* \param ctx The CTR_DRBG context.
* \param additional The data to update the state with.
* \param add_len Length of \p additional data.
*/
MBEDTLS_DEPRECATED void mbedtls_ctr_drbg_update(
mbedtls_ctr_drbg_context *ctx,
const unsigned char *additional,
size_t add_len );
#undef MBEDTLS_DEPRECATED
#endif /* !MBEDTLS_DEPRECATED_REMOVED */
#if defined(MBEDTLS_FS_IO) #if defined(MBEDTLS_FS_IO)
/** /**
* \brief This function writes a seed file. * \brief This function writes a seed file.

View File

@ -65,6 +65,11 @@
mbedtls_debug_print_crt( ssl, level, __FILE__, __LINE__, text, crt ) mbedtls_debug_print_crt( ssl, level, __FILE__, __LINE__, text, crt )
#endif #endif
#if defined(MBEDTLS_ECDH_C)
#define MBEDTLS_SSL_DEBUG_ECDH( level, ecdh, attr ) \
mbedtls_debug_printf_ecdh( ssl, level, __FILE__, __LINE__, ecdh, attr )
#endif
#else /* MBEDTLS_DEBUG_C */ #else /* MBEDTLS_DEBUG_C */
#define MBEDTLS_SSL_DEBUG_MSG( level, args ) do { } while( 0 ) #define MBEDTLS_SSL_DEBUG_MSG( level, args ) do { } while( 0 )
@ -73,6 +78,7 @@
#define MBEDTLS_SSL_DEBUG_MPI( level, text, X ) do { } while( 0 ) #define MBEDTLS_SSL_DEBUG_MPI( level, text, X ) do { } while( 0 )
#define MBEDTLS_SSL_DEBUG_ECP( level, text, X ) do { } while( 0 ) #define MBEDTLS_SSL_DEBUG_ECP( level, text, X ) do { } while( 0 )
#define MBEDTLS_SSL_DEBUG_CRT( level, text, crt ) do { } while( 0 ) #define MBEDTLS_SSL_DEBUG_CRT( level, text, crt ) do { } while( 0 )
#define MBEDTLS_SSL_DEBUG_ECDH( level, ecdh, attr ) do { } while( 0 )
#endif /* MBEDTLS_DEBUG_C */ #endif /* MBEDTLS_DEBUG_C */
@ -221,6 +227,36 @@ void mbedtls_debug_print_crt( const mbedtls_ssl_context *ssl, int level,
const char *text, const mbedtls_x509_crt *crt ); const char *text, const mbedtls_x509_crt *crt );
#endif #endif
#if defined(MBEDTLS_ECDH_C)
typedef enum
{
MBEDTLS_DEBUG_ECDH_Q,
MBEDTLS_DEBUG_ECDH_QP,
MBEDTLS_DEBUG_ECDH_Z,
} mbedtls_debug_ecdh_attr;
/**
* \brief Print a field of the ECDH structure in the SSL context to the debug
* output. This function is always used through the
* MBEDTLS_SSL_DEBUG_ECDH() macro, which supplies the ssl context, file
* and line number parameters.
*
* \param ssl SSL context
* \param level error level of the debug message
* \param file file the error has occurred in
* \param line line number the error has occurred in
* \param ecdh the ECDH context
* \param attr the identifier of the attribute being output
*
* \attention This function is intended for INTERNAL usage within the
* library only.
*/
void mbedtls_debug_printf_ecdh( const mbedtls_ssl_context *ssl, int level,
const char *file, int line,
const mbedtls_ecdh_context *ecdh,
mbedtls_debug_ecdh_attr attr );
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -36,6 +36,18 @@
#include "ecp.h" #include "ecp.h"
/*
* Use a backward compatible ECDH context.
*
* This flag is always enabled for now and future versions might add a
* configuration option that conditionally undefines this flag.
* The configuration option in question may have a different name.
*
* Features undefining this flag, must have a warning in their description in
* config.h stating that the feature breaks backward compatibility.
*/
#define MBEDTLS_ECDH_LEGACY_CONTEXT
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -49,6 +61,39 @@ typedef enum
MBEDTLS_ECDH_THEIRS, /**< The key of the peer. */ MBEDTLS_ECDH_THEIRS, /**< The key of the peer. */
} mbedtls_ecdh_side; } mbedtls_ecdh_side;
#if !defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
/**
* Defines the ECDH implementation used.
*
* Later versions of the library may add new variants, therefore users should
* not make any assumptions about them.
*/
typedef enum
{
MBEDTLS_ECDH_VARIANT_NONE = 0, /*!< Implementation not defined. */
MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0,/*!< The default Mbed TLS implementation */
} mbedtls_ecdh_variant;
/**
* The context used by the default ECDH implementation.
*
* Later versions might change the structure of this context, therefore users
* should not make any assumptions about the structure of
* mbedtls_ecdh_context_mbed.
*/
typedef struct mbedtls_ecdh_context_mbed
{
mbedtls_ecp_group grp; /*!< The elliptic curve used. */
mbedtls_mpi d; /*!< The private key. */
mbedtls_ecp_point Q; /*!< The public key. */
mbedtls_ecp_point Qp; /*!< The value of the public key of the peer. */
mbedtls_mpi z; /*!< The shared secret. */
#if defined(MBEDTLS_ECP_RESTARTABLE)
mbedtls_ecp_restart_ctx rs; /*!< The restart context for EC computations. */
#endif
} mbedtls_ecdh_context_mbed;
#endif
/** /**
* *
* \warning Performing multiple operations concurrently on the same * \warning Performing multiple operations concurrently on the same
@ -58,6 +103,7 @@ typedef enum
*/ */
typedef struct mbedtls_ecdh_context typedef struct mbedtls_ecdh_context
{ {
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
mbedtls_ecp_group grp; /*!< The elliptic curve used. */ mbedtls_ecp_group grp; /*!< The elliptic curve used. */
mbedtls_mpi d; /*!< The private key. */ mbedtls_mpi d; /*!< The private key. */
mbedtls_ecp_point Q; /*!< The public key. */ mbedtls_ecp_point Q; /*!< The public key. */
@ -70,7 +116,26 @@ typedef struct mbedtls_ecdh_context
#if defined(MBEDTLS_ECP_RESTARTABLE) #if defined(MBEDTLS_ECP_RESTARTABLE)
int restart_enabled; /*!< The flag for restartable mode. */ int restart_enabled; /*!< The flag for restartable mode. */
mbedtls_ecp_restart_ctx rs; /*!< The restart context for EC computations. */ mbedtls_ecp_restart_ctx rs; /*!< The restart context for EC computations. */
#endif #endif /* MBEDTLS_ECP_RESTARTABLE */
#else
uint8_t point_format; /*!< The format of point export in TLS messages
as defined in RFC 4492. */
mbedtls_ecp_group_id grp_id;/*!< The elliptic curve used. */
mbedtls_ecdh_variant var; /*!< The ECDH implementation/structure used. */
union
{
mbedtls_ecdh_context_mbed mbed_ecdh;
} ctx; /*!< Implementation-specific context. The
context in use is specified by the \c var
field. */
#if defined(MBEDTLS_ECP_RESTARTABLE)
uint8_t restart_enabled; /*!< The flag for restartable mode. Functions of
an alternative implementation not supporting
restartable mode must return
MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED error
if this flag is set. */
#endif /* MBEDTLS_ECP_RESTARTABLE */
#endif /* MBEDTLS_ECDH_LEGACY_CONTEXT */
} }
mbedtls_ecdh_context; mbedtls_ecdh_context;
@ -134,6 +199,24 @@ int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z,
*/ */
void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx ); void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx );
/**
* \brief This function sets up the ECDH context with the information
* given.
*
* This function should be called after mbedtls_ecdh_init() but
* before mbedtls_ecdh_make_params(). There is no need to call
* this function before mbedtls_ecdh_read_params().
*
* This is the first function used by a TLS server for ECDHE
* ciphersuites.
*
* \param ctx The ECDH context to set up.
* \param grp_id The group id of the group to set up the context for.
*
* \return \c 0 on success.
*/
int mbedtls_ecdh_setup( mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id );
/** /**
* \brief This function frees a context. * \brief This function frees a context.
* *
@ -145,8 +228,8 @@ void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx );
* \brief This function generates a public key and a TLS * \brief This function generates a public key and a TLS
* ServerKeyExchange payload. * ServerKeyExchange payload.
* *
* This is the first function used by a TLS server for ECDHE * This is the second function used by a TLS server for ECDHE
* ciphersuites. * ciphersuites. (It is called after mbedtls_ecdh_setup().)
* *
* \note This function assumes that the ECP group (grp) of the * \note This function assumes that the ECP group (grp) of the
* \p ctx context has already been properly set, * \p ctx context has already been properly set,
@ -242,8 +325,9 @@ int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen,
* \brief This function parses and processes a TLS ClientKeyExchange * \brief This function parses and processes a TLS ClientKeyExchange
* payload. * payload.
* *
* This is the second function used by a TLS server for ECDH(E) * This is the third function used by a TLS server for ECDH(E)
* ciphersuites. * ciphersuites. (It is called after mbedtls_ecdh_setup() and
* mbedtls_ecdh_make_params().)
* *
* \see ecp.h * \see ecp.h
* *

View File

@ -159,6 +159,10 @@ mbedtls_ecp_point;
* additions or subtractions. Therefore, it is only an approximative modular * additions or subtractions. Therefore, it is only an approximative modular
* reduction. It must return 0 on success and non-zero on failure. * reduction. It must return 0 on success and non-zero on failure.
* *
* \note Alternative implementations must keep the group IDs distinct. If
* two group structures have the same ID, then they must be
* identical.
*
*/ */
typedef struct mbedtls_ecp_group typedef struct mbedtls_ecp_group
{ {
@ -632,7 +636,7 @@ int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, mbedtls_ecp_poi
/** /**
* \brief This function imports a point from a TLS ECPoint record. * \brief This function imports a point from a TLS ECPoint record.
* *
* \note On function return, \p buf is updated to point to immediately * \note On function return, \p *buf is updated to point immediately
* after the ECPoint record. * after the ECPoint record.
* *
* \param grp The ECP group used. * \param grp The ECP group used.
@ -641,7 +645,8 @@ int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, mbedtls_ecp_poi
* \param len The length of the buffer. * \param len The length of the buffer.
* *
* \return \c 0 on success. * \return \c 0 on success.
* \return An \c MBEDTLS_ERR_MPI_XXX error code on initialization failure. * \return An \c MBEDTLS_ERR_MPI_XXX error code on initialization
* failure.
* \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid.
*/ */
int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
@ -687,19 +692,39 @@ int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id id );
/** /**
* \brief This function sets a group from a TLS ECParameters record. * \brief This function sets a group from a TLS ECParameters record.
* *
* \note \p buf is updated to point right after the ECParameters record * \note \p buf is updated to point right after the ECParameters
* on exit. * record on exit.
* *
* \param grp The destination group. * \param grp The destination group.
* \param buf The address of the pointer to the start of the input buffer. * \param buf The address of the pointer to the start of the input buffer.
* \param len The length of the buffer. * \param len The length of the buffer.
* *
* \return \c 0 on success. * \return \c 0 on success.
* \return An \c MBEDTLS_ERR_MPI_XXX error code on initialization failure. * \return An \c MBEDTLS_ERR_MPI_XXX error code on initialization
* failure.
* \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid.
* \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the group is not
* recognised.
*/ */
int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, const unsigned char **buf, size_t len ); int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, const unsigned char **buf, size_t len );
/**
* \brief This function reads a group from a TLS ECParameters record.
*
* \note \p buf is updated to point right after the ECParameters
* record on exit.
*
* \param grp Output parameter to hold the group id.
* \param buf The address of the pointer to the start of the input buffer.
* \param len The length of the buffer.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid.
* \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the group is not
* recognised.
*/
int mbedtls_ecp_tls_read_group_id( mbedtls_ecp_group_id *grp,
const unsigned char **buf, size_t len );
/** /**
* \brief This function writes the TLS ECParameters record for a group. * \brief This function writes the TLS ECParameters record for a group.
* *

View File

@ -195,10 +195,13 @@ void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx,
* \param additional Additional data to update state with, or NULL * \param additional Additional data to update state with, or NULL
* \param add_len Length of additional data, or 0 * \param add_len Length of additional data, or 0
* *
* \return \c 0 on success, or an error from the underlying
* hash calculation.
*
* \note Additional data is optional, pass NULL and 0 as second * \note Additional data is optional, pass NULL and 0 as second
* third argument if no additional data is being used. * third argument if no additional data is being used.
*/ */
void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx, int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx,
const unsigned char *additional, size_t add_len ); const unsigned char *additional, size_t add_len );
/** /**
@ -257,6 +260,31 @@ int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len
*/ */
void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx ); void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx );
#if ! defined(MBEDTLS_DEPRECATED_REMOVED)
#if defined(MBEDTLS_DEPRECATED_WARNING)
#define MBEDTLS_DEPRECATED __attribute__((deprecated))
#else
#define MBEDTLS_DEPRECATED
#endif
/**
* \brief HMAC_DRBG update state
*
* \deprecated Superseded by mbedtls_hmac_drbg_update_ret()
* in 2.16.0.
*
* \param ctx HMAC_DRBG context
* \param additional Additional data to update state with, or NULL
* \param add_len Length of additional data, or 0
*
* \note Additional data is optional, pass NULL and 0 as second
* third argument if no additional data is being used.
*/
MBEDTLS_DEPRECATED void mbedtls_hmac_drbg_update(
mbedtls_hmac_drbg_context *ctx,
const unsigned char *additional, size_t add_len );
#undef MBEDTLS_DEPRECATED
#endif /* !MBEDTLS_DEPRECATED_REMOVED */
#if defined(MBEDTLS_FS_IO) #if defined(MBEDTLS_FS_IO)
/** /**
* \brief Write a seed file * \brief Write a seed file

View File

@ -46,6 +46,8 @@
extern "C" { extern "C" {
#endif #endif
#if defined(MBEDTLS_ASN1_PARSE_C)
/** /**
* \brief PKCS12 Password Based function (encryption / decryption) * \brief PKCS12 Password Based function (encryption / decryption)
* for pbeWithSHAAnd128BitRC4 * for pbeWithSHAAnd128BitRC4
@ -87,6 +89,8 @@ int mbedtls_pkcs12_pbe( mbedtls_asn1_buf *pbe_params, int mode,
const unsigned char *input, size_t len, const unsigned char *input, size_t len,
unsigned char *output ); unsigned char *output );
#endif /* MBEDTLS_ASN1_PARSE_C */
/** /**
* \brief The PKCS#12 derivation function uses a password and a salt * \brief The PKCS#12 derivation function uses a password and a salt
* to produce pseudo-random bits for a particular "purpose". * to produce pseudo-random bits for a particular "purpose".

View File

@ -44,6 +44,8 @@
extern "C" { extern "C" {
#endif #endif
#if defined(MBEDTLS_ASN1_PARSE_C)
/** /**
* \brief PKCS#5 PBES2 function * \brief PKCS#5 PBES2 function
* *
@ -62,6 +64,8 @@ int mbedtls_pkcs5_pbes2( const mbedtls_asn1_buf *pbe_params, int mode,
const unsigned char *data, size_t datalen, const unsigned char *data, size_t datalen,
unsigned char *output ); unsigned char *output );
#endif /* MBEDTLS_ASN1_PARSE_C */
/** /**
* \brief PKCS#5 PBKDF2 using HMAC * \brief PKCS#5 PBKDF2 using HMAC
* *

View File

@ -232,19 +232,34 @@ int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, const unsigned char *bu
size_t buflen ); size_t buflen );
/** /**
* \brief Parse one or more certificates and add them * \brief Parse one DER-encoded or one or more concatenated PEM-encoded
* to the chained list. Parses permissively. If some * certificates and add them to the chained list.
* certificates can be parsed, the result is the number
* of failed certificates it encountered. If none complete
* correctly, the first error is returned.
* *
* \param chain points to the start of the chain * For CRTs in PEM encoding, the function parses permissively:
* \param buf buffer holding the certificate data in PEM or DER format * if at least one certificate can be parsed, the function
* \param buflen size of the buffer * returns the number of certificates for which parsing failed
* (including the terminating null byte for PEM data) * (hence \c 0 if all certificates were parsed successfully).
* If no certificate could be parsed, the function returns
* the first (negative) error encountered during parsing.
*
* PEM encoded certificates may be interleaved by other data
* such as human readable descriptions of their content, as
* long as the certificates are enclosed in the PEM specific
* '-----{BEGIN/END} CERTIFICATE-----' delimiters.
*
* \param chain The chain to which to add the parsed certificates.
* \param buf The buffer holding the certificate data in PEM or DER format.
* For certificates in PEM encoding, this may be a concatenation
* of multiple certificates; for DER encoding, the buffer must
* comprise exactly one certificate.
* \param buflen The size of \p buf, including the terminating \c NULL byte
* in case of PEM encoded data.
*
* \return \c 0 if all certificates were parsed successfully.
* \return The (positive) number of certificates that couldn't
* be parsed if parsing was partly successful (see above).
* \return A negative X509 or PEM error code otherwise.
* *
* \return 0 if all certificates parsed successfully, a positive number
* if partly successful or a specific X509 or PEM error code
*/ */
int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen ); int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen );

View File

@ -331,14 +331,36 @@ int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start,
return( (int) len ); return( (int) len );
} }
mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( mbedtls_asn1_named_data **head,
/* This is a copy of the ASN.1 parsing function mbedtls_asn1_find_named_data(),
* which is replicated to avoid a dependency ASN1_WRITE_C on ASN1_PARSE_C. */
static mbedtls_asn1_named_data *asn1_find_named_data(
mbedtls_asn1_named_data *list,
const char *oid, size_t len )
{
while( list != NULL )
{
if( list->oid.len == len &&
memcmp( list->oid.p, oid, len ) == 0 )
{
break;
}
list = list->next;
}
return( list );
}
mbedtls_asn1_named_data *mbedtls_asn1_store_named_data(
mbedtls_asn1_named_data **head,
const char *oid, size_t oid_len, const char *oid, size_t oid_len,
const unsigned char *val, const unsigned char *val,
size_t val_len ) size_t val_len )
{ {
mbedtls_asn1_named_data *cur; mbedtls_asn1_named_data *cur;
if( ( cur = mbedtls_asn1_find_named_data( *head, oid, oid_len ) ) == NULL ) if( ( cur = asn1_find_named_data( *head, oid, oid_len ) ) == NULL )
{ {
// Add new entry if not present yet based on OID // Add new entry if not present yet based on OID
// //

View File

@ -321,6 +321,10 @@ int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 ); return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
} }
/* Get a specific byte, without range checks. */
#define GET_BYTE( X, i ) \
( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
/* /*
* Set a bit to a specific value of 0 or 1 * Set a bit to a specific value of 0 or 1
*/ */
@ -704,19 +708,40 @@ cleanup:
/* /*
* Export X into unsigned binary data, big endian * Export X into unsigned binary data, big endian
*/ */
int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen ) int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
unsigned char *buf, size_t buflen )
{ {
size_t i, j, n; size_t stored_bytes = X->n * ciL;
size_t bytes_to_copy;
unsigned char *p;
size_t i;
n = mbedtls_mpi_size( X ); if( stored_bytes < buflen )
{
if( buflen < n ) /* There is enough space in the output buffer. Write initial
* null bytes and record the position at which to start
* writing the significant bytes. In this case, the execution
* trace of this function does not depend on the value of the
* number. */
bytes_to_copy = stored_bytes;
p = buf + buflen - stored_bytes;
memset( buf, 0, buflen - stored_bytes );
}
else
{
/* The output buffer is smaller than the allocated size of X.
* However X may fit if its leading bytes are zero. */
bytes_to_copy = buflen;
p = buf;
for( i = bytes_to_copy; i < stored_bytes; i++ )
{
if( GET_BYTE( X, i ) != 0 )
return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
}
}
memset( buf, 0, buflen ); for( i = 0; i < bytes_to_copy; i++ )
p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
return( 0 ); return( 0 );
} }

View File

@ -299,9 +299,7 @@ static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
* Crypt counter block * Crypt counter block
*/ */
if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ) ) != 0 ) if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ) ) != 0 )
{ goto exit;
return( ret );
}
p += MBEDTLS_CTR_DRBG_BLOCKSIZE; p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
} }
@ -313,12 +311,12 @@ static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
* Update key and counter * Update key and counter
*/ */
if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
{ goto exit;
return( ret );
}
memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE ); memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE );
return( 0 ); exit:
mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
return( ret );
} }
/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2) /* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
@ -333,22 +331,38 @@ static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
* and with outputs * and with outputs
* ctx = initial_working_state * ctx = initial_working_state
*/ */
void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
const unsigned char *additional, size_t add_len ) const unsigned char *additional,
size_t add_len )
{ {
unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
int ret;
if( add_len > 0 ) if( add_len == 0 )
return( 0 );
if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
goto exit;
if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
goto exit;
exit:
mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
return( ret );
}
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
const unsigned char *additional,
size_t add_len )
{ {
/* MAX_INPUT would be more logical here, but we have to match /* MAX_INPUT would be more logical here, but we have to match
* block_cipher_df()'s limits since we can't propagate errors */ * block_cipher_df()'s limits since we can't propagate errors */
if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT; add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
(void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
block_cipher_df( add_input, additional, add_len );
ctr_drbg_update_internal( ctx, add_input );
}
} }
#endif /* MBEDTLS_DEPRECATED_REMOVED */
/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2) /* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
* mbedtls_ctr_drbg_reseed(ctx, additional, len) * mbedtls_ctr_drbg_reseed(ctx, additional, len)
@ -399,20 +413,18 @@ int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
* Reduce to 384 bits * Reduce to 384 bits
*/ */
if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 ) if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
{ goto exit;
return( ret );
}
/* /*
* Update state * Update state
*/ */
if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 ) if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
{ goto exit;
return( ret );
}
ctx->reseed_counter = 1; ctx->reseed_counter = 1;
return( 0 ); exit:
mbedtls_platform_zeroize( seed, sizeof( seed ) );
return( ret );
} }
/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2) /* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
@ -467,13 +479,9 @@ int mbedtls_ctr_drbg_random_with_add( void *p_rng,
if( add_len > 0 ) if( add_len > 0 )
{ {
if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 ) if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
{ goto exit;
return( ret );
}
if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
{ goto exit;
return( ret );
}
} }
while( output_len > 0 ) while( output_len > 0 )
@ -489,9 +497,7 @@ int mbedtls_ctr_drbg_random_with_add( void *p_rng,
* Crypt counter block * Crypt counter block
*/ */
if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 ) if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 )
{ goto exit;
return( ret );
}
use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
output_len; output_len;
@ -504,12 +510,13 @@ int mbedtls_ctr_drbg_random_with_add( void *p_rng,
} }
if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
{ goto exit;
return( ret );
}
ctx->reseed_counter++; ctx->reseed_counter++;
exit:
mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
return( 0 ); return( 0 );
} }
@ -561,35 +568,36 @@ exit:
int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ) int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
{ {
int ret = 0; int ret = 0;
FILE *f; FILE *f = NULL;
size_t n; size_t n;
unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ]; unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
unsigned char c;
if( ( f = fopen( path, "rb" ) ) == NULL ) if( ( f = fopen( path, "rb" ) ) == NULL )
return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR ); return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
fseek( f, 0, SEEK_END ); n = fread( buf, 1, sizeof( buf ), f );
n = (size_t) ftell( f ); if( fread( &c, 1, 1, f ) != 0 )
fseek( f, 0, SEEK_SET );
if( n > MBEDTLS_CTR_DRBG_MAX_INPUT )
{ {
fclose( f ); ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); goto exit;
} }
if( n == 0 || ferror( f ) )
if( fread( buf, 1, n, f ) != n ) {
ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
else goto exit;
mbedtls_ctr_drbg_update( ctx, buf, n ); }
fclose( f ); fclose( f );
f = NULL;
ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
exit:
mbedtls_platform_zeroize( buf, sizeof( buf ) ); mbedtls_platform_zeroize( buf, sizeof( buf ) );
if( f != NULL )
fclose( f );
if( ret != 0 ) if( ret != 0 )
return( ret ); return( ret );
return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) ); return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
} }
#endif /* MBEDTLS_FS_IO */ #endif /* MBEDTLS_FS_IO */

View File

@ -365,4 +365,54 @@ void mbedtls_debug_print_crt( const mbedtls_ssl_context *ssl, int level,
} }
#endif /* MBEDTLS_X509_CRT_PARSE_C */ #endif /* MBEDTLS_X509_CRT_PARSE_C */
#if defined(MBEDTLS_ECDH_C)
static void mbedtls_debug_printf_ecdh_internal( const mbedtls_ssl_context *ssl,
int level, const char *file,
int line,
const mbedtls_ecdh_context *ecdh,
mbedtls_debug_ecdh_attr attr )
{
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
const mbedtls_ecdh_context* ctx = ecdh;
#else
const mbedtls_ecdh_context_mbed* ctx = &ecdh->ctx.mbed_ecdh;
#endif
switch( attr )
{
case MBEDTLS_DEBUG_ECDH_Q:
mbedtls_debug_print_ecp( ssl, level, file, line, "ECDH: Q",
&ctx->Q );
break;
case MBEDTLS_DEBUG_ECDH_QP:
mbedtls_debug_print_ecp( ssl, level, file, line, "ECDH: Qp",
&ctx->Qp );
break;
case MBEDTLS_DEBUG_ECDH_Z:
mbedtls_debug_print_mpi( ssl, level, file, line, "ECDH: z",
&ctx->z );
break;
default:
break;
}
}
void mbedtls_debug_printf_ecdh( const mbedtls_ssl_context *ssl, int level,
const char *file, int line,
const mbedtls_ecdh_context *ecdh,
mbedtls_debug_ecdh_attr attr )
{
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
mbedtls_debug_printf_ecdh_internal( ssl, level, file, line, ecdh, attr );
#else
switch( ecdh->var )
{
default:
mbedtls_debug_printf_ecdh_internal( ssl, level, file, line, ecdh,
attr );
}
#endif
}
#endif /* MBEDTLS_ECDH_C */
#endif /* MBEDTLS_DEBUG_C */ #endif /* MBEDTLS_DEBUG_C */

View File

@ -38,6 +38,10 @@
#include <string.h> #include <string.h>
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
typedef mbedtls_ecdh_context mbedtls_ecdh_context_mbed;
#endif
#if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) #if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT)
/* /*
* Generate public key (restartable version) * Generate public key (restartable version)
@ -124,43 +128,84 @@ int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z,
} }
#endif /* !MBEDTLS_ECDH_COMPUTE_SHARED_ALT */ #endif /* !MBEDTLS_ECDH_COMPUTE_SHARED_ALT */
/* static void ecdh_init_internal( mbedtls_ecdh_context_mbed *ctx )
* Initialize context
*/
void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx )
{ {
mbedtls_ecp_group_init( &ctx->grp ); mbedtls_ecp_group_init( &ctx->grp );
mbedtls_mpi_init( &ctx->d ); mbedtls_mpi_init( &ctx->d );
mbedtls_ecp_point_init( &ctx->Q ); mbedtls_ecp_point_init( &ctx->Q );
mbedtls_ecp_point_init( &ctx->Qp ); mbedtls_ecp_point_init( &ctx->Qp );
mbedtls_mpi_init( &ctx->z ); mbedtls_mpi_init( &ctx->z );
ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
mbedtls_ecp_point_init( &ctx->Vi );
mbedtls_ecp_point_init( &ctx->Vf );
mbedtls_mpi_init( &ctx->_d );
#if defined(MBEDTLS_ECP_RESTARTABLE) #if defined(MBEDTLS_ECP_RESTARTABLE)
ctx->restart_enabled = 0;
mbedtls_ecp_restart_init( &ctx->rs ); mbedtls_ecp_restart_init( &ctx->rs );
#endif #endif
} }
/* /*
* Free context * Initialize context
*/ */
void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx ) void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx )
{
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
ecdh_init_internal( ctx );
mbedtls_ecp_point_init( &ctx->Vi );
mbedtls_ecp_point_init( &ctx->Vf );
mbedtls_mpi_init( &ctx->_d );
#else
memset( ctx, 0, sizeof( mbedtls_ecdh_context ) );
ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
#endif
ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
#if defined(MBEDTLS_ECP_RESTARTABLE)
ctx->restart_enabled = 0;
#endif
}
static int ecdh_setup_internal( mbedtls_ecdh_context_mbed *ctx,
mbedtls_ecp_group_id grp_id )
{
int ret;
ret = mbedtls_ecp_group_load( &ctx->grp, grp_id );
if( ret != 0 )
{
return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
}
return( 0 );
}
/*
* Setup context
*/
int mbedtls_ecdh_setup( mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id )
{ {
if( ctx == NULL ) if( ctx == NULL )
return; return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
return( ecdh_setup_internal( ctx, grp_id ) );
#else
switch( grp_id )
{
default:
ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0;
ctx->grp_id = grp_id;
ecdh_init_internal( &ctx->ctx.mbed_ecdh );
return( ecdh_setup_internal( &ctx->ctx.mbed_ecdh, grp_id ) );
}
#endif
}
static void ecdh_free_internal( mbedtls_ecdh_context_mbed *ctx )
{
mbedtls_ecp_group_free( &ctx->grp ); mbedtls_ecp_group_free( &ctx->grp );
mbedtls_mpi_free( &ctx->d ); mbedtls_mpi_free( &ctx->d );
mbedtls_ecp_point_free( &ctx->Q ); mbedtls_ecp_point_free( &ctx->Q );
mbedtls_ecp_point_free( &ctx->Qp ); mbedtls_ecp_point_free( &ctx->Qp );
mbedtls_mpi_free( &ctx->z ); mbedtls_mpi_free( &ctx->z );
mbedtls_ecp_point_free( &ctx->Vi );
mbedtls_ecp_point_free( &ctx->Vf );
mbedtls_mpi_free( &ctx->_d );
#if defined(MBEDTLS_ECP_RESTARTABLE) #if defined(MBEDTLS_ECP_RESTARTABLE)
mbedtls_ecp_restart_free( &ctx->rs ); mbedtls_ecp_restart_free( &ctx->rs );
@ -173,21 +218,50 @@ void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx )
*/ */
void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx ) void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx )
{ {
if( ctx == NULL )
return;
ctx->restart_enabled = 1; ctx->restart_enabled = 1;
} }
#endif #endif
/* /*
* Setup and write the ServerKeyExhange parameters (RFC 4492) * Free context
* struct {
* ECParameters curve_params;
* ECPoint public;
* } ServerECDHParams;
*/ */
int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx )
{
if( ctx == NULL )
return;
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
mbedtls_ecp_point_free( &ctx->Vi );
mbedtls_ecp_point_free( &ctx->Vf );
mbedtls_mpi_free( &ctx->_d );
ecdh_free_internal( ctx );
#else
switch( ctx->var )
{
case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
ecdh_free_internal( &ctx->ctx.mbed_ecdh );
break;
default:
break;
}
ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
ctx->grp_id = MBEDTLS_ECP_DP_NONE;
#endif
}
static int ecdh_make_params_internal( mbedtls_ecdh_context_mbed *ctx,
size_t *olen, int point_format,
unsigned char *buf, size_t blen, unsigned char *buf, size_t blen,
int (*f_rng)(void *, unsigned char *, size_t), int (*f_rng)(void *,
void *p_rng ) unsigned char *,
size_t),
void *p_rng,
int restart_enabled )
{ {
int ret; int ret;
size_t grp_len, pt_len; size_t grp_len, pt_len;
@ -195,12 +269,14 @@ int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen,
mbedtls_ecp_restart_ctx *rs_ctx = NULL; mbedtls_ecp_restart_ctx *rs_ctx = NULL;
#endif #endif
if( ctx == NULL || ctx->grp.pbits == 0 ) if( ctx->grp.pbits == 0 )
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
#if defined(MBEDTLS_ECP_RESTARTABLE) #if defined(MBEDTLS_ECP_RESTARTABLE)
if( ctx->restart_enabled ) if( restart_enabled )
rs_ctx = &ctx->rs; rs_ctx = &ctx->rs;
#else
(void) restart_enabled;
#endif #endif
@ -214,14 +290,14 @@ int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen,
return( ret ); return( ret );
#endif /* MBEDTLS_ECP_RESTARTABLE */ #endif /* MBEDTLS_ECP_RESTARTABLE */
if( ( ret = mbedtls_ecp_tls_write_group( &ctx->grp, &grp_len, buf, blen ) ) if( ( ret = mbedtls_ecp_tls_write_group( &ctx->grp, &grp_len, buf,
!= 0 ) blen ) ) != 0 )
return( ret ); return( ret );
buf += grp_len; buf += grp_len;
blen -= grp_len; blen -= grp_len;
if( ( ret = mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, ctx->point_format, if( ( ret = mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, point_format,
&pt_len, buf, blen ) ) != 0 ) &pt_len, buf, blen ) ) != 0 )
return( ret ); return( ret );
@ -229,6 +305,54 @@ int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen,
return( 0 ); return( 0 );
} }
/*
* Setup and write the ServerKeyExhange parameters (RFC 4492)
* struct {
* ECParameters curve_params;
* ECPoint public;
* } ServerECDHParams;
*/
int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen,
unsigned char *buf, size_t blen,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
int restart_enabled = 0;
if( ctx == NULL )
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
#if defined(MBEDTLS_ECP_RESTARTABLE)
restart_enabled = ctx->restart_enabled;
#else
(void) restart_enabled;
#endif
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
return( ecdh_make_params_internal( ctx, olen, ctx->point_format, buf, blen,
f_rng, p_rng, restart_enabled ) );
#else
switch( ctx->var )
{
case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
return( ecdh_make_params_internal( &ctx->ctx.mbed_ecdh, olen,
ctx->point_format, buf, blen,
f_rng, p_rng,
restart_enabled ) );
default:
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
}
#endif
}
static int ecdh_read_params_internal( mbedtls_ecdh_context_mbed *ctx,
const unsigned char **buf,
const unsigned char *end )
{
return( mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, buf,
end - *buf ) );
}
/* /*
* Read the ServerKeyExhange parameters (RFC 4492) * Read the ServerKeyExhange parameters (RFC 4492)
* struct { * struct {
@ -237,31 +361,42 @@ int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen,
* } ServerECDHParams; * } ServerECDHParams;
*/ */
int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx, int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx,
const unsigned char **buf, const unsigned char *end ) const unsigned char **buf,
const unsigned char *end )
{ {
int ret; int ret;
mbedtls_ecp_group_id grp_id;
if( ( ret = mbedtls_ecp_tls_read_group( &ctx->grp, buf, end - *buf ) ) != 0 ) if( ctx == NULL )
return( ret ); return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, buf, end - *buf ) ) if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, end - *buf ) )
!= 0 ) != 0 )
return( ret ); return( ret );
return( 0 ); if( ( ret = mbedtls_ecdh_setup( ctx, grp_id ) ) != 0 )
return( ret );
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
return( ecdh_read_params_internal( ctx, buf, end ) );
#else
switch( ctx->var )
{
case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
return( ecdh_read_params_internal( &ctx->ctx.mbed_ecdh,
buf, end ) );
default:
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
}
#endif
} }
/* static int ecdh_get_params_internal( mbedtls_ecdh_context_mbed *ctx,
* Get parameters from a keypair const mbedtls_ecp_keypair *key,
*/
int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypair *key,
mbedtls_ecdh_side side ) mbedtls_ecdh_side side )
{ {
int ret; int ret;
if( ( ret = mbedtls_ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 )
return( ret );
/* If it's not our key, just import the public part as Qp */ /* If it's not our key, just import the public part as Qp */
if( side == MBEDTLS_ECDH_THEIRS ) if( side == MBEDTLS_ECDH_THEIRS )
return( mbedtls_ecp_copy( &ctx->Qp, &key->Q ) ); return( mbedtls_ecp_copy( &ctx->Qp, &key->Q ) );
@ -278,24 +413,56 @@ int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypai
} }
/* /*
* Setup and export the client public value * Get parameters from a keypair
*/ */
int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen, int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx,
const mbedtls_ecp_keypair *key,
mbedtls_ecdh_side side )
{
int ret;
if( ctx == NULL )
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
if( ( ret = mbedtls_ecdh_setup( ctx, key->grp.id ) ) != 0 )
return( ret );
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
return( ecdh_get_params_internal( ctx, key, side ) );
#else
switch( ctx->var )
{
case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
return( ecdh_get_params_internal( &ctx->ctx.mbed_ecdh,
key, side ) );
default:
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
}
#endif
}
static int ecdh_make_public_internal( mbedtls_ecdh_context_mbed *ctx,
size_t *olen, int point_format,
unsigned char *buf, size_t blen, unsigned char *buf, size_t blen,
int (*f_rng)(void *, unsigned char *, size_t), int (*f_rng)(void *,
void *p_rng ) unsigned char *,
size_t),
void *p_rng,
int restart_enabled )
{ {
int ret; int ret;
#if defined(MBEDTLS_ECP_RESTARTABLE) #if defined(MBEDTLS_ECP_RESTARTABLE)
mbedtls_ecp_restart_ctx *rs_ctx = NULL; mbedtls_ecp_restart_ctx *rs_ctx = NULL;
#endif #endif
if( ctx == NULL || ctx->grp.pbits == 0 ) if( ctx->grp.pbits == 0 )
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
#if defined(MBEDTLS_ECP_RESTARTABLE) #if defined(MBEDTLS_ECP_RESTARTABLE)
if( ctx->restart_enabled ) if( restart_enabled )
rs_ctx = &ctx->rs; rs_ctx = &ctx->rs;
#else
(void) restart_enabled;
#endif #endif
#if defined(MBEDTLS_ECP_RESTARTABLE) #if defined(MBEDTLS_ECP_RESTARTABLE)
@ -308,23 +475,52 @@ int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen,
return( ret ); return( ret );
#endif /* MBEDTLS_ECP_RESTARTABLE */ #endif /* MBEDTLS_ECP_RESTARTABLE */
return mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, ctx->point_format, return mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, point_format, olen,
olen, buf, blen ); buf, blen );
} }
/* /*
* Parse and import the client's public value * Setup and export the client public value
*/ */
int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx, int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen,
unsigned char *buf, size_t blen,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
int restart_enabled = 0;
if( ctx == NULL )
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
#if defined(MBEDTLS_ECP_RESTARTABLE)
restart_enabled = ctx->restart_enabled;
#endif
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
return( ecdh_make_public_internal( ctx, olen, ctx->point_format, buf, blen,
f_rng, p_rng, restart_enabled ) );
#else
switch( ctx->var )
{
case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
return( ecdh_make_public_internal( &ctx->ctx.mbed_ecdh, olen,
ctx->point_format, buf, blen,
f_rng, p_rng,
restart_enabled ) );
default:
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
}
#endif
}
static int ecdh_read_public_internal( mbedtls_ecdh_context_mbed *ctx,
const unsigned char *buf, size_t blen ) const unsigned char *buf, size_t blen )
{ {
int ret; int ret;
const unsigned char *p = buf; const unsigned char *p = buf;
if( ctx == NULL ) if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, &p,
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); blen ) ) != 0 )
if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, &p, blen ) ) != 0 )
return( ret ); return( ret );
if( (size_t)( p - buf ) != blen ) if( (size_t)( p - buf ) != blen )
@ -334,12 +530,36 @@ int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx,
} }
/* /*
* Derive and export the shared secret * Parse and import the client's public value
*/ */
int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen, int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx,
unsigned char *buf, size_t blen, const unsigned char *buf, size_t blen )
int (*f_rng)(void *, unsigned char *, size_t), {
void *p_rng ) if( ctx == NULL )
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
return( ecdh_read_public_internal( ctx, buf, blen ) );
#else
switch( ctx->var )
{
case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
return( ecdh_read_public_internal( &ctx->ctx.mbed_ecdh,
buf, blen ) );
default:
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
}
#endif
}
static int ecdh_calc_secret_internal( mbedtls_ecdh_context_mbed *ctx,
size_t *olen, unsigned char *buf,
size_t blen,
int (*f_rng)(void *,
unsigned char *,
size_t),
void *p_rng,
int restart_enabled )
{ {
int ret; int ret;
#if defined(MBEDTLS_ECP_RESTARTABLE) #if defined(MBEDTLS_ECP_RESTARTABLE)
@ -350,13 +570,16 @@ int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen,
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
#if defined(MBEDTLS_ECP_RESTARTABLE) #if defined(MBEDTLS_ECP_RESTARTABLE)
if( ctx->restart_enabled ) if( restart_enabled )
rs_ctx = &ctx->rs; rs_ctx = &ctx->rs;
#else
(void) restart_enabled;
#endif #endif
#if defined(MBEDTLS_ECP_RESTARTABLE) #if defined(MBEDTLS_ECP_RESTARTABLE)
if( ( ret = ecdh_compute_shared_restartable( &ctx->grp, if( ( ret = ecdh_compute_shared_restartable( &ctx->grp, &ctx->z, &ctx->Qp,
&ctx->z, &ctx->Qp, &ctx->d, f_rng, p_rng, rs_ctx ) ) != 0 ) &ctx->d, f_rng, p_rng,
rs_ctx ) ) != 0 )
{ {
return( ret ); return( ret );
} }
@ -375,4 +598,37 @@ int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen,
return mbedtls_mpi_write_binary( &ctx->z, buf, *olen ); return mbedtls_mpi_write_binary( &ctx->z, buf, *olen );
} }
/*
* Derive and export the shared secret
*/
int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen,
unsigned char *buf, size_t blen,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
int restart_enabled = 0;
if( ctx == NULL )
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
#if defined(MBEDTLS_ECP_RESTARTABLE)
restart_enabled = ctx->restart_enabled;
#endif
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
return( ecdh_calc_secret_internal( ctx, olen, buf, blen, f_rng, p_rng,
restart_enabled ) );
#else
switch( ctx->var )
{
case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
return( ecdh_calc_secret_internal( &ctx->ctx.mbed_ecdh, olen, buf,
blen, f_rng, p_rng,
restart_enabled ) );
default:
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
}
#endif
}
#endif /* MBEDTLS_ECDH_C */ #endif /* MBEDTLS_ECDH_C */

View File

@ -47,6 +47,35 @@
#include MBEDTLS_CONFIG_FILE #include MBEDTLS_CONFIG_FILE
#endif #endif
/**
* \brief Function level alternative implementation.
*
* The MBEDTLS_ECP_INTERNAL_ALT macro enables alternative implementations to
* replace certain functions in this module. The alternative implementations are
* typically hardware accelerators and need to activate the hardware before the
* computation starts and deactivate it after it finishes. The
* mbedtls_internal_ecp_init() and mbedtls_internal_ecp_free() functions serve
* this purpose.
*
* To preserve the correct functionality the following conditions must hold:
*
* - The alternative implementation must be activated by
* mbedtls_internal_ecp_init() before any of the replaceable functions is
* called.
* - mbedtls_internal_ecp_free() must \b only be called when the alternative
* implementation is activated.
* - mbedtls_internal_ecp_init() must \b not be called when the alternative
* implementation is activated.
* - Public functions must not return while the alternative implementation is
* activated.
* - Replaceable functions are guarded by \c MBEDTLS_ECP_XXX_ALT macros and
* before calling them an \code if( mbedtls_internal_ecp_grp_capable( grp ) )
* \endcode ensures that the alternative implementation supports the current
* group.
*/
#if defined(MBEDTLS_ECP_INTERNAL_ALT)
#endif
#if defined(MBEDTLS_ECP_C) #if defined(MBEDTLS_ECP_C)
#include "mbedtls/ecp.h" #include "mbedtls/ecp.h"
@ -645,7 +674,7 @@ int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt )
} }
/* /*
* Compare two points lazyly * Compare two points lazily
*/ */
int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P, int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P,
const mbedtls_ecp_point *Q ) const mbedtls_ecp_point *Q )
@ -833,7 +862,24 @@ int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp
/* /*
* Set a group from an ECParameters record (RFC 4492) * Set a group from an ECParameters record (RFC 4492)
*/ */
int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, const unsigned char **buf, size_t len ) int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp,
const unsigned char **buf, size_t len )
{
int ret;
mbedtls_ecp_group_id grp_id;
if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, len ) ) != 0 )
return( ret );
return mbedtls_ecp_group_load( grp, grp_id );
}
/*
* Read a group id from an ECParameters record (RFC 4492) and convert it to
* mbedtls_ecp_group_id.
*/
int mbedtls_ecp_tls_read_group_id( mbedtls_ecp_group_id *grp,
const unsigned char **buf, size_t len )
{ {
uint16_t tls_id; uint16_t tls_id;
const mbedtls_ecp_curve_info *curve_info; const mbedtls_ecp_curve_info *curve_info;
@ -860,7 +906,9 @@ int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, const unsigned char **bu
if( ( curve_info = mbedtls_ecp_curve_info_from_tls_id( tls_id ) ) == NULL ) if( ( curve_info = mbedtls_ecp_curve_info_from_tls_id( tls_id ) ) == NULL )
return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
return mbedtls_ecp_group_load( grp, curve_info->grp_id ); *grp = curve_info->grp_id;
return( 0 );
} }
/* /*
@ -2393,11 +2441,6 @@ int mbedtls_ecp_muladd_restartable(
mbedtls_ecp_point_init( &mP ); mbedtls_ecp_point_init( &mP );
#if defined(MBEDTLS_ECP_INTERNAL_ALT)
if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) )
MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
#endif /* MBEDTLS_ECP_INTERNAL_ALT */
ECP_RS_ENTER( ma ); ECP_RS_ENTER( ma );
#if defined(MBEDTLS_ECP_RESTARTABLE) #if defined(MBEDTLS_ECP_RESTARTABLE)
@ -2425,6 +2468,12 @@ int mbedtls_ecp_muladd_restartable(
mul2: mul2:
#endif #endif
MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pR, n, Q, rs_ctx ) ); MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pR, n, Q, rs_ctx ) );
#if defined(MBEDTLS_ECP_INTERNAL_ALT)
if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) )
MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
#endif /* MBEDTLS_ECP_INTERNAL_ALT */
#if defined(MBEDTLS_ECP_RESTARTABLE) #if defined(MBEDTLS_ECP_RESTARTABLE)
if( rs_ctx != NULL && rs_ctx->ma != NULL ) if( rs_ctx != NULL && rs_ctx->ma != NULL )
rs_ctx->ma->state = ecp_rsma_add; rs_ctx->ma->state = ecp_rsma_add;

View File

@ -99,6 +99,7 @@ int mbedtls_platform_entropy_poll( void *data, unsigned char *output, size_t len
#include <sys/syscall.h> #include <sys/syscall.h>
#if defined(SYS_getrandom) #if defined(SYS_getrandom)
#define HAVE_GETRANDOM #define HAVE_GETRANDOM
#include <errno.h>
static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags ) static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags )
{ {
@ -108,47 +109,8 @@ static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags )
memset( buf, 0, buflen ); memset( buf, 0, buflen );
#endif #endif
#endif #endif
return( syscall( SYS_getrandom, buf, buflen, flags ) ); 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 /* SYS_getrandom */
#endif /* __linux__ */ #endif /* __linux__ */
@ -159,22 +121,21 @@ int mbedtls_platform_entropy_poll( void *data,
{ {
FILE *file; FILE *file;
size_t read_len; size_t read_len;
int ret;
((void) data); ((void) data);
#if defined(HAVE_GETRANDOM) #if defined(HAVE_GETRANDOM)
if( has_getrandom == -1 ) ret = getrandom_wrapper( output, len, 0 );
has_getrandom = ( check_version_3_17_plus() == 0 ); if( ret >= 0 )
if( has_getrandom )
{ {
int ret;
if( ( ret = getrandom_wrapper( output, len, 0 ) ) < 0 )
return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
*olen = ret; *olen = ret;
return( 0 ); return( 0 );
} }
else if( errno != ENOSYS )
return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
/* Fall through if the system call isn't known. */
#else
((void) ret);
#endif /* HAVE_GETRANDOM */ #endif /* HAVE_GETRANDOM */
*olen = 0; *olen = 0;

View File

@ -66,31 +66,60 @@ void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx )
/* /*
* HMAC_DRBG update, using optional additional data (10.1.2.2) * HMAC_DRBG update, using optional additional data (10.1.2.2)
*/ */
void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx, int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx,
const unsigned char *additional, size_t add_len ) const unsigned char *additional,
size_t add_len )
{ {
size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info ); size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1; unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
unsigned char sep[1]; unsigned char sep[1];
unsigned char K[MBEDTLS_MD_MAX_SIZE]; unsigned char K[MBEDTLS_MD_MAX_SIZE];
int ret;
for( sep[0] = 0; sep[0] < rounds; sep[0]++ ) for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
{ {
/* Step 1 or 4 */ /* Step 1 or 4 */
mbedtls_md_hmac_reset( &ctx->md_ctx ); if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); goto exit;
mbedtls_md_hmac_update( &ctx->md_ctx, sep, 1 ); if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
ctx->V, md_len ) ) != 0 )
goto exit;
if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
sep, 1 ) ) != 0 )
goto exit;
if( rounds == 2 ) if( rounds == 2 )
mbedtls_md_hmac_update( &ctx->md_ctx, additional, add_len ); {
mbedtls_md_hmac_finish( &ctx->md_ctx, K ); if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
additional, add_len ) ) != 0 )
goto exit;
}
if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, K ) ) != 0 )
goto exit;
/* Step 2 or 5 */ /* Step 2 or 5 */
mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len ); if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len ) ) != 0 )
mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); goto exit;
mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ); if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
ctx->V, md_len ) ) != 0 )
goto exit;
if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
goto exit;
} }
exit:
mbedtls_platform_zeroize( K, sizeof( K ) );
return( ret );
} }
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx,
const unsigned char *additional,
size_t add_len )
{
(void) mbedtls_hmac_drbg_update_ret( ctx, additional, add_len );
}
#endif /* MBEDTLS_DEPRECATED_REMOVED */
/* /*
* Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA) * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
*/ */
@ -108,10 +137,13 @@ int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx,
* Use the V memory location, which is currently all 0, to initialize the * Use the V memory location, which is currently all 0, to initialize the
* MD context with an all-zero key. Then set V to its initial value. * MD context with an all-zero key. Then set V to its initial value.
*/ */
mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, mbedtls_md_get_size( md_info ) ); if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V,
mbedtls_md_get_size( md_info ) ) ) != 0 )
return( ret );
memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) ); memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) );
mbedtls_hmac_drbg_update( ctx, data, data_len ); if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, data, data_len ) ) != 0 )
return( ret );
return( 0 ); return( 0 );
} }
@ -124,6 +156,7 @@ int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
{ {
unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT]; unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
size_t seedlen; size_t seedlen;
int ret;
/* III. Check input length */ /* III. Check input length */
if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT || if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||
@ -135,7 +168,8 @@ int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT ); memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT );
/* IV. Gather entropy_len bytes of entropy for the seed */ /* IV. Gather entropy_len bytes of entropy for the seed */
if( ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) != 0 ) if( ( ret = ctx->f_entropy( ctx->p_entropy,
seed, ctx->entropy_len ) ) != 0 )
return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED ); return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
seedlen = ctx->entropy_len; seedlen = ctx->entropy_len;
@ -148,13 +182,16 @@ int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
} }
/* 2. Update state */ /* 2. Update state */
mbedtls_hmac_drbg_update( ctx, seed, seedlen ); if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, seed, seedlen ) ) != 0 )
goto exit;
/* 3. Reset reseed_counter */ /* 3. Reset reseed_counter */
ctx->reseed_counter = 1; ctx->reseed_counter = 1;
exit:
/* 4. Done */ /* 4. Done */
return( 0 ); mbedtls_platform_zeroize( seed, seedlen );
return( ret );
} }
/* /*
@ -180,7 +217,8 @@ int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
* Use the V memory location, which is currently all 0, to initialize the * Use the V memory location, which is currently all 0, to initialize the
* MD context with an all-zero key. Then set V to its initial value. * MD context with an all-zero key. Then set V to its initial value.
*/ */
mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ); if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ) ) != 0 )
return( ret );
memset( ctx->V, 0x01, md_size ); memset( ctx->V, 0x01, md_size );
ctx->f_entropy = f_entropy; ctx->f_entropy = f_entropy;
@ -273,16 +311,24 @@ int mbedtls_hmac_drbg_random_with_add( void *p_rng,
/* 2. Use additional data if any */ /* 2. Use additional data if any */
if( additional != NULL && add_len != 0 ) if( additional != NULL && add_len != 0 )
mbedtls_hmac_drbg_update( ctx, additional, add_len ); {
if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
additional, add_len ) ) != 0 )
goto exit;
}
/* 3, 4, 5. Generate bytes */ /* 3, 4, 5. Generate bytes */
while( left != 0 ) while( left != 0 )
{ {
size_t use_len = left > md_len ? md_len : left; size_t use_len = left > md_len ? md_len : left;
mbedtls_md_hmac_reset( &ctx->md_ctx ); if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); goto exit;
mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ); if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
ctx->V, md_len ) ) != 0 )
goto exit;
if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
goto exit;
memcpy( out, ctx->V, use_len ); memcpy( out, ctx->V, use_len );
out += use_len; out += use_len;
@ -290,13 +336,16 @@ int mbedtls_hmac_drbg_random_with_add( void *p_rng,
} }
/* 6. Update */ /* 6. Update */
mbedtls_hmac_drbg_update( ctx, additional, add_len ); if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
additional, add_len ) ) != 0 )
goto exit;
/* 7. Update reseed counter */ /* 7. Update reseed counter */
ctx->reseed_counter++; ctx->reseed_counter++;
exit:
/* 8. Done */ /* 8. Done */
return( 0 ); return( ret );
} }
/* /*
@ -368,35 +417,36 @@ exit:
int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ) int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
{ {
int ret = 0; int ret = 0;
FILE *f; FILE *f = NULL;
size_t n; size_t n;
unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ]; unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
unsigned char c;
if( ( f = fopen( path, "rb" ) ) == NULL ) if( ( f = fopen( path, "rb" ) ) == NULL )
return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR ); return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
fseek( f, 0, SEEK_END ); n = fread( buf, 1, sizeof( buf ), f );
n = (size_t) ftell( f ); if( fread( &c, 1, 1, f ) != 0 )
fseek( f, 0, SEEK_SET );
if( n > MBEDTLS_HMAC_DRBG_MAX_INPUT )
{ {
fclose( f ); ret = MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG ); goto exit;
} }
if( n == 0 || ferror( f ) )
if( fread( buf, 1, n, f ) != n ) {
ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR; ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
else goto exit;
mbedtls_hmac_drbg_update( ctx, buf, n ); }
fclose( f ); fclose( f );
f = NULL;
ret = mbedtls_hmac_drbg_update_ret( ctx, buf, n );
exit:
mbedtls_platform_zeroize( buf, sizeof( buf ) ); mbedtls_platform_zeroize( buf, sizeof( buf ) );
if( f != NULL )
fclose( f );
if( ret != 0 ) if( ret != 0 )
return( ret ); return( ret );
return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) ); return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) );
} }
#endif /* MBEDTLS_FS_IO */ #endif /* MBEDTLS_FS_IO */

View File

@ -48,6 +48,8 @@
#include "mbedtls/des.h" #include "mbedtls/des.h"
#endif #endif
#if defined(MBEDTLS_ASN1_PARSE_C)
static int pkcs12_parse_pbe_params( mbedtls_asn1_buf *params, static int pkcs12_parse_pbe_params( mbedtls_asn1_buf *params,
mbedtls_asn1_buf *salt, int *iterations ) mbedtls_asn1_buf *salt, int *iterations )
{ {
@ -226,6 +228,8 @@ exit:
return( ret ); return( ret );
} }
#endif /* MBEDTLS_ASN1_PARSE_C */
static void pkcs12_fill_buffer( unsigned char *data, size_t data_len, static void pkcs12_fill_buffer( unsigned char *data, size_t data_len,
const unsigned char *filler, size_t fill_len ) const unsigned char *filler, size_t fill_len )
{ {

View File

@ -54,22 +54,7 @@
#define mbedtls_printf printf #define mbedtls_printf printf
#endif #endif
#if !defined(MBEDTLS_ASN1_PARSE_C) #if defined(MBEDTLS_ASN1_PARSE_C)
int mbedtls_pkcs5_pbes2( const mbedtls_asn1_buf *pbe_params, int mode,
const unsigned char *pwd, size_t pwdlen,
const unsigned char *data, size_t datalen,
unsigned char *output )
{
((void) pbe_params);
((void) mode);
((void) pwd);
((void) pwdlen);
((void) data);
((void) datalen);
((void) output);
return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE );
}
#else
static int pkcs5_parse_pbkdf2_params( const mbedtls_asn1_buf *params, static int pkcs5_parse_pbkdf2_params( const mbedtls_asn1_buf *params,
mbedtls_asn1_buf *salt, int *iterations, mbedtls_asn1_buf *salt, int *iterations,
int *keylen, mbedtls_md_type_t *md_type ) int *keylen, mbedtls_md_type_t *md_type )

View File

@ -1392,6 +1392,97 @@ cleanup:
#endif /* MBEDTLS_PKCS1_V21 */ #endif /* MBEDTLS_PKCS1_V21 */
#if defined(MBEDTLS_PKCS1_V15) #if defined(MBEDTLS_PKCS1_V15)
/** Turn zero-or-nonzero into zero-or-all-bits-one, without branches.
*
* \param value The value to analyze.
* \return Zero if \p value is zero, otherwise all-bits-one.
*/
static unsigned all_or_nothing_int( unsigned value )
{
/* 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
return( - ( ( value | - value ) >> ( sizeof( value ) * 8 - 1 ) ) );
#if defined(_MSC_VER)
#pragma warning( pop )
#endif
}
/** Check whether a size is out of bounds, without branches.
*
* This is equivalent to `size > max`, but is likely to be compiled to
* to code using bitwise operation rather than a branch.
*
* \param size Size to check.
* \param max Maximum desired value for \p size.
* \return \c 0 if `size <= max`.
* \return \c 1 if `size > max`.
*/
static unsigned size_greater_than( size_t size, size_t max )
{
/* Return the sign bit (1 for negative) of (max - size). */
return( ( max - size ) >> ( sizeof( size_t ) * 8 - 1 ) );
}
/** Choose between two integer values, without branches.
*
* This is equivalent to `cond ? if1 : if0`, but is likely to be compiled
* to code using bitwise operation rather than a branch.
*
* \param cond Condition to test.
* \param if1 Value to use if \p cond is nonzero.
* \param if0 Value to use if \p cond is zero.
* \return \c if1 if \p cond is nonzero, otherwise \c if0.
*/
static unsigned if_int( unsigned cond, unsigned if1, unsigned if0 )
{
unsigned mask = all_or_nothing_int( cond );
return( ( mask & if1 ) | (~mask & if0 ) );
}
/** Shift some data towards the left inside a buffer without leaking
* the length of the data through side channels.
*
* `mem_move_to_left(start, total, offset)` is functionally equivalent to
* ```
* memmove(start, start + offset, total - offset);
* memset(start + offset, 0, total - offset);
* ```
* but it strives to use a memory access pattern (and thus total timing)
* that does not depend on \p offset. This timing independence comes at
* the expense of performance.
*
* \param start Pointer to the start of the buffer.
* \param total Total size of the buffer.
* \param offset Offset from which to copy \p total - \p offset bytes.
*/
static void mem_move_to_left( void *start,
size_t total,
size_t offset )
{
volatile unsigned char *buf = start;
size_t i, n;
if( total == 0 )
return;
for( i = 0; i < total; i++ )
{
unsigned no_op = size_greater_than( total - offset, i );
/* The first `total - offset` passes are a no-op. The last
* `offset` passes shift the data one byte to the left and
* zero out the last byte. */
for( n = 0; n < total - 1; n++ )
{
unsigned char current = buf[n];
unsigned char next = buf[n+1];
buf[n] = if_int( no_op, current, next );
}
buf[total-1] = if_int( no_op, buf[total-1], 0 );
}
}
/* /*
* Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-DECRYPT function * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-DECRYPT function
*/ */
@ -1404,15 +1495,31 @@ int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx,
size_t output_max_len ) size_t output_max_len )
{ {
int ret; int ret;
size_t ilen, pad_count = 0, i; size_t ilen = ctx->len;
unsigned char *p, bad, pad_done = 0; size_t i;
size_t plaintext_max_size = ( output_max_len > ilen - 11 ?
ilen - 11 :
output_max_len );
unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
/* The following variables take sensitive values: their value must
* not leak into the observable behavior of the function other than
* the designated outputs (output, olen, return value). Otherwise
* this would open the execution of the function to
* side-channel-based variants of the Bleichenbacher padding oracle
* attack. Potential side channels include overall timing, memory
* access patterns (especially visible to an adversary who has access
* to a shared memory cache), and branches (especially visible to
* an adversary who has access to a shared code cache or to a shared
* branch predictor). */
size_t pad_count = 0;
unsigned bad = 0;
unsigned char pad_done = 0;
size_t plaintext_size = 0;
unsigned output_too_large;
if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
ilen = ctx->len;
if( ilen < 16 || ilen > sizeof( buf ) ) if( ilen < 16 || ilen > sizeof( buf ) )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
@ -1423,64 +1530,109 @@ int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx,
if( ret != 0 ) if( ret != 0 )
goto cleanup; goto cleanup;
p = buf; /* Check and get padding length in constant time and constant
bad = 0; * memory trace. The first byte must be 0. */
bad |= buf[0];
/*
* Check and get padding len in "constant-time"
*/
bad |= *p++; /* First byte must be 0 */
/* This test does not depend on secret data */
if( mode == MBEDTLS_RSA_PRIVATE ) if( mode == MBEDTLS_RSA_PRIVATE )
{ {
bad |= *p++ ^ MBEDTLS_RSA_CRYPT; /* Decode EME-PKCS1-v1_5 padding: 0x00 || 0x02 || PS || 0x00
* where PS must be at least 8 nonzero bytes. */
bad |= buf[1] ^ MBEDTLS_RSA_CRYPT;
/* Get padding len, but always read till end of buffer /* Read the whole buffer. Set pad_done to nonzero if we find
* (minus one, for the 00 byte) */ * the 0x00 byte and remember the padding length in pad_count. */
for( i = 0; i < ilen - 3; i++ ) for( i = 2; i < ilen; i++ )
{ {
pad_done |= ((p[i] | (unsigned char)-p[i]) >> 7) ^ 1; pad_done |= ((buf[i] | (unsigned char)-buf[i]) >> 7) ^ 1;
pad_count += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1; pad_count += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1;
} }
p += pad_count;
bad |= *p++; /* Must be zero */
} }
else else
{ {
bad |= *p++ ^ MBEDTLS_RSA_SIGN; /* Decode EMSA-PKCS1-v1_5 padding: 0x00 || 0x01 || PS || 0x00
* where PS must be at least 8 bytes with the value 0xFF. */
bad |= buf[1] ^ MBEDTLS_RSA_SIGN;
/* Get padding len, but always read till end of buffer /* Read the whole buffer. Set pad_done to nonzero if we find
* (minus one, for the 00 byte) */ * the 0x00 byte and remember the padding length in pad_count.
for( i = 0; i < ilen - 3; i++ ) * If there's a non-0xff byte in the padding, the padding is bad. */
for( i = 2; i < ilen; i++ )
{ {
pad_done |= ( p[i] != 0xFF ); pad_done |= if_int( buf[i], 0, 1 );
pad_count += ( pad_done == 0 ); pad_count += if_int( pad_done, 0, 1 );
bad |= if_int( pad_done, 0, buf[i] ^ 0xFF );
}
} }
p += pad_count; /* If pad_done is still zero, there's no data, only unfinished padding. */
bad |= *p++; /* Must be zero */ bad |= if_int( pad_done, 0, 1 );
}
bad |= ( pad_count < 8 ); /* There must be at least 8 bytes of padding. */
bad |= size_greater_than( 8, pad_count );
if( bad ) /* If the padding is valid, set plaintext_size to the number of
{ * remaining bytes after stripping the padding. If the padding
ret = MBEDTLS_ERR_RSA_INVALID_PADDING; * is invalid, avoid leaking this fact through the size of the
goto cleanup; * output: use the maximum message size that fits in the output
} * buffer. Do it without branches to avoid leaking the padding
* validity through timing. RSA keys are small enough that all the
* size_t values involved fit in unsigned int. */
plaintext_size = if_int( bad,
(unsigned) plaintext_max_size,
(unsigned) ( ilen - pad_count - 3 ) );
if( ilen - ( p - buf ) > output_max_len ) /* Set output_too_large to 0 if the plaintext fits in the output
{ * buffer and to 1 otherwise. */
ret = MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; output_too_large = size_greater_than( plaintext_size,
goto cleanup; plaintext_max_size );
}
*olen = ilen - (p - buf); /* Set ret without branches to avoid timing attacks. Return:
if( *olen != 0 ) * - INVALID_PADDING if the padding is bad (bad != 0).
memcpy( output, p, *olen ); * - OUTPUT_TOO_LARGE if the padding is good but the decrypted
ret = 0; * plaintext does not fit in the output buffer.
* - 0 if the padding is correct. */
ret = - (int) if_int( bad, - MBEDTLS_ERR_RSA_INVALID_PADDING,
if_int( output_too_large, - MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE,
0 ) );
/* If the padding is bad or the plaintext is too large, zero the
* data that we're about to copy to the output buffer.
* We need to copy the same amount of data
* from the same buffer whether the padding is good or not to
* avoid leaking the padding validity through overall timing or
* through memory or cache access patterns. */
bad = all_or_nothing_int( bad | output_too_large );
for( i = 11; i < ilen; i++ )
buf[i] &= ~bad;
/* If the plaintext is too large, truncate it to the buffer size.
* Copy anyway to avoid revealing the length through timing, because
* revealing the length is as bad as revealing the padding validity
* for a Bleichenbacher attack. */
plaintext_size = if_int( output_too_large,
(unsigned) plaintext_max_size,
(unsigned) plaintext_size );
/* Move the plaintext to the leftmost position where it can start in
* the working buffer, i.e. make it start plaintext_max_size from
* the end of the buffer. Do this with a memory access trace that
* does not depend on the plaintext size. After this move, the
* starting location of the plaintext is no longer sensitive
* information. */
mem_move_to_left( buf + ilen - plaintext_max_size,
plaintext_max_size,
plaintext_max_size - plaintext_size );
/* Finally copy the decrypted plaintext plus trailing zeros
* into the output buffer. */
memcpy( output, buf + ilen - plaintext_max_size, plaintext_max_size );
/* Report the amount of data we copied to the output buffer. In case
* of errors (bad padding or output too large), the value of *olen
* when this function returns is not specified. Making it equivalent
* to the good case limits the risks of leaking the padding validity. */
*olen = plaintext_size;
cleanup: cleanup:
mbedtls_platform_zeroize( buf, sizeof( buf ) ); mbedtls_platform_zeroize( buf, sizeof( buf ) );

View File

@ -2074,8 +2074,14 @@ static int ssl_parse_server_dh_params( mbedtls_ssl_context *ssl, unsigned char *
static int ssl_check_server_ecdh_params( const mbedtls_ssl_context *ssl ) static int ssl_check_server_ecdh_params( const mbedtls_ssl_context *ssl )
{ {
const mbedtls_ecp_curve_info *curve_info; const mbedtls_ecp_curve_info *curve_info;
mbedtls_ecp_group_id grp_id;
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
grp_id = ssl->handshake->ecdh_ctx.grp.id;
#else
grp_id = ssl->handshake->ecdh_ctx.grp_id;
#endif
curve_info = mbedtls_ecp_curve_info_from_grp_id( ssl->handshake->ecdh_ctx.grp.id ); curve_info = mbedtls_ecp_curve_info_from_grp_id( grp_id );
if( curve_info == NULL ) if( curve_info == NULL )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
@ -2085,14 +2091,15 @@ static int ssl_check_server_ecdh_params( const mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDH curve: %s", curve_info->name ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDH curve: %s", curve_info->name ) );
#if defined(MBEDTLS_ECP_C) #if defined(MBEDTLS_ECP_C)
if( mbedtls_ssl_check_curve( ssl, ssl->handshake->ecdh_ctx.grp.id ) != 0 ) if( mbedtls_ssl_check_curve( ssl, grp_id ) != 0 )
#else #else
if( ssl->handshake->ecdh_ctx.grp.nbits < 163 || if( ssl->handshake->ecdh_ctx.grp.nbits < 163 ||
ssl->handshake->ecdh_ctx.grp.nbits > 521 ) ssl->handshake->ecdh_ctx.grp.nbits > 521 )
#endif #endif
return( -1 ); return( -1 );
MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Qp", &ssl->handshake->ecdh_ctx.Qp ); MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx,
MBEDTLS_DEBUG_ECDH_QP );
return( 0 ); return( 0 );
} }
@ -3014,7 +3021,8 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
return( ret ); return( ret );
} }
MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q", &ssl->handshake->ecdh_ctx.Q ); MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx,
MBEDTLS_DEBUG_ECDH_Q );
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) #if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
if( ssl->handshake->ecrs_enabled ) if( ssl->handshake->ecrs_enabled )
@ -3041,7 +3049,8 @@ ecdh_calc_secret:
return( ret ); return( ret );
} }
MBEDTLS_SSL_DEBUG_MPI( 3, "ECDH: z", &ssl->handshake->ecdh_ctx.z ); MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx,
MBEDTLS_DEBUG_ECDH_Z );
} }
else else
#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
@ -3156,7 +3165,8 @@ ecdh_calc_secret:
return( ret ); return( ret );
} }
MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q", &ssl->handshake->ecdh_ctx.Q ); MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx,
MBEDTLS_DEBUG_ECDH_Q );
} }
else else
#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */

View File

@ -3088,7 +3088,7 @@ curve_matching_done:
MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDHE curve: %s", (*curve)->name ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDHE curve: %s", (*curve)->name ) );
if( ( ret = mbedtls_ecp_group_load( &ssl->handshake->ecdh_ctx.grp, if( ( ret = mbedtls_ecdh_setup( &ssl->handshake->ecdh_ctx,
(*curve)->grp_id ) ) != 0 ) (*curve)->grp_id ) ) != 0 )
{ {
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecp_group_load", ret ); MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecp_group_load", ret );
@ -3111,7 +3111,8 @@ curve_matching_done:
ssl->out_msglen += len; ssl->out_msglen += len;
MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q ", &ssl->handshake->ecdh_ctx.Q ); MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx,
MBEDTLS_DEBUG_ECDH_Q );
} }
#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED */ #endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED */
@ -3832,7 +3833,8 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP );
} }
MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Qp ", &ssl->handshake->ecdh_ctx.Qp ); MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx,
MBEDTLS_DEBUG_ECDH_QP );
if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx,
&ssl->handshake->pmslen, &ssl->handshake->pmslen,
@ -3844,7 +3846,8 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS );
} }
MBEDTLS_SSL_DEBUG_MPI( 3, "ECDH: z ", &ssl->handshake->ecdh_ctx.z ); MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx,
MBEDTLS_DEBUG_ECDH_Z );
} }
else else
#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
@ -3982,7 +3985,8 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
#endif #endif
MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Qp ", &ssl->handshake->ecdh_ctx.Qp ); MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx,
MBEDTLS_DEBUG_ECDH_QP );
if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl,
ciphersuite_info->key_exchange ) ) != 0 ) ciphersuite_info->key_exchange ) ) != 0 )

View File

@ -217,9 +217,9 @@ static int ssl_save_session( const mbedtls_ssl_session *session,
if( left < 3 + cert_len ) if( left < 3 + cert_len )
return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
*p++ = (unsigned char)( cert_len >> 16 & 0xFF ); *p++ = (unsigned char)( ( cert_len >> 16 ) & 0xFF );
*p++ = (unsigned char)( cert_len >> 8 & 0xFF ); *p++ = (unsigned char)( ( cert_len >> 8 ) & 0xFF );
*p++ = (unsigned char)( cert_len & 0xFF ); *p++ = (unsigned char)( ( cert_len ) & 0xFF );
if( session->peer_cert != NULL ) if( session->peer_cert != NULL )
memcpy( p, session->peer_cert->raw.p, cert_len ); memcpy( p, session->peer_cert->raw.p, cert_len );
@ -244,14 +244,14 @@ static int ssl_load_session( mbedtls_ssl_session *session,
size_t cert_len; size_t cert_len;
#endif /* MBEDTLS_X509_CRT_PARSE_C */ #endif /* MBEDTLS_X509_CRT_PARSE_C */
if( p + sizeof( mbedtls_ssl_session ) > end ) if( sizeof( mbedtls_ssl_session ) > (size_t)( end - p ) )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
memcpy( session, p, sizeof( mbedtls_ssl_session ) ); memcpy( session, p, sizeof( mbedtls_ssl_session ) );
p += sizeof( mbedtls_ssl_session ); p += sizeof( mbedtls_ssl_session );
#if defined(MBEDTLS_X509_CRT_PARSE_C) #if defined(MBEDTLS_X509_CRT_PARSE_C)
if( p + 3 > end ) if( 3 > (size_t)( end - p ) )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
cert_len = ( p[0] << 16 ) | ( p[1] << 8 ) | p[2]; cert_len = ( p[0] << 16 ) | ( p[1] << 8 ) | p[2];
@ -265,7 +265,7 @@ static int ssl_load_session( mbedtls_ssl_session *session,
{ {
int ret; int ret;
if( p + cert_len > end ) if( cert_len > (size_t)( end - p ) )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
session->peer_cert = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); session->peer_cert = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) );

View File

@ -1499,7 +1499,8 @@ int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exch
*(p++) = (unsigned char)( zlen ); *(p++) = (unsigned char)( zlen );
p += zlen; p += zlen;
MBEDTLS_SSL_DEBUG_MPI( 3, "ECDH: z", &ssl->handshake->ecdh_ctx.z ); MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx,
MBEDTLS_DEBUG_ECDH_Z );
} }
else else
#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
@ -3366,8 +3367,10 @@ int mbedtls_ssl_write_handshake_msg( mbedtls_ssl_context *ssl )
} }
} }
if( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && /* Whenever we send anything different from a
hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST && * HelloRequest we should be in a handshake - double check. */
if( ! ( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
hs_type == MBEDTLS_SSL_HS_HELLO_REQUEST ) &&
ssl->handshake == NULL ) ssl->handshake == NULL )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
@ -3461,8 +3464,8 @@ int mbedtls_ssl_write_handshake_msg( mbedtls_ssl_context *ssl )
/* Either send now, or just save to be sent (and resent) later */ /* Either send now, or just save to be sent (and resent) later */
#if defined(MBEDTLS_SSL_PROTO_DTLS) #if defined(MBEDTLS_SSL_PROTO_DTLS)
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
( ssl->out_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE || ! ( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST ) ) hs_type == MBEDTLS_SSL_HS_HELLO_REQUEST ) )
{ {
if( ( ret = ssl_flight_append( ssl ) ) != 0 ) if( ( ret = ssl_flight_append( ssl ) ) != 0 )
{ {

View File

@ -2203,7 +2203,7 @@ static int x509_crt_find_parent(
} }
/* extra precaution against mistakes in the caller */ /* extra precaution against mistakes in the caller */
if( parent == NULL ) if( *parent == NULL )
{ {
*parent_is_trusted = 0; *parent_is_trusted = 0;
*signature_is_good = 0; *signature_is_good = 0;

View File

@ -35,12 +35,12 @@
#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE #define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
#endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_PLATFORM_C */
#if !defined(MBEDTLS_ECDH_C) || \ #if !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_ECDH_LEGACY_CONTEXT) || \
!defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || \ !defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || \
!defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_CTR_DRBG_C) !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_CTR_DRBG_C)
int main( void ) int main( void )
{ {
mbedtls_printf( "MBEDTLS_ECDH_C and/or " mbedtls_printf( "MBEDTLS_ECDH_C and/or MBEDTLS_ECDH_LEGACY_CONTEXT and/or "
"MBEDTLS_ECP_DP_CURVE25519_ENABLED and/or " "MBEDTLS_ECP_DP_CURVE25519_ENABLED and/or "
"MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C " "MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C "
"not defined\n" ); "not defined\n" );

View File

@ -322,7 +322,8 @@ int main( int argc, char *argv[] )
mbedtls_printf( "\n . Generating the private key ..." ); mbedtls_printf( "\n . Generating the private key ..." );
fflush( stdout ); fflush( stdout );
if( ( ret = mbedtls_pk_setup( &key, mbedtls_pk_info_from_type( opt.type ) ) ) != 0 ) if( ( ret = mbedtls_pk_setup( &key,
mbedtls_pk_info_from_type( (mbedtls_pk_type_t) opt.type ) ) ) != 0 )
{ {
mbedtls_printf( " failed\n ! mbedtls_pk_setup returned -0x%04x", -ret ); mbedtls_printf( " failed\n ! mbedtls_pk_setup returned -0x%04x", -ret );
goto exit; goto exit;
@ -344,7 +345,8 @@ int main( int argc, char *argv[] )
#if defined(MBEDTLS_ECP_C) #if defined(MBEDTLS_ECP_C)
if( opt.type == MBEDTLS_PK_ECKEY ) if( opt.type == MBEDTLS_PK_ECKEY )
{ {
ret = mbedtls_ecp_gen_key( opt.ec_curve, mbedtls_pk_ec( key ), ret = mbedtls_ecp_gen_key( (mbedtls_ecp_group_id) opt.ec_curve,
mbedtls_pk_ec( key ),
mbedtls_ctr_drbg_random, &ctr_drbg ); mbedtls_ctr_drbg_random, &ctr_drbg );
if( ret != 0 ) if( ret != 0 )
{ {

View File

@ -87,10 +87,12 @@
USAGE_OUT \ USAGE_OUT \
"\n" "\n"
#if !defined(MBEDTLS_PK_WRITE_C) || !defined(MBEDTLS_FS_IO) #if !defined(MBEDTLS_PK_PARSE_C) || \
!defined(MBEDTLS_PK_WRITE_C) || \
!defined(MBEDTLS_FS_IO)
int main( void ) int main( void )
{ {
mbedtls_printf( "MBEDTLS_PK_WRITE_C and/or MBEDTLS_FS_IO not defined.\n" ); mbedtls_printf( "MBEDTLS_PK_PARSE_C and/or MBEDTLS_PK_WRITE_C and/or MBEDTLS_FS_IO not defined.\n" );
return( 0 ); return( 0 );
} }
#else #else
@ -433,4 +435,4 @@ exit:
return( exit_code ); return( exit_code );
} }
#endif /* MBEDTLS_PK_WRITE_C && MBEDTLS_FS_IO */ #endif /* MBEDTLS_PK_PARSE_C && MBEDTLS_PK_WRITE_C && MBEDTLS_FS_IO */

View File

@ -862,7 +862,7 @@ int main( int argc, char *argv[] )
} }
#endif #endif
#if defined(MBEDTLS_ECDH_C) #if defined(MBEDTLS_ECDH_C) && defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
if( todo.ecdh ) if( todo.ecdh )
{ {
mbedtls_ecdh_context ecdh; mbedtls_ecdh_context ecdh;

View File

@ -46,3 +46,4 @@ run_test ./tests/scripts/check-doxy-blocks.pl
run_test ./tests/scripts/check-names.sh run_test ./tests/scripts/check-names.sh
run_test ./tests/scripts/check-generated-files.sh run_test ./tests/scripts/check-generated-files.sh
run_test ./tests/scripts/check-files.py run_test ./tests/scripts/check-files.py
run_test ./tests/scripts/doxygen.sh

View File

@ -76,7 +76,7 @@ TEST_OUTPUT=out_${PPID}
cd tests cd tests
# Step 2a - Unit Tests # Step 2a - Unit Tests
perl scripts/run-test-suites.pl -v |tee unit-test-$TEST_OUTPUT perl scripts/run-test-suites.pl -v 2 |tee unit-test-$TEST_OUTPUT
echo echo
# Step 2b - System Tests # Step 2b - System Tests

View File

@ -43,12 +43,15 @@ class IssueTracker(object):
for i, line in enumerate(iter(f.readline, b"")): for i, line in enumerate(iter(f.readline, b"")):
self.check_file_line(filepath, line, i + 1) self.check_file_line(filepath, line, i + 1)
def check_file_line(self, filepath, line, line_number): def record_issue(self, filepath, line_number):
if self.issue_with_line(line):
if filepath not in self.files_with_issues.keys(): if filepath not in self.files_with_issues.keys():
self.files_with_issues[filepath] = [] self.files_with_issues[filepath] = []
self.files_with_issues[filepath].append(line_number) self.files_with_issues[filepath].append(line_number)
def check_file_line(self, filepath, line, line_number):
if self.issue_with_line(line):
self.record_issue(filepath, line_number)
def output_file_issues(self, logger): def output_file_issues(self, logger):
if self.files_with_issues.values(): if self.files_with_issues.values():
logger.info(self.heading) logger.info(self.heading)
@ -132,13 +135,36 @@ class TabIssueTracker(IssueTracker):
return b"\t" in line return b"\t" in line
class MergeArtifactIssueTracker(IssueTracker):
def __init__(self):
super().__init__()
self.heading = "Merge artifact:"
def issue_with_line(self, filepath, line):
# Detect leftover git conflict markers.
if line.startswith(b'<<<<<<< ') or line.startswith(b'>>>>>>> '):
return True
if line.startswith(b'||||||| '): # from merge.conflictStyle=diff3
return True
if line.rstrip(b'\r\n') == b'=======' and \
not filepath.endswith('.md'):
return True
return False
def check_file_line(self, filepath, line, line_number):
if self.issue_with_line(filepath, line):
self.record_issue(filepath, line_number)
class TodoIssueTracker(IssueTracker): class TodoIssueTracker(IssueTracker):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.heading = "TODO present:" self.heading = "TODO present:"
self.files_exemptions = [ self.files_exemptions = [
__file__, "benchmark.c", "pull_request_template.md" os.path.basename(__file__),
"benchmark.c",
"pull_request_template.md",
] ]
def issue_with_line(self, line): def issue_with_line(self, line):
@ -167,6 +193,7 @@ class IntegrityChecker(object):
LineEndingIssueTracker(), LineEndingIssueTracker(),
TrailingWhitespaceIssueTracker(), TrailingWhitespaceIssueTracker(),
TabIssueTracker(), TabIssueTracker(),
MergeArtifactIssueTracker(),
TodoIssueTracker(), TodoIssueTracker(),
] ]

View File

@ -185,7 +185,7 @@ class MbedTlsTest(BaseHostTest):
binary_path = self.get_config_item('image_path') binary_path = self.get_config_item('image_path')
script_dir = os.path.split(os.path.abspath(__file__))[0] script_dir = os.path.split(os.path.abspath(__file__))[0]
suite_name = os.path.splitext(os.path.basename(binary_path))[0] suite_name = os.path.splitext(os.path.basename(binary_path))[0]
data_file = ".".join((suite_name, 'data')) data_file = ".".join((suite_name, 'datax'))
data_file = os.path.join(script_dir, '..', 'mbedtls', data_file = os.path.join(script_dir, '..', 'mbedtls',
suite_name, data_file) suite_name, data_file)
if os.path.exists(data_file): if os.path.exists(data_file):

View File

@ -24,14 +24,10 @@ use strict;
use utf8; use utf8;
use open qw(:std utf8); use open qw(:std utf8);
use constant FALSE => 0; use Getopt::Long;
use constant TRUE => 1;
my $verbose; my $verbose = 0;
my $switch = shift; GetOptions( "verbose|v:1" => \$verbose );
if ( defined($switch) && ( $switch eq "-v" || $switch eq "--verbose" ) ) {
$verbose = TRUE;
}
# All test suites = executable files, excluding source files, debug # All test suites = executable files, excluding source files, debug
# and profiling information, etc. We can't just grep {! /\./} because # and profiling information, etc. We can't just grep {! /\./} because
@ -50,10 +46,20 @@ my ($failed_suites, $total_tests_run, $failed, $suite_cases_passed,
$suite_cases_failed, $suite_cases_skipped, $total_cases_passed, $suite_cases_failed, $suite_cases_skipped, $total_cases_passed,
$total_cases_failed, $total_cases_skipped ); $total_cases_failed, $total_cases_skipped );
sub pad_print_center {
my( $width, $padchar, $string ) = @_;
my $padlen = ( $width - length( $string ) - 2 ) / 2;
print $padchar x( $padlen ), " $string ", $padchar x( $padlen ), "\n";
}
for my $suite (@suites) for my $suite (@suites)
{ {
print "$suite ", "." x ( 72 - length($suite) - 2 - 4 ), " "; print "$suite ", "." x ( 72 - length($suite) - 2 - 4 ), " ";
my $result = `$prefix$suite`; my $command = "$prefix$suite";
if( $verbose ) {
$command .= ' -v';
}
my $result = `$command`;
$suite_cases_passed = () = $result =~ /.. PASS/g; $suite_cases_passed = () = $result =~ /.. PASS/g;
$suite_cases_failed = () = $result =~ /.. FAILED/g; $suite_cases_failed = () = $result =~ /.. FAILED/g;
@ -61,15 +67,25 @@ for my $suite (@suites)
if( $result =~ /PASSED/ ) { if( $result =~ /PASSED/ ) {
print "PASS\n"; print "PASS\n";
if( $verbose > 2 ) {
pad_print_center( 72, '-', "Begin $suite" );
print $result;
pad_print_center( 72, '-', "End $suite" );
}
} else { } else {
$failed_suites++; $failed_suites++;
print "FAIL\n"; print "FAIL\n";
if( $verbose ) {
pad_print_center( 72, '-', "Begin $suite" );
print $result;
pad_print_center( 72, '-', "End $suite" );
}
} }
my ($passed, $tests, $skipped) = $result =~ /([0-9]*) \/ ([0-9]*) tests.*?([0-9]*) skipped/; my ($passed, $tests, $skipped) = $result =~ /([0-9]*) \/ ([0-9]*) tests.*?([0-9]*) skipped/;
$total_tests_run += $tests - $skipped; $total_tests_run += $tests - $skipped;
if ( $verbose ) { if( $verbose > 1 ) {
print "(test cases passed:", $suite_cases_passed, print "(test cases passed:", $suite_cases_passed,
" failed:", $suite_cases_failed, " failed:", $suite_cases_failed,
" skipped:", $suite_cases_skipped, " skipped:", $suite_cases_skipped,
@ -87,7 +103,7 @@ print "-" x 72, "\n";
print $failed_suites ? "FAILED" : "PASSED"; print $failed_suites ? "FAILED" : "PASSED";
printf " (%d suites, %d tests run)\n", scalar @suites, $total_tests_run; printf " (%d suites, %d tests run)\n", scalar @suites, $total_tests_run;
if ( $verbose ) { if( $verbose > 1 ) {
print " test cases passed :", $total_cases_passed, "\n"; print " test cases passed :", $total_cases_passed, "\n";
print " failed :", $total_cases_failed, "\n"; print " failed :", $total_cases_failed, "\n";
print " skipped :", $total_cases_skipped, "\n"; print " skipped :", $total_cases_skipped, "\n";

View File

@ -78,7 +78,7 @@ void mbedtls_asn1_write_ia5_string( char * str, data_t * asn1,
} }
/* END_CASE */ /* END_CASE */
/* BEGIN_CASE */ /* BEGIN_CASE depends_on:MBEDTLS_ASN1PARSE_C */
void mbedtls_asn1_write_len( int len, data_t * asn1, int buf_len, void mbedtls_asn1_write_len( int len, data_t * asn1, int buf_len,
int result ) int result )
{ {

View File

@ -244,9 +244,11 @@ void ctr_drbg_entropy_usage( )
} }
TEST_ASSERT( last_idx == test_offset_idx ); TEST_ASSERT( last_idx == test_offset_idx );
/* Call update with too much data (sizeof entropy > MAX(_SEED)_INPUT) /* Call update with too much data (sizeof entropy > MAX(_SEED)_INPUT).
* (just make sure it doesn't cause memory corruption) */ * Make sure it's detected as an error and doesn't cause memory
mbedtls_ctr_drbg_update( &ctx, entropy, sizeof( entropy ) ); * corruption. */
TEST_ASSERT( mbedtls_ctr_drbg_update_ret(
&ctx, entropy, sizeof( entropy ) ) != 0 );
/* Now enable PR, so the next few calls should all reseed */ /* Now enable PR, so the next few calls should all reseed */
mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON ); mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );

View File

@ -69,3 +69,7 @@ ecdh_restart:MBEDTLS_ECP_DP_SECP256R1:"C88F01F510D9AC3F70A292DAA2316DE544E9AAB8A
ECDH restartable rfc 5903 p256 restart disabled max_ops=250 ECDH restartable rfc 5903 p256 restart disabled max_ops=250
depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
ecdh_restart:MBEDTLS_ECP_DP_SECP256R1:"C88F01F510D9AC3F70A292DAA2316DE544E9AAB8AFE84049C62A9C57862D1433":"C6EF9C5D78AE012A011164ACB397CE2088685D8F06BF9BE0B283AB46476BEE53":"D6840F6B42F6EDAFD13116E0E12565202FEF8E9ECE7DCE03812464D04B9442DE":0:250:0:0 ecdh_restart:MBEDTLS_ECP_DP_SECP256R1:"C88F01F510D9AC3F70A292DAA2316DE544E9AAB8AFE84049C62A9C57862D1433":"C6EF9C5D78AE012A011164ACB397CE2088685D8F06BF9BE0B283AB46476BEE53":"D6840F6B42F6EDAFD13116E0E12565202FEF8E9ECE7DCE03812464D04B9442DE":0:250:0:0
ECDH exchange legacy context
depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
ecdh_exchange_legacy:MBEDTLS_ECP_DP_SECP192R1

View File

@ -129,12 +129,14 @@ void ecdh_exchange( int id )
const unsigned char *vbuf; const unsigned char *vbuf;
size_t len; size_t len;
rnd_pseudo_info rnd_info; rnd_pseudo_info rnd_info;
unsigned char res_buf[1000];
size_t res_len;
mbedtls_ecdh_init( &srv ); mbedtls_ecdh_init( &srv );
mbedtls_ecdh_init( &cli ); mbedtls_ecdh_init( &cli );
memset( &rnd_info, 0x00, sizeof( rnd_pseudo_info ) ); memset( &rnd_info, 0x00, sizeof( rnd_pseudo_info ) );
TEST_ASSERT( mbedtls_ecp_group_load( &srv.grp, id ) == 0 ); TEST_ASSERT( mbedtls_ecdh_setup( &srv, id ) == 0 );
memset( buf, 0x00, sizeof( buf ) ); vbuf = buf; memset( buf, 0x00, sizeof( buf ) ); vbuf = buf;
TEST_ASSERT( mbedtls_ecdh_make_params( &srv, &len, buf, 1000, TEST_ASSERT( mbedtls_ecdh_make_params( &srv, &len, buf, 1000,
@ -148,8 +150,10 @@ void ecdh_exchange( int id )
TEST_ASSERT( mbedtls_ecdh_calc_secret( &srv, &len, buf, 1000, TEST_ASSERT( mbedtls_ecdh_calc_secret( &srv, &len, buf, 1000,
&rnd_pseudo_rand, &rnd_info ) == 0 ); &rnd_pseudo_rand, &rnd_info ) == 0 );
TEST_ASSERT( mbedtls_ecdh_calc_secret( &cli, &len, buf, 1000, NULL, NULL ) == 0 ); TEST_ASSERT( mbedtls_ecdh_calc_secret( &cli, &res_len, res_buf, 1000,
TEST_ASSERT( mbedtls_mpi_cmp_mpi( &srv.z, &cli.z ) == 0 ); NULL, NULL ) == 0 );
TEST_ASSERT( len == res_len );
TEST_ASSERT( memcmp( buf, res_buf, len ) == 0 );
exit: exit:
mbedtls_ecdh_free( &srv ); mbedtls_ecdh_free( &srv );
@ -172,7 +176,9 @@ void ecdh_restart( int id, char *dA_str, char *dB_str, char *z_str,
unsigned char rnd_buf_B[MBEDTLS_ECP_MAX_BYTES]; unsigned char rnd_buf_B[MBEDTLS_ECP_MAX_BYTES];
rnd_buf_info rnd_info_A, rnd_info_B; rnd_buf_info rnd_info_A, rnd_info_B;
int cnt_restart; int cnt_restart;
mbedtls_ecp_group grp;
mbedtls_ecp_group_init( &grp );
mbedtls_ecdh_init( &srv ); mbedtls_ecdh_init( &srv );
mbedtls_ecdh_init( &cli ); mbedtls_ecdh_init( &cli );
@ -184,11 +190,15 @@ void ecdh_restart( int id, char *dA_str, char *dB_str, char *z_str,
rnd_info_B.buf = rnd_buf_B; rnd_info_B.buf = rnd_buf_B;
rnd_info_B.length = unhexify( rnd_buf_B, dB_str ); rnd_info_B.length = unhexify( rnd_buf_B, dB_str );
TEST_ASSERT( mbedtls_ecp_group_load( &srv.grp, id ) == 0 ); /* The ECDH context is not guaranteed ot have an mbedtls_ecp_group structure
* in every configuration, therefore we load it separately. */
TEST_ASSERT( mbedtls_ecp_group_load( &grp, id ) == 0 );
/* otherwise we would have to fix the random buffer, /* Otherwise we would have to fix the random buffer,
* as in ecdh_primitive_test_vec */ * as in ecdh_primitive_testvec. */
TEST_ASSERT( srv.grp.nbits % 8 == 0 ); TEST_ASSERT( grp.nbits % 8 == 0 );
TEST_ASSERT( mbedtls_ecdh_setup( &srv, id ) == 0 );
/* set up restart parameters */ /* set up restart parameters */
mbedtls_ecp_set_max_ops( max_ops ); mbedtls_ecp_set_max_ops( max_ops );
@ -268,6 +278,45 @@ void ecdh_restart( int id, char *dA_str, char *dB_str, char *z_str,
TEST_ASSERT( len == z_len ); TEST_ASSERT( len == z_len );
TEST_ASSERT( memcmp( buf, z, len ) == 0 ); TEST_ASSERT( memcmp( buf, z, len ) == 0 );
exit:
mbedtls_ecp_group_free( &grp );
mbedtls_ecdh_free( &srv );
mbedtls_ecdh_free( &cli );
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_ECDH_LEGACY_CONTEXT */
void ecdh_exchange_legacy( int id )
{
mbedtls_ecdh_context srv, cli;
unsigned char buf[1000];
const unsigned char *vbuf;
size_t len;
rnd_pseudo_info rnd_info;
mbedtls_ecdh_init( &srv );
mbedtls_ecdh_init( &cli );
memset( &rnd_info, 0x00, sizeof( rnd_pseudo_info ) );
TEST_ASSERT( mbedtls_ecp_group_load( &srv.grp, id ) == 0 );
memset( buf, 0x00, sizeof( buf ) ); vbuf = buf;
TEST_ASSERT( mbedtls_ecdh_make_params( &srv, &len, buf, 1000,
&rnd_pseudo_rand, &rnd_info ) == 0 );
TEST_ASSERT( mbedtls_ecdh_read_params( &cli, &vbuf, buf + len ) == 0 );
memset( buf, 0x00, sizeof( buf ) );
TEST_ASSERT( mbedtls_ecdh_make_public( &cli, &len, buf, 1000,
&rnd_pseudo_rand, &rnd_info ) == 0 );
TEST_ASSERT( mbedtls_ecdh_read_public( &srv, buf, len ) == 0 );
TEST_ASSERT( mbedtls_ecdh_calc_secret( &srv, &len, buf, 1000,
&rnd_pseudo_rand, &rnd_info ) == 0 );
TEST_ASSERT( mbedtls_ecdh_calc_secret( &cli, &len, buf, 1000, NULL,
NULL ) == 0 );
TEST_ASSERT( mbedtls_mpi_cmp_mpi( &srv.z, &cli.z ) == 0 );
exit: exit:
mbedtls_ecdh_free( &srv ); mbedtls_ecdh_free( &srv );
mbedtls_ecdh_free( &cli ); mbedtls_ecdh_free( &cli );

View File

@ -14,7 +14,7 @@ void ecdsa_prim_random( int id )
mbedtls_ecp_point Q; mbedtls_ecp_point Q;
mbedtls_mpi d, r, s; mbedtls_mpi d, r, s;
rnd_pseudo_info rnd_info; rnd_pseudo_info rnd_info;
unsigned char buf[66]; unsigned char buf[MBEDTLS_MD_MAX_SIZE];
mbedtls_ecp_group_init( &grp ); mbedtls_ecp_group_init( &grp );
mbedtls_ecp_point_init( &Q ); mbedtls_ecp_point_init( &Q );

View File

@ -33,3 +33,93 @@ pkcs1_rsassa_v15_sign:1024:16:"d17f655bf27c8b16d35462c905cc04a26f37e2a67fa9c0ce0
RSASSA-V15 Verification Test Vector Int RSASSA-V15 Verification Test Vector Int
pkcs1_rsassa_v15_verify:1024:16:"a2ba40ee07e3b2bd2f02ce227f36a195024486e49c19cb41bbbdfbba98b22b0e577c2eeaffa20d883a76e65e394c69d4b3c05a1e8fadda27edb2a42bc000fe888b9b32c22d15add0cd76b3e7936e19955b220dd17d4ea904b1ec102b2e4de7751222aa99151024c7cb41cc5ea21d00eeb41f7c800834d2c6e06bce3bce7ea9a5":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"859eef2fd78aca00308bdc471193bf55bf9d78db8f8a672b484634f3c9c26e6478ae10260fe0dd8c082e53a5293af2173cd50c6d5d354febf78b26021c25c02712e78cd4694c9f469777e451e7f8e9e04cd3739c6bbfedae487fb55644e9ca74ff77a53cb729802f6ed4a5ffa8ba159890fc":"e3b5d5d002c1bce50c2b65ef88a188d83bce7e61":"2154f928615e5101fcdeb57bc08fc2f35c3d5996403861ae3efb1d0712f8bb05cc21f7f5f11f62e5b6ea9f0f2b62180e5cbe7ba535032d6ac8068fff7f362f73d2c3bf5eca6062a1723d7cfd5abb6dcf7e405f2dc560ffe6fc37d38bee4dc9e24fe2bece3e3b4a3f032701d3f0947b42930083dd4ad241b3309b514595482d42":0 pkcs1_rsassa_v15_verify:1024:16:"a2ba40ee07e3b2bd2f02ce227f36a195024486e49c19cb41bbbdfbba98b22b0e577c2eeaffa20d883a76e65e394c69d4b3c05a1e8fadda27edb2a42bc000fe888b9b32c22d15add0cd76b3e7936e19955b220dd17d4ea904b1ec102b2e4de7751222aa99151024c7cb41cc5ea21d00eeb41f7c800834d2c6e06bce3bce7ea9a5":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"859eef2fd78aca00308bdc471193bf55bf9d78db8f8a672b484634f3c9c26e6478ae10260fe0dd8c082e53a5293af2173cd50c6d5d354febf78b26021c25c02712e78cd4694c9f469777e451e7f8e9e04cd3739c6bbfedae487fb55644e9ca74ff77a53cb729802f6ed4a5ffa8ba159890fc":"e3b5d5d002c1bce50c2b65ef88a188d83bce7e61":"2154f928615e5101fcdeb57bc08fc2f35c3d5996403861ae3efb1d0712f8bb05cc21f7f5f11f62e5b6ea9f0f2b62180e5cbe7ba535032d6ac8068fff7f362f73d2c3bf5eca6062a1723d7cfd5abb6dcf7e405f2dc560ffe6fc37d38bee4dc9e24fe2bece3e3b4a3f032701d3f0947b42930083dd4ad241b3309b514595482d42":0
RSAES-V15 decoding: good, payload=max, tight output buffer
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"0002505152535455565700":117:117:0
RSAES-V15 decoding: good, payload=max, larger output buffer
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"0002505152535455565700":117:128:0
RSAES-V15 decoding: good, payload=max-1, tight output buffer
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"000250515253545556575800":116:116:0
RSAES-V15 decoding: good, payload=max-1, larger output buffer
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"000250515253545556575800":116:117:0
RSAES-V15 decoding: good, payload=1
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"00025050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505000":1:1:0
RSAES-V15 decoding: good, empty payload
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"0002505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505000":0:0:0
RSAES-V15 decoding: payload=max, output too large
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"0002505152535455565700":117:116:MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE
RSAES-V15 decoding: payload=max-1, output too large
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"000250515253545556575800":116:115:MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE
RSAES-V15 decoding: bad first byte
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"0102505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
RSAES-V15 decoding: bad second byte (0 instead of 2)
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"0000505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
RSAES-V15 decoding: bad second byte (1 instead of 2)
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"0001505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
RSAES-V15 decoding: padding too short (0)
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"000200":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
RSAES-V15 decoding: padding too short (7)
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"0002505050505050500000ffffffffffffffffff00":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
RSAES-V15 decoding: unfinished padding
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"0002505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
EMSA-V15 decoding: good, payload=max, tight output buffer
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0001ffffffffffffffff00":117:117:0
EMSA-V15 decoding: good, payload=max, larger output buffer
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0001ffffffffffffffff00":117:128:0
EMSA-V15 decoding: good, payload=max-1, tight output buffer
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0001ffffffffffffffffff00":116:116:0
EMSA-V15 decoding: good, payload=max-1, larger output buffer
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0001ffffffffffffffffff00":116:117:0
EMSA-V15 decoding: good, payload=1
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00":1:1:0
EMSA-V15 decoding: good, empty payload
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00":0:0:0
EMSA-V15 decoding: bad first byte
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0101ffffffffffffffff00":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
EMSA-V15 decoding: bad second byte (0 instead of 1)
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0000ffffffffffffffff00":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
EMSA-V15 decoding: bad second byte (2 instead of 1)
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0002ffffffffffffffff00":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
EMSA-V15 decoding: padding too short (0)
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"000100":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
EMSA-V15 decoding: padding too short (7)
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0001ffffffffffffff0000ffffffffffffffff00":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
EMSA-V15 decoding: invalid padding at first byte
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0001fffffffffffffffe00":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
EMSA-V15 decoding: invalid padding at last byte
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0001feffffffffffffff00":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
EMSA-V15 decoding: unfinished padding
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
EMSA-V15 decoding: unfinished padding with invalid first byte
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0001feffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
EMSA-V15 decoding: unfinished padding with invalid last byte
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0001fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING

View File

@ -93,6 +93,154 @@ exit:
} }
/* END_CASE */ /* END_CASE */
/* BEGIN_CASE */
void pkcs1_v15_decode( int mode,
data_t *input,
int expected_plaintext_length_arg,
int output_size_arg,
int expected_result )
{
size_t expected_plaintext_length = expected_plaintext_length_arg;
size_t output_size = output_size_arg;
rnd_pseudo_info rnd_info;
mbedtls_mpi Nmpi, Empi, Pmpi, Qmpi;
mbedtls_rsa_context ctx;
static unsigned char N[128] = {
0xc4, 0x79, 0x4c, 0x6d, 0xb2, 0xe9, 0xdf, 0xc5,
0xe5, 0xd7, 0x55, 0x4b, 0xfb, 0x6c, 0x2e, 0xec,
0x84, 0xd0, 0x88, 0x12, 0xaf, 0xbf, 0xb4, 0xf5,
0x47, 0x3c, 0x7e, 0x92, 0x4c, 0x58, 0xc8, 0x73,
0xfe, 0x8f, 0x2b, 0x8f, 0x8e, 0xc8, 0x5c, 0xf5,
0x05, 0xeb, 0xfb, 0x0d, 0x7b, 0x2a, 0x93, 0xde,
0x15, 0x0d, 0xc8, 0x13, 0xcf, 0xd2, 0x6f, 0x0d,
0x9d, 0xad, 0x30, 0xe5, 0x70, 0x20, 0x92, 0x9e,
0xb3, 0x6b, 0xba, 0x5c, 0x50, 0x0f, 0xc3, 0xb2,
0x7e, 0x64, 0x07, 0x94, 0x7e, 0xc9, 0x4e, 0xc1,
0x65, 0x04, 0xaf, 0xb3, 0x9f, 0xde, 0xa8, 0x46,
0xfa, 0x6c, 0xf3, 0x03, 0xaf, 0x1c, 0x1b, 0xec,
0x75, 0x44, 0x66, 0x77, 0xc9, 0xde, 0x51, 0x33,
0x64, 0x27, 0xb0, 0xd4, 0x8d, 0x31, 0x6a, 0x11,
0x27, 0x3c, 0x99, 0xd4, 0x22, 0xc0, 0x9d, 0x12,
0x01, 0xc7, 0x4a, 0x73, 0xac, 0xbf, 0xc2, 0xbb
};
static unsigned char E[1] = { 0x03 };
static unsigned char P[64] = {
0xe5, 0x53, 0x1f, 0x88, 0x51, 0xee, 0x59, 0xf8,
0xc1, 0xe4, 0xcc, 0x5b, 0xb3, 0x75, 0x8d, 0xc8,
0xe8, 0x95, 0x2f, 0xd0, 0xef, 0x37, 0xb4, 0xcd,
0xd3, 0x9e, 0x48, 0x8b, 0x81, 0x58, 0x60, 0xb9,
0x27, 0x1d, 0xb6, 0x28, 0x92, 0x64, 0xa3, 0xa5,
0x64, 0xbd, 0xcc, 0x53, 0x68, 0xdd, 0x3e, 0x55,
0xea, 0x9d, 0x5e, 0xcd, 0x1f, 0x96, 0x87, 0xf1,
0x29, 0x75, 0x92, 0x70, 0x8f, 0x28, 0xfb, 0x2b
};
static unsigned char Q[64] = {
0xdb, 0x53, 0xef, 0x74, 0x61, 0xb4, 0x20, 0x3b,
0x3b, 0x87, 0x76, 0x75, 0x81, 0x56, 0x11, 0x03,
0x59, 0x31, 0xe3, 0x38, 0x4b, 0x8c, 0x7a, 0x9c,
0x05, 0xd6, 0x7f, 0x1e, 0x5e, 0x60, 0xf0, 0x4e,
0x0b, 0xdc, 0x34, 0x54, 0x1c, 0x2e, 0x90, 0x83,
0x14, 0xef, 0xc0, 0x96, 0x5c, 0x30, 0x10, 0xcc,
0xc1, 0xba, 0xa0, 0x54, 0x3f, 0x96, 0x24, 0xca,
0xa3, 0xfb, 0x55, 0xbc, 0x71, 0x29, 0x4e, 0xb1
};
unsigned char original[128];
unsigned char intermediate[128];
static unsigned char default_content[128] = {
/* A randomly generated pattern. */
0x4c, 0x27, 0x54, 0xa0, 0xce, 0x0d, 0x09, 0x4a,
0x1c, 0x38, 0x8e, 0x2d, 0xa3, 0xc4, 0xe0, 0x19,
0x4c, 0x99, 0xb2, 0xbf, 0xe6, 0x65, 0x7e, 0x58,
0xd7, 0xb6, 0x8a, 0x05, 0x2f, 0xa5, 0xec, 0xa4,
0x35, 0xad, 0x10, 0x36, 0xff, 0x0d, 0x08, 0x50,
0x74, 0x47, 0xc9, 0x9c, 0x4a, 0xe7, 0xfd, 0xfa,
0x83, 0x5f, 0x14, 0x5a, 0x1e, 0xe7, 0x35, 0x08,
0xad, 0xf7, 0x0d, 0x86, 0xdf, 0xb8, 0xd4, 0xcf,
0x32, 0xb9, 0x5c, 0xbe, 0xa3, 0xd2, 0x89, 0x70,
0x7b, 0xc6, 0x48, 0x7e, 0x58, 0x4d, 0xf3, 0xef,
0x34, 0xb7, 0x57, 0x54, 0x79, 0xc5, 0x8e, 0x0a,
0xa3, 0xbf, 0x6d, 0x42, 0x83, 0x25, 0x13, 0xa2,
0x95, 0xc0, 0x0d, 0x32, 0xec, 0x77, 0x91, 0x2b,
0x68, 0xb6, 0x8c, 0x79, 0x15, 0xfb, 0x94, 0xde,
0xb9, 0x2b, 0x94, 0xb3, 0x28, 0x23, 0x86, 0x3d,
0x37, 0x00, 0xe6, 0xf1, 0x1f, 0x4e, 0xd4, 0x42
};
unsigned char final[128];
size_t output_length = 0x7EA0;
memset( &rnd_info, 0, sizeof( rnd_pseudo_info ) );
mbedtls_mpi_init( &Nmpi ); mbedtls_mpi_init( &Empi );
mbedtls_mpi_init( &Pmpi ); mbedtls_mpi_init( &Qmpi );
mbedtls_rsa_init( &ctx, MBEDTLS_RSA_PKCS_V15, 0 );
TEST_ASSERT( mbedtls_mpi_read_binary( &Nmpi, N, sizeof( N ) ) == 0 );
TEST_ASSERT( mbedtls_mpi_read_binary( &Empi, E, sizeof( E ) ) == 0 );
TEST_ASSERT( mbedtls_mpi_read_binary( &Pmpi, P, sizeof( P ) ) == 0 );
TEST_ASSERT( mbedtls_mpi_read_binary( &Qmpi, Q, sizeof( Q ) ) == 0 );
TEST_ASSERT( mbedtls_rsa_import( &ctx, &Nmpi, &Pmpi, &Qmpi,
NULL, &Empi ) == 0 );
TEST_ASSERT( mbedtls_rsa_complete( &ctx ) == 0 );
TEST_ASSERT( input->len <= sizeof( N ) );
memcpy( original, input->x, input->len );
memset( original + input->len, 'd', sizeof( original ) - input->len );
if( mode == MBEDTLS_RSA_PRIVATE )
TEST_ASSERT( mbedtls_rsa_public( &ctx, original, intermediate ) == 0 );
else
TEST_ASSERT( mbedtls_rsa_private( &ctx, &rnd_pseudo_rand, &rnd_info,
original, intermediate ) == 0 );
memcpy( final, default_content, sizeof( final ) );
TEST_ASSERT( mbedtls_rsa_pkcs1_decrypt( &ctx,
&rnd_pseudo_rand, &rnd_info,
mode,
&output_length,
intermediate,
final,
output_size ) == expected_result );
if( expected_result == 0 )
{
TEST_ASSERT( output_length == expected_plaintext_length );
TEST_ASSERT( memcmp( original + sizeof( N ) - output_length,
final,
output_length ) == 0 );
}
else if( expected_result == MBEDTLS_ERR_RSA_INVALID_PADDING ||
expected_result == MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE )
{
size_t max_payload_length =
output_size > sizeof( N ) - 11 ? sizeof( N ) - 11 : output_size;
size_t i;
size_t count = 0;
#if !defined(MBEDTLS_RSA_ALT)
/* Check that the output in invalid cases is what the default
* implementation currently does. Alternative implementations
* may produce different output, so we only perform these precise
* checks when using the default implementation. */
TEST_ASSERT( output_length == max_payload_length );
for( i = 0; i < max_payload_length; i++ )
TEST_ASSERT( final[i] == 0 );
#endif
/* Even in alternative implementations, the outputs must have
* changed, otherwise it indicates at least a timing vulnerability
* because no write to the outputs is performed in the bad case. */
TEST_ASSERT( output_length != 0x7EA0 );
for( i = 0; i < max_payload_length; i++ )
count += ( final[i] == default_content[i] );
/* If more than 16 bytes are unchanged in final, that's evidence
* that final wasn't overwritten. */
TEST_ASSERT( count < 16 );
}
exit:
mbedtls_mpi_free( &Nmpi ); mbedtls_mpi_free( &Empi );
mbedtls_mpi_free( &Pmpi ); mbedtls_mpi_free( &Qmpi );
mbedtls_rsa_free( &ctx );
}
/* END_CASE */
/* BEGIN_CASE */ /* BEGIN_CASE */
void pkcs1_rsassa_v15_sign( int mod, int radix_P, char * input_P, int radix_Q, void pkcs1_rsassa_v15_sign( int mod, int radix_P, char * input_P, int radix_Q,
char * input_Q, int radix_N, char * input_N, char * input_Q, int radix_N, char * input_N,

View File

@ -5,7 +5,7 @@
/* END_HEADER */ /* END_HEADER */
/* BEGIN_DEPENDENCIES /* BEGIN_DEPENDENCIES
* depends_on:MBEDTLS_PK_WRITE_C:MBEDTLS_BIGNUM_C:MBEDTLS_FS_IO * depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_BIGNUM_C:MBEDTLS_FS_IO
* END_DEPENDENCIES * END_DEPENDENCIES
*/ */