mirror of
https://git.suyu.dev/suyu/mbedtls.git
synced 2026-03-25 17:02:58 +00:00
Merge branch 'iotssl-1770' into development_thomas_dee
This commit is contained in:
@@ -6,6 +6,7 @@ set(src_crypto
|
||||
aes.c
|
||||
aesni.c
|
||||
arc4.c
|
||||
aria.c
|
||||
asn1parse.c
|
||||
asn1write.c
|
||||
base64.c
|
||||
@@ -13,6 +14,8 @@ set(src_crypto
|
||||
blowfish.c
|
||||
camellia.c
|
||||
ccm.c
|
||||
chacha20.c
|
||||
chachapoly.c
|
||||
cipher.c
|
||||
cipher_wrap.c
|
||||
cmac.c
|
||||
@@ -29,6 +32,7 @@ set(src_crypto
|
||||
error.c
|
||||
gcm.c
|
||||
havege.c
|
||||
hkdf.c
|
||||
hmac_drbg.c
|
||||
md.c
|
||||
md2.c
|
||||
@@ -36,6 +40,7 @@ set(src_crypto
|
||||
md5.c
|
||||
md_wrap.c
|
||||
memory_buffer_alloc.c
|
||||
nist_kw.c
|
||||
oid.c
|
||||
padlock.c
|
||||
pem.c
|
||||
@@ -47,6 +52,7 @@ set(src_crypto
|
||||
pkwrite.c
|
||||
platform.c
|
||||
platform_util.c
|
||||
poly1305.c
|
||||
ripemd160.c
|
||||
rsa.c
|
||||
rsa_internal.c
|
||||
@@ -96,6 +102,17 @@ if(WIN32)
|
||||
set(libs ${libs} ws2_32)
|
||||
endif(WIN32)
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
SET(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> Scr <TARGET> <LINK_FLAGS> <OBJECTS>")
|
||||
SET(CMAKE_CXX_ARCHIVE_CREATE "<CMAKE_AR> Scr <TARGET> <LINK_FLAGS> <OBJECTS>")
|
||||
SET(CMAKE_C_ARCHIVE_FINISH "<CMAKE_RANLIB> -no_warning_for_no_symbols -c <TARGET>")
|
||||
SET(CMAKE_CXX_ARCHIVE_FINISH "<CMAKE_RANLIB> -no_warning_for_no_symbols -c <TARGET>")
|
||||
endif()
|
||||
|
||||
if(HAIKU)
|
||||
set(libs ${libs} network)
|
||||
endif(HAIKU)
|
||||
|
||||
if(USE_PKCS11_HELPER_LIBRARY)
|
||||
set(libs ${libs} pkcs11-helper)
|
||||
endif(USE_PKCS11_HELPER_LIBRARY)
|
||||
@@ -142,15 +159,15 @@ endif(USE_STATIC_MBEDTLS_LIBRARY)
|
||||
|
||||
if(USE_SHARED_MBEDTLS_LIBRARY)
|
||||
add_library(mbedcrypto SHARED ${src_crypto})
|
||||
set_target_properties(mbedcrypto PROPERTIES VERSION 2.9.0 SOVERSION 2)
|
||||
set_target_properties(mbedcrypto PROPERTIES VERSION 2.13.1 SOVERSION 3)
|
||||
target_link_libraries(mbedcrypto ${libs})
|
||||
|
||||
add_library(mbedx509 SHARED ${src_x509})
|
||||
set_target_properties(mbedx509 PROPERTIES VERSION 2.9.0 SOVERSION 0)
|
||||
set_target_properties(mbedx509 PROPERTIES VERSION 2.13.1 SOVERSION 0)
|
||||
target_link_libraries(mbedx509 ${libs} mbedcrypto)
|
||||
|
||||
add_library(mbedtls SHARED ${src_tls})
|
||||
set_target_properties(mbedtls PROPERTIES VERSION 2.9.0 SOVERSION 10)
|
||||
set_target_properties(mbedtls PROPERTIES VERSION 2.13.1 SOVERSION 12)
|
||||
target_link_libraries(mbedtls ${libs} mbedx509)
|
||||
|
||||
install(TARGETS mbedtls mbedx509 mbedcrypto
|
||||
|
||||
@@ -21,6 +21,10 @@ endif
|
||||
# if were running on Windows build for Windows
|
||||
ifdef WINDOWS
|
||||
WINDOWS_BUILD=1
|
||||
else ifeq ($(shell uname -s),Darwin)
|
||||
ifeq ($(AR),ar)
|
||||
APPLE_BUILD ?= 1
|
||||
endif
|
||||
endif
|
||||
|
||||
# To compile as a shared library:
|
||||
@@ -31,42 +35,56 @@ LOCAL_CFLAGS += -fPIC -fpic
|
||||
endif
|
||||
endif
|
||||
|
||||
SOEXT_TLS=so.10
|
||||
SOEXT_TLS=so.12
|
||||
SOEXT_X509=so.0
|
||||
SOEXT_CRYPTO=so.2
|
||||
|
||||
# Set DLEXT=dylib to compile as a shared library for Mac OS X
|
||||
DLEXT ?= so
|
||||
SOEXT_CRYPTO=so.3
|
||||
|
||||
# Set AR_DASH= (empty string) to use an ar implentation that does not accept
|
||||
# the - prefix for command line options (e.g. llvm-ar)
|
||||
AR_DASH ?= -
|
||||
|
||||
# Windows shared library extension:
|
||||
ARFLAGS = $(AR_DASH)src
|
||||
ifdef APPLE_BUILD
|
||||
ifneq ($(APPLE_BUILD),0)
|
||||
ARFLAGS = $(AR_DASH)Src
|
||||
RLFLAGS = -no_warning_for_no_symbols -c
|
||||
RL ?= ranlib
|
||||
endif
|
||||
endif
|
||||
|
||||
DLEXT ?= so
|
||||
ifdef WINDOWS_BUILD
|
||||
DLEXT=dll
|
||||
# Windows shared library extension:
|
||||
DLEXT = dll
|
||||
else ifdef APPLE_BUILD
|
||||
ifneq ($(APPLE_BUILD),0)
|
||||
# Mac OS X shared library extension:
|
||||
DLEXT = dylib
|
||||
endif
|
||||
endif
|
||||
|
||||
OBJS_CRYPTO= aes.o aesni.o arc4.o \
|
||||
asn1parse.o asn1write.o base64.o \
|
||||
bignum.o blowfish.o camellia.o \
|
||||
ccm.o cipher.o cipher_wrap.o \
|
||||
aria.o asn1parse.o asn1write.o \
|
||||
base64.o bignum.o blowfish.o \
|
||||
camellia.o ccm.o chacha20.o \
|
||||
chachapoly.o cipher.o cipher_wrap.o \
|
||||
cmac.o ctr_drbg.o des.o \
|
||||
dhm.o ecdh.o ecdsa.o \
|
||||
ecjpake.o ecp.o \
|
||||
ecp_curves.o entropy.o entropy_poll.o \
|
||||
error.o gcm.o havege.o \
|
||||
hkdf.o \
|
||||
hmac_drbg.o md.o md2.o \
|
||||
md4.o md5.o md_wrap.o \
|
||||
memory_buffer_alloc.o oid.o \
|
||||
padlock.o pem.o pk.o \
|
||||
pk_wrap.o pkcs12.o pkcs5.o \
|
||||
pkparse.o pkwrite.o platform.o \
|
||||
platform_util.o ripemd160.o rsa_internal.o \
|
||||
rsa.o sha1.o sha256.o \
|
||||
sha512.o threading.o timing.o \
|
||||
version.o version_features.o \
|
||||
xtea.o
|
||||
memory_buffer_alloc.o nist_kw.o \
|
||||
oid.o padlock.o pem.o \
|
||||
pk.o pk_wrap.o pkcs12.o \
|
||||
pkcs5.o pkparse.o pkwrite.o \
|
||||
platform.o platform_util.o poly1305.o \
|
||||
ripemd160.o rsa_internal.o rsa.o \
|
||||
sha1.o sha256.o sha512.o \
|
||||
threading.o timing.o version.o \
|
||||
version_features.o xtea.o
|
||||
|
||||
OBJS_X509= certs.o pkcs11.o x509.o \
|
||||
x509_create.o x509_crl.o x509_crt.o \
|
||||
@@ -95,9 +113,13 @@ shared: libmbedcrypto.$(DLEXT) libmbedx509.$(DLEXT) libmbedtls.$(DLEXT)
|
||||
# tls
|
||||
libmbedtls.a: $(OBJS_TLS)
|
||||
echo " AR $@"
|
||||
$(AR) $(AR_DASH)rc $@ $(OBJS_TLS)
|
||||
$(AR) $(ARFLAGS) $@ $(OBJS_TLS)
|
||||
ifdef APPLE_BUILD
|
||||
ifneq ($(APPLE_BUILD),0)
|
||||
echo " RL $@"
|
||||
$(AR) $(AR_DASH)s $@
|
||||
$(RL) $(RLFLAGS) $@
|
||||
endif
|
||||
endif
|
||||
|
||||
libmbedtls.$(SOEXT_TLS): $(OBJS_TLS) libmbedx509.so
|
||||
echo " LD $@"
|
||||
@@ -118,9 +140,13 @@ libmbedtls.dll: $(OBJS_TLS) libmbedx509.dll
|
||||
# x509
|
||||
libmbedx509.a: $(OBJS_X509)
|
||||
echo " AR $@"
|
||||
$(AR) $(AR_DASH)rc $@ $(OBJS_X509)
|
||||
$(AR) $(ARFLAGS) $@ $(OBJS_X509)
|
||||
ifdef APPLE_BUILD
|
||||
ifneq ($(APPLE_BUILD),0)
|
||||
echo " RL $@"
|
||||
$(AR) $(AR_DASH)s $@
|
||||
$(RL) $(RLFLAGS) $@
|
||||
endif
|
||||
endif
|
||||
|
||||
libmbedx509.$(SOEXT_X509): $(OBJS_X509) libmbedcrypto.so
|
||||
echo " LD $@"
|
||||
@@ -141,9 +167,13 @@ libmbedx509.dll: $(OBJS_X509) libmbedcrypto.dll
|
||||
# crypto
|
||||
libmbedcrypto.a: $(OBJS_CRYPTO)
|
||||
echo " AR $@"
|
||||
$(AR) $(AR_DASH)rc $@ $(OBJS_CRYPTO)
|
||||
$(AR) $(ARFLAGS) $@ $(OBJS_CRYPTO)
|
||||
ifdef APPLE_BUILD
|
||||
ifneq ($(APPLE_BUILD),0)
|
||||
echo " RL $@"
|
||||
$(AR) $(AR_DASH)s $@
|
||||
$(RL) $(RLFLAGS) $@
|
||||
endif
|
||||
endif
|
||||
|
||||
libmbedcrypto.$(SOEXT_CRYPTO): $(OBJS_CRYPTO)
|
||||
echo " LD $@"
|
||||
|
||||
555
library/aes.c
555
library/aes.c
@@ -521,6 +521,20 @@ void mbedtls_aes_free( mbedtls_aes_context *ctx )
|
||||
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_aes_context ) );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_CIPHER_MODE_XTS)
|
||||
void mbedtls_aes_xts_init( mbedtls_aes_xts_context *ctx )
|
||||
{
|
||||
mbedtls_aes_init( &ctx->crypt );
|
||||
mbedtls_aes_init( &ctx->tweak );
|
||||
}
|
||||
|
||||
void mbedtls_aes_xts_free( mbedtls_aes_xts_context *ctx )
|
||||
{
|
||||
mbedtls_aes_free( &ctx->crypt );
|
||||
mbedtls_aes_free( &ctx->tweak );
|
||||
}
|
||||
#endif /* MBEDTLS_CIPHER_MODE_XTS */
|
||||
|
||||
/*
|
||||
* AES key schedule (encryption)
|
||||
*/
|
||||
@@ -702,6 +716,78 @@ exit:
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_CIPHER_MODE_XTS)
|
||||
static int mbedtls_aes_xts_decode_keys( const unsigned char *key,
|
||||
unsigned int keybits,
|
||||
const unsigned char **key1,
|
||||
unsigned int *key1bits,
|
||||
const unsigned char **key2,
|
||||
unsigned int *key2bits )
|
||||
{
|
||||
const unsigned int half_keybits = keybits / 2;
|
||||
const unsigned int half_keybytes = half_keybits / 8;
|
||||
|
||||
switch( keybits )
|
||||
{
|
||||
case 256: break;
|
||||
case 512: break;
|
||||
default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
|
||||
}
|
||||
|
||||
*key1bits = half_keybits;
|
||||
*key2bits = half_keybits;
|
||||
*key1 = &key[0];
|
||||
*key2 = &key[half_keybytes];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mbedtls_aes_xts_setkey_enc( mbedtls_aes_xts_context *ctx,
|
||||
const unsigned char *key,
|
||||
unsigned int keybits)
|
||||
{
|
||||
int ret;
|
||||
const unsigned char *key1, *key2;
|
||||
unsigned int key1bits, key2bits;
|
||||
|
||||
ret = mbedtls_aes_xts_decode_keys( key, keybits, &key1, &key1bits,
|
||||
&key2, &key2bits );
|
||||
if( ret != 0 )
|
||||
return( ret );
|
||||
|
||||
/* Set the tweak key. Always set tweak key for the encryption mode. */
|
||||
ret = mbedtls_aes_setkey_enc( &ctx->tweak, key2, key2bits );
|
||||
if( ret != 0 )
|
||||
return( ret );
|
||||
|
||||
/* Set crypt key for encryption. */
|
||||
return mbedtls_aes_setkey_enc( &ctx->crypt, key1, key1bits );
|
||||
}
|
||||
|
||||
int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx,
|
||||
const unsigned char *key,
|
||||
unsigned int keybits)
|
||||
{
|
||||
int ret;
|
||||
const unsigned char *key1, *key2;
|
||||
unsigned int key1bits, key2bits;
|
||||
|
||||
ret = mbedtls_aes_xts_decode_keys( key, keybits, &key1, &key1bits,
|
||||
&key2, &key2bits );
|
||||
if( ret != 0 )
|
||||
return( ret );
|
||||
|
||||
/* Set the tweak key. Always set tweak key for encryption. */
|
||||
ret = mbedtls_aes_setkey_enc( &ctx->tweak, key2, key2bits );
|
||||
if( ret != 0 )
|
||||
return( ret );
|
||||
|
||||
/* Set crypt key for decryption. */
|
||||
return mbedtls_aes_setkey_dec( &ctx->crypt, key1, key1bits );
|
||||
}
|
||||
#endif /* MBEDTLS_CIPHER_MODE_XTS */
|
||||
|
||||
#endif /* !MBEDTLS_AES_SETKEY_DEC_ALT */
|
||||
|
||||
#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
|
||||
@@ -983,6 +1069,165 @@ int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx,
|
||||
}
|
||||
#endif /* MBEDTLS_CIPHER_MODE_CBC */
|
||||
|
||||
#if defined(MBEDTLS_CIPHER_MODE_XTS)
|
||||
|
||||
/* Endianess with 64 bits values */
|
||||
#ifndef GET_UINT64_LE
|
||||
#define GET_UINT64_LE(n,b,i) \
|
||||
{ \
|
||||
(n) = ( (uint64_t) (b)[(i) + 7] << 56 ) \
|
||||
| ( (uint64_t) (b)[(i) + 6] << 48 ) \
|
||||
| ( (uint64_t) (b)[(i) + 5] << 40 ) \
|
||||
| ( (uint64_t) (b)[(i) + 4] << 32 ) \
|
||||
| ( (uint64_t) (b)[(i) + 3] << 24 ) \
|
||||
| ( (uint64_t) (b)[(i) + 2] << 16 ) \
|
||||
| ( (uint64_t) (b)[(i) + 1] << 8 ) \
|
||||
| ( (uint64_t) (b)[(i) ] ); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef PUT_UINT64_LE
|
||||
#define PUT_UINT64_LE(n,b,i) \
|
||||
{ \
|
||||
(b)[(i) + 7] = (unsigned char) ( (n) >> 56 ); \
|
||||
(b)[(i) + 6] = (unsigned char) ( (n) >> 48 ); \
|
||||
(b)[(i) + 5] = (unsigned char) ( (n) >> 40 ); \
|
||||
(b)[(i) + 4] = (unsigned char) ( (n) >> 32 ); \
|
||||
(b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
|
||||
(b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
|
||||
(b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
|
||||
(b)[(i) ] = (unsigned char) ( (n) ); \
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef unsigned char mbedtls_be128[16];
|
||||
|
||||
/*
|
||||
* GF(2^128) multiplication function
|
||||
*
|
||||
* This function multiplies a field element by x in the polynomial field
|
||||
* representation. It uses 64-bit word operations to gain speed but compensates
|
||||
* for machine endianess and hence works correctly on both big and little
|
||||
* endian machines.
|
||||
*/
|
||||
static void mbedtls_gf128mul_x_ble( unsigned char r[16],
|
||||
const unsigned char x[16] )
|
||||
{
|
||||
uint64_t a, b, ra, rb;
|
||||
|
||||
GET_UINT64_LE( a, x, 0 );
|
||||
GET_UINT64_LE( b, x, 8 );
|
||||
|
||||
ra = ( a << 1 ) ^ 0x0087 >> ( 8 - ( ( b >> 63 ) << 3 ) );
|
||||
rb = ( a >> 63 ) | ( b << 1 );
|
||||
|
||||
PUT_UINT64_LE( ra, r, 0 );
|
||||
PUT_UINT64_LE( rb, r, 8 );
|
||||
}
|
||||
|
||||
/*
|
||||
* AES-XTS buffer encryption/decryption
|
||||
*/
|
||||
int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx,
|
||||
int mode,
|
||||
size_t length,
|
||||
const unsigned char data_unit[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output )
|
||||
{
|
||||
int ret;
|
||||
size_t blocks = length / 16;
|
||||
size_t leftover = length % 16;
|
||||
unsigned char tweak[16];
|
||||
unsigned char prev_tweak[16];
|
||||
unsigned char tmp[16];
|
||||
|
||||
/* Sectors must be at least 16 bytes. */
|
||||
if( length < 16 )
|
||||
return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
|
||||
|
||||
/* NIST SP 80-38E disallows data units larger than 2**20 blocks. */
|
||||
if( length > ( 1 << 20 ) * 16 )
|
||||
return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
|
||||
|
||||
/* Compute the tweak. */
|
||||
ret = mbedtls_aes_crypt_ecb( &ctx->tweak, MBEDTLS_AES_ENCRYPT,
|
||||
data_unit, tweak );
|
||||
if( ret != 0 )
|
||||
return( ret );
|
||||
|
||||
while( blocks-- )
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if( leftover && ( mode == MBEDTLS_AES_DECRYPT ) && blocks == 0 )
|
||||
{
|
||||
/* We are on the last block in a decrypt operation that has
|
||||
* leftover bytes, so we need to use the next tweak for this block,
|
||||
* and this tweak for the lefover bytes. Save the current tweak for
|
||||
* the leftovers and then update the current tweak for use on this,
|
||||
* the last full block. */
|
||||
memcpy( prev_tweak, tweak, sizeof( tweak ) );
|
||||
mbedtls_gf128mul_x_ble( tweak, tweak );
|
||||
}
|
||||
|
||||
for( i = 0; i < 16; i++ )
|
||||
tmp[i] = input[i] ^ tweak[i];
|
||||
|
||||
ret = mbedtls_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp );
|
||||
if( ret != 0 )
|
||||
return( ret );
|
||||
|
||||
for( i = 0; i < 16; i++ )
|
||||
output[i] = tmp[i] ^ tweak[i];
|
||||
|
||||
/* Update the tweak for the next block. */
|
||||
mbedtls_gf128mul_x_ble( tweak, tweak );
|
||||
|
||||
output += 16;
|
||||
input += 16;
|
||||
}
|
||||
|
||||
if( leftover )
|
||||
{
|
||||
/* If we are on the leftover bytes in a decrypt operation, we need to
|
||||
* use the previous tweak for these bytes (as saved in prev_tweak). */
|
||||
unsigned char *t = mode == MBEDTLS_AES_DECRYPT ? prev_tweak : tweak;
|
||||
|
||||
/* We are now on the final part of the data unit, which doesn't divide
|
||||
* evenly by 16. It's time for ciphertext stealing. */
|
||||
size_t i;
|
||||
unsigned char *prev_output = output - 16;
|
||||
|
||||
/* Copy ciphertext bytes from the previous block to our output for each
|
||||
* byte of cyphertext we won't steal. At the same time, copy the
|
||||
* remainder of the input for this final round (since the loop bounds
|
||||
* are the same). */
|
||||
for( i = 0; i < leftover; i++ )
|
||||
{
|
||||
output[i] = prev_output[i];
|
||||
tmp[i] = input[i] ^ t[i];
|
||||
}
|
||||
|
||||
/* Copy ciphertext bytes from the previous block for input in this
|
||||
* round. */
|
||||
for( ; i < 16; i++ )
|
||||
tmp[i] = prev_output[i] ^ t[i];
|
||||
|
||||
ret = mbedtls_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp );
|
||||
if( ret != 0 )
|
||||
return ret;
|
||||
|
||||
/* Write the result back to the previous block, overriding the previous
|
||||
* output we copied. */
|
||||
for( i = 0; i < 16; i++ )
|
||||
prev_output[i] = tmp[i] ^ t[i];
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
#endif /* MBEDTLS_CIPHER_MODE_XTS */
|
||||
|
||||
#if defined(MBEDTLS_CIPHER_MODE_CFB)
|
||||
/*
|
||||
* AES-CFB128 buffer encryption/decryption
|
||||
@@ -1061,7 +1306,41 @@ int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx,
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
#endif /*MBEDTLS_CIPHER_MODE_CFB */
|
||||
#endif /* MBEDTLS_CIPHER_MODE_CFB */
|
||||
|
||||
#if defined(MBEDTLS_CIPHER_MODE_OFB)
|
||||
/*
|
||||
* AES-OFB (Output Feedback Mode) buffer encryption/decryption
|
||||
*/
|
||||
int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx,
|
||||
size_t length,
|
||||
size_t *iv_off,
|
||||
unsigned char iv[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output )
|
||||
{
|
||||
int ret = 0;
|
||||
size_t n = *iv_off;
|
||||
|
||||
while( length-- )
|
||||
{
|
||||
if( n == 0 )
|
||||
{
|
||||
ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
|
||||
if( ret != 0 )
|
||||
goto exit;
|
||||
}
|
||||
*output++ = *input++ ^ iv[n];
|
||||
|
||||
n = ( n + 1 ) & 0x0F;
|
||||
}
|
||||
|
||||
*iv_off = n;
|
||||
|
||||
exit:
|
||||
return( ret );
|
||||
}
|
||||
#endif /* MBEDTLS_CIPHER_MODE_OFB */
|
||||
|
||||
#if defined(MBEDTLS_CIPHER_MODE_CTR)
|
||||
/*
|
||||
@@ -1078,6 +1357,9 @@ int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx,
|
||||
int c, i;
|
||||
size_t n = *nc_off;
|
||||
|
||||
if ( n > 0x0F )
|
||||
return( MBEDTLS_ERR_AES_BAD_INPUT_DATA );
|
||||
|
||||
while( length-- )
|
||||
{
|
||||
if( n == 0 ) {
|
||||
@@ -1215,6 +1497,72 @@ static const unsigned char aes_test_cfb128_ct[3][64] =
|
||||
};
|
||||
#endif /* MBEDTLS_CIPHER_MODE_CFB */
|
||||
|
||||
#if defined(MBEDTLS_CIPHER_MODE_OFB)
|
||||
/*
|
||||
* AES-OFB test vectors from:
|
||||
*
|
||||
* https://csrc.nist.gov/publications/detail/sp/800-38a/final
|
||||
*/
|
||||
static const unsigned char aes_test_ofb_key[3][32] =
|
||||
{
|
||||
{ 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
|
||||
0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C },
|
||||
{ 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52,
|
||||
0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5,
|
||||
0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B },
|
||||
{ 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE,
|
||||
0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81,
|
||||
0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7,
|
||||
0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 }
|
||||
};
|
||||
|
||||
static const unsigned char aes_test_ofb_iv[16] =
|
||||
{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
|
||||
};
|
||||
|
||||
static const unsigned char aes_test_ofb_pt[64] =
|
||||
{
|
||||
0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96,
|
||||
0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A,
|
||||
0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C,
|
||||
0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51,
|
||||
0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11,
|
||||
0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF,
|
||||
0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17,
|
||||
0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10
|
||||
};
|
||||
|
||||
static const unsigned char aes_test_ofb_ct[3][64] =
|
||||
{
|
||||
{ 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20,
|
||||
0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A,
|
||||
0x77, 0x89, 0x50, 0x8d, 0x16, 0x91, 0x8f, 0x03,
|
||||
0xf5, 0x3c, 0x52, 0xda, 0xc5, 0x4e, 0xd8, 0x25,
|
||||
0x97, 0x40, 0x05, 0x1e, 0x9c, 0x5f, 0xec, 0xf6,
|
||||
0x43, 0x44, 0xf7, 0xa8, 0x22, 0x60, 0xed, 0xcc,
|
||||
0x30, 0x4c, 0x65, 0x28, 0xf6, 0x59, 0xc7, 0x78,
|
||||
0x66, 0xa5, 0x10, 0xd9, 0xc1, 0xd6, 0xae, 0x5e },
|
||||
{ 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB,
|
||||
0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74,
|
||||
0xfc, 0xc2, 0x8b, 0x8d, 0x4c, 0x63, 0x83, 0x7c,
|
||||
0x09, 0xe8, 0x17, 0x00, 0xc1, 0x10, 0x04, 0x01,
|
||||
0x8d, 0x9a, 0x9a, 0xea, 0xc0, 0xf6, 0x59, 0x6f,
|
||||
0x55, 0x9c, 0x6d, 0x4d, 0xaf, 0x59, 0xa5, 0xf2,
|
||||
0x6d, 0x9f, 0x20, 0x08, 0x57, 0xca, 0x6c, 0x3e,
|
||||
0x9c, 0xac, 0x52, 0x4b, 0xd9, 0xac, 0xc9, 0x2a },
|
||||
{ 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B,
|
||||
0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60,
|
||||
0x4f, 0xeb, 0xdc, 0x67, 0x40, 0xd2, 0x0b, 0x3a,
|
||||
0xc8, 0x8f, 0x6a, 0xd8, 0x2a, 0x4f, 0xb0, 0x8d,
|
||||
0x71, 0xab, 0x47, 0xa0, 0x86, 0xe8, 0x6e, 0xed,
|
||||
0xf3, 0x9d, 0x1c, 0x5b, 0xba, 0x97, 0xc4, 0x08,
|
||||
0x01, 0x26, 0x14, 0x1d, 0x67, 0xf3, 0x7b, 0xe8,
|
||||
0x53, 0x8f, 0x5a, 0x8b, 0xe7, 0x40, 0xe4, 0x84 }
|
||||
};
|
||||
#endif /* MBEDTLS_CIPHER_MODE_OFB */
|
||||
|
||||
#if defined(MBEDTLS_CIPHER_MODE_CTR)
|
||||
/*
|
||||
* AES-CTR test vectors from:
|
||||
@@ -1278,6 +1626,74 @@ static const int aes_test_ctr_len[3] =
|
||||
{ 16, 32, 36 };
|
||||
#endif /* MBEDTLS_CIPHER_MODE_CTR */
|
||||
|
||||
#if defined(MBEDTLS_CIPHER_MODE_XTS)
|
||||
/*
|
||||
* AES-XTS test vectors from:
|
||||
*
|
||||
* IEEE P1619/D16 Annex B
|
||||
* https://web.archive.org/web/20150629024421/http://grouper.ieee.org/groups/1619/email/pdf00086.pdf
|
||||
* (Archived from original at http://grouper.ieee.org/groups/1619/email/pdf00086.pdf)
|
||||
*/
|
||||
static const unsigned char aes_test_xts_key[][32] =
|
||||
{
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
{ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
|
||||
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
|
||||
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
|
||||
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 },
|
||||
{ 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8,
|
||||
0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
|
||||
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
|
||||
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 },
|
||||
};
|
||||
|
||||
static const unsigned char aes_test_xts_pt32[][32] =
|
||||
{
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
{ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
|
||||
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
|
||||
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
|
||||
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 },
|
||||
{ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
|
||||
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
|
||||
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
|
||||
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 },
|
||||
};
|
||||
|
||||
static const unsigned char aes_test_xts_ct32[][32] =
|
||||
{
|
||||
{ 0x91, 0x7c, 0xf6, 0x9e, 0xbd, 0x68, 0xb2, 0xec,
|
||||
0x9b, 0x9f, 0xe9, 0xa3, 0xea, 0xdd, 0xa6, 0x92,
|
||||
0xcd, 0x43, 0xd2, 0xf5, 0x95, 0x98, 0xed, 0x85,
|
||||
0x8c, 0x02, 0xc2, 0x65, 0x2f, 0xbf, 0x92, 0x2e },
|
||||
{ 0xc4, 0x54, 0x18, 0x5e, 0x6a, 0x16, 0x93, 0x6e,
|
||||
0x39, 0x33, 0x40, 0x38, 0xac, 0xef, 0x83, 0x8b,
|
||||
0xfb, 0x18, 0x6f, 0xff, 0x74, 0x80, 0xad, 0xc4,
|
||||
0x28, 0x93, 0x82, 0xec, 0xd6, 0xd3, 0x94, 0xf0 },
|
||||
{ 0xaf, 0x85, 0x33, 0x6b, 0x59, 0x7a, 0xfc, 0x1a,
|
||||
0x90, 0x0b, 0x2e, 0xb2, 0x1e, 0xc9, 0x49, 0xd2,
|
||||
0x92, 0xdf, 0x4c, 0x04, 0x7e, 0x0b, 0x21, 0x53,
|
||||
0x21, 0x86, 0xa5, 0x97, 0x1a, 0x22, 0x7a, 0x89 },
|
||||
};
|
||||
|
||||
static const unsigned char aes_test_xts_data_unit[][16] =
|
||||
{
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
{ 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
{ 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
};
|
||||
|
||||
#endif /* MBEDTLS_CIPHER_MODE_XTS */
|
||||
|
||||
/*
|
||||
* Checkup routine
|
||||
*/
|
||||
@@ -1294,11 +1710,14 @@ int mbedtls_aes_self_test( int verbose )
|
||||
#if defined(MBEDTLS_CIPHER_MODE_CBC)
|
||||
unsigned char prv[16];
|
||||
#endif
|
||||
#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_CFB)
|
||||
#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_CFB) || \
|
||||
defined(MBEDTLS_CIPHER_MODE_OFB)
|
||||
size_t offset;
|
||||
#endif
|
||||
#if defined(MBEDTLS_CIPHER_MODE_CTR)
|
||||
#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_XTS)
|
||||
int len;
|
||||
#endif
|
||||
#if defined(MBEDTLS_CIPHER_MODE_CTR)
|
||||
unsigned char nonce_counter[16];
|
||||
unsigned char stream_block[16];
|
||||
#endif
|
||||
@@ -1506,6 +1925,69 @@ int mbedtls_aes_self_test( int verbose )
|
||||
mbedtls_printf( "\n" );
|
||||
#endif /* MBEDTLS_CIPHER_MODE_CFB */
|
||||
|
||||
#if defined(MBEDTLS_CIPHER_MODE_OFB)
|
||||
/*
|
||||
* OFB mode
|
||||
*/
|
||||
for( i = 0; i < 6; i++ )
|
||||
{
|
||||
u = i >> 1;
|
||||
keybits = 128 + u * 64;
|
||||
mode = i & 1;
|
||||
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( " AES-OFB-%3d (%s): ", keybits,
|
||||
( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
|
||||
|
||||
memcpy( iv, aes_test_ofb_iv, 16 );
|
||||
memcpy( key, aes_test_ofb_key[u], keybits / 8 );
|
||||
|
||||
offset = 0;
|
||||
ret = mbedtls_aes_setkey_enc( &ctx, key, keybits );
|
||||
/*
|
||||
* AES-192 is an optional feature that may be unavailable when
|
||||
* there is an alternative underlying implementation i.e. when
|
||||
* MBEDTLS_AES_ALT is defined.
|
||||
*/
|
||||
if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 )
|
||||
{
|
||||
mbedtls_printf( "skipped\n" );
|
||||
continue;
|
||||
}
|
||||
else if( ret != 0 )
|
||||
{
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if( mode == MBEDTLS_AES_DECRYPT )
|
||||
{
|
||||
memcpy( buf, aes_test_ofb_ct[u], 64 );
|
||||
aes_tests = aes_test_ofb_pt;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy( buf, aes_test_ofb_pt, 64 );
|
||||
aes_tests = aes_test_ofb_ct[u];
|
||||
}
|
||||
|
||||
ret = mbedtls_aes_crypt_ofb( &ctx, 64, &offset, iv, buf, buf );
|
||||
if( ret != 0 )
|
||||
goto exit;
|
||||
|
||||
if( memcmp( buf, aes_tests, 64 ) != 0 )
|
||||
{
|
||||
ret = 1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( "passed\n" );
|
||||
}
|
||||
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( "\n" );
|
||||
#endif /* MBEDTLS_CIPHER_MODE_OFB */
|
||||
|
||||
#if defined(MBEDTLS_CIPHER_MODE_CTR)
|
||||
/*
|
||||
* CTR mode
|
||||
@@ -1558,6 +2040,73 @@ int mbedtls_aes_self_test( int verbose )
|
||||
mbedtls_printf( "\n" );
|
||||
#endif /* MBEDTLS_CIPHER_MODE_CTR */
|
||||
|
||||
#if defined(MBEDTLS_CIPHER_MODE_XTS)
|
||||
{
|
||||
static const int num_tests =
|
||||
sizeof(aes_test_xts_key) / sizeof(*aes_test_xts_key);
|
||||
mbedtls_aes_xts_context ctx_xts;
|
||||
|
||||
/*
|
||||
* XTS mode
|
||||
*/
|
||||
mbedtls_aes_xts_init( &ctx_xts );
|
||||
|
||||
for( i = 0; i < num_tests << 1; i++ )
|
||||
{
|
||||
const unsigned char *data_unit;
|
||||
u = i >> 1;
|
||||
mode = i & 1;
|
||||
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( " AES-XTS-128 (%s): ",
|
||||
( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
|
||||
|
||||
memset( key, 0, sizeof( key ) );
|
||||
memcpy( key, aes_test_xts_key[u], 32 );
|
||||
data_unit = aes_test_xts_data_unit[u];
|
||||
|
||||
len = sizeof( *aes_test_xts_ct32 );
|
||||
|
||||
if( mode == MBEDTLS_AES_DECRYPT )
|
||||
{
|
||||
ret = mbedtls_aes_xts_setkey_dec( &ctx_xts, key, 256 );
|
||||
if( ret != 0)
|
||||
goto exit;
|
||||
memcpy( buf, aes_test_xts_ct32[u], len );
|
||||
aes_tests = aes_test_xts_pt32[u];
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = mbedtls_aes_xts_setkey_enc( &ctx_xts, key, 256 );
|
||||
if( ret != 0)
|
||||
goto exit;
|
||||
memcpy( buf, aes_test_xts_pt32[u], len );
|
||||
aes_tests = aes_test_xts_ct32[u];
|
||||
}
|
||||
|
||||
|
||||
ret = mbedtls_aes_crypt_xts( &ctx_xts, mode, len, data_unit,
|
||||
buf, buf );
|
||||
if( ret != 0 )
|
||||
goto exit;
|
||||
|
||||
if( memcmp( buf, aes_tests, len ) != 0 )
|
||||
{
|
||||
ret = 1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( "passed\n" );
|
||||
}
|
||||
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( "\n" );
|
||||
|
||||
mbedtls_aes_xts_free( &ctx_xts );
|
||||
}
|
||||
#endif /* MBEDTLS_CIPHER_MODE_XTS */
|
||||
|
||||
ret = 0;
|
||||
|
||||
exit:
|
||||
|
||||
1028
library/aria.c
Normal file
1028
library/aria.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -83,7 +83,9 @@ int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len
|
||||
return( 4 );
|
||||
}
|
||||
|
||||
#if SIZE_MAX > 0xFFFFFFFF
|
||||
if( len <= 0xFFFFFFFF )
|
||||
#endif
|
||||
{
|
||||
if( *p - start < 5 )
|
||||
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
|
||||
@@ -96,7 +98,9 @@ int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len
|
||||
return( 5 );
|
||||
}
|
||||
|
||||
#if SIZE_MAX > 0xFFFFFFFF
|
||||
return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
|
||||
#endif
|
||||
}
|
||||
|
||||
int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag )
|
||||
|
||||
@@ -152,8 +152,10 @@ static int ccm_auth_crypt( mbedtls_ccm_context *ctx, int mode, size_t length,
|
||||
* Check length requirements: SP800-38C A.1
|
||||
* Additional requirement: a < 2^16 - 2^8 to simplify the code.
|
||||
* 'length' checked later (when writing it to the first block)
|
||||
*
|
||||
* Also, loosen the requirements to enable support for CCM* (IEEE 802.15.4).
|
||||
*/
|
||||
if( tag_len < 4 || tag_len > 16 || tag_len % 2 != 0 )
|
||||
if( tag_len == 2 || tag_len > 16 || tag_len % 2 != 0 )
|
||||
return( MBEDTLS_ERR_CCM_BAD_INPUT );
|
||||
|
||||
/* Also implies q is within bounds */
|
||||
@@ -302,7 +304,7 @@ static int ccm_auth_crypt( mbedtls_ccm_context *ctx, int mode, size_t length,
|
||||
/*
|
||||
* Authenticated encryption
|
||||
*/
|
||||
int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
|
||||
int mbedtls_ccm_star_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
|
||||
const unsigned char *iv, size_t iv_len,
|
||||
const unsigned char *add, size_t add_len,
|
||||
const unsigned char *input, unsigned char *output,
|
||||
@@ -312,10 +314,23 @@ int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
|
||||
add, add_len, input, output, tag, tag_len ) );
|
||||
}
|
||||
|
||||
int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
|
||||
const unsigned char *iv, size_t iv_len,
|
||||
const unsigned char *add, size_t add_len,
|
||||
const unsigned char *input, unsigned char *output,
|
||||
unsigned char *tag, size_t tag_len )
|
||||
{
|
||||
if( tag_len == 0 )
|
||||
return( MBEDTLS_ERR_CCM_BAD_INPUT );
|
||||
|
||||
return( mbedtls_ccm_star_encrypt_and_tag( ctx, length, iv, iv_len, add,
|
||||
add_len, input, output, tag, tag_len ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* Authenticated decryption
|
||||
*/
|
||||
int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
|
||||
int mbedtls_ccm_star_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
|
||||
const unsigned char *iv, size_t iv_len,
|
||||
const unsigned char *add, size_t add_len,
|
||||
const unsigned char *input, unsigned char *output,
|
||||
@@ -346,6 +361,18 @@ int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
|
||||
const unsigned char *iv, size_t iv_len,
|
||||
const unsigned char *add, size_t add_len,
|
||||
const unsigned char *input, unsigned char *output,
|
||||
const unsigned char *tag, size_t tag_len )
|
||||
{
|
||||
if( tag_len == 0 )
|
||||
return( MBEDTLS_ERR_CCM_BAD_INPUT );
|
||||
|
||||
return( mbedtls_ccm_star_auth_decrypt( ctx, length, iv, iv_len, add,
|
||||
add_len, input, output, tag, tag_len ) );
|
||||
}
|
||||
#endif /* !MBEDTLS_CCM_ALT */
|
||||
|
||||
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
|
||||
@@ -354,7 +381,8 @@ int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
|
||||
*/
|
||||
|
||||
#define NB_TESTS 3
|
||||
|
||||
#define CCM_SELFTEST_PT_MAX_LEN 24
|
||||
#define CCM_SELFTEST_CT_MAX_LEN 32
|
||||
/*
|
||||
* The data is the same for all tests, only the used length changes
|
||||
*/
|
||||
@@ -374,7 +402,7 @@ static const unsigned char ad[] = {
|
||||
0x10, 0x11, 0x12, 0x13
|
||||
};
|
||||
|
||||
static const unsigned char msg[] = {
|
||||
static const unsigned char msg[CCM_SELFTEST_PT_MAX_LEN] = {
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
|
||||
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
|
||||
@@ -385,7 +413,7 @@ static const size_t add_len[NB_TESTS] = { 8, 16, 20 };
|
||||
static const size_t msg_len[NB_TESTS] = { 4, 16, 24 };
|
||||
static const size_t tag_len[NB_TESTS] = { 4, 6, 8 };
|
||||
|
||||
static const unsigned char res[NB_TESTS][32] = {
|
||||
static const unsigned char res[NB_TESTS][CCM_SELFTEST_CT_MAX_LEN] = {
|
||||
{ 0x71, 0x62, 0x01, 0x5b, 0x4d, 0xac, 0x25, 0x5d },
|
||||
{ 0xd2, 0xa1, 0xf0, 0xe0, 0x51, 0xea, 0x5f, 0x62,
|
||||
0x08, 0x1a, 0x77, 0x92, 0x07, 0x3d, 0x59, 0x3d,
|
||||
@@ -399,7 +427,13 @@ static const unsigned char res[NB_TESTS][32] = {
|
||||
int mbedtls_ccm_self_test( int verbose )
|
||||
{
|
||||
mbedtls_ccm_context ctx;
|
||||
unsigned char out[32];
|
||||
/*
|
||||
* Some hardware accelerators require the input and output buffers
|
||||
* would be in RAM, because the flash is not accessible.
|
||||
* Use buffers on the stack to hold the test vectors data.
|
||||
*/
|
||||
unsigned char plaintext[CCM_SELFTEST_PT_MAX_LEN];
|
||||
unsigned char ciphertext[CCM_SELFTEST_CT_MAX_LEN];
|
||||
size_t i;
|
||||
int ret;
|
||||
|
||||
@@ -418,27 +452,32 @@ int mbedtls_ccm_self_test( int verbose )
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( " CCM-AES #%u: ", (unsigned int) i + 1 );
|
||||
|
||||
memset( plaintext, 0, CCM_SELFTEST_PT_MAX_LEN );
|
||||
memset( ciphertext, 0, CCM_SELFTEST_CT_MAX_LEN );
|
||||
memcpy( plaintext, msg, msg_len[i] );
|
||||
|
||||
ret = mbedtls_ccm_encrypt_and_tag( &ctx, msg_len[i],
|
||||
iv, iv_len[i], ad, add_len[i],
|
||||
msg, out,
|
||||
out + msg_len[i], tag_len[i] );
|
||||
iv, iv_len[i], ad, add_len[i],
|
||||
plaintext, ciphertext,
|
||||
ciphertext + msg_len[i], tag_len[i] );
|
||||
|
||||
if( ret != 0 ||
|
||||
memcmp( out, res[i], msg_len[i] + tag_len[i] ) != 0 )
|
||||
memcmp( ciphertext, res[i], msg_len[i] + tag_len[i] ) != 0 )
|
||||
{
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( "failed\n" );
|
||||
|
||||
return( 1 );
|
||||
}
|
||||
memset( plaintext, 0, CCM_SELFTEST_PT_MAX_LEN );
|
||||
|
||||
ret = mbedtls_ccm_auth_decrypt( &ctx, msg_len[i],
|
||||
iv, iv_len[i], ad, add_len[i],
|
||||
res[i], out,
|
||||
res[i] + msg_len[i], tag_len[i] );
|
||||
iv, iv_len[i], ad, add_len[i],
|
||||
ciphertext, plaintext,
|
||||
ciphertext + msg_len[i], tag_len[i] );
|
||||
|
||||
if( ret != 0 ||
|
||||
memcmp( out, msg, msg_len[i] ) != 0 )
|
||||
memcmp( plaintext, msg, msg_len[i] ) != 0 )
|
||||
{
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( "failed\n" );
|
||||
|
||||
570
library/chacha20.c
Normal file
570
library/chacha20.c
Normal file
@@ -0,0 +1,570 @@
|
||||
/**
|
||||
* \file chacha20.c
|
||||
*
|
||||
* \brief ChaCha20 cipher.
|
||||
*
|
||||
* \author Daniel King <damaki.gh@gmail.com>
|
||||
*
|
||||
* Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is part of mbed TLS (https://tls.mbed.org)
|
||||
*/
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_CHACHA20_C)
|
||||
|
||||
#include "mbedtls/chacha20.h"
|
||||
#include "mbedtls/platform_util.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(MBEDTLS_SELF_TEST)
|
||||
#if defined(MBEDTLS_PLATFORM_C)
|
||||
#include "mbedtls/platform.h"
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#define mbedtls_printf printf
|
||||
#endif /* MBEDTLS_PLATFORM_C */
|
||||
#endif /* MBEDTLS_SELF_TEST */
|
||||
|
||||
#if !defined(MBEDTLS_CHACHA20_ALT)
|
||||
|
||||
#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
|
||||
!defined(inline) && !defined(__cplusplus)
|
||||
#define inline __inline
|
||||
#endif
|
||||
|
||||
#define BYTES_TO_U32_LE( data, offset ) \
|
||||
( (uint32_t) data[offset] \
|
||||
| (uint32_t) ( (uint32_t) data[( offset ) + 1] << 8 ) \
|
||||
| (uint32_t) ( (uint32_t) data[( offset ) + 2] << 16 ) \
|
||||
| (uint32_t) ( (uint32_t) data[( offset ) + 3] << 24 ) \
|
||||
)
|
||||
|
||||
#define ROTL32( value, amount ) \
|
||||
( (uint32_t) ( value << amount ) | ( value >> ( 32 - amount ) ) )
|
||||
|
||||
#define CHACHA20_CTR_INDEX ( 12U )
|
||||
|
||||
#define CHACHA20_BLOCK_SIZE_BYTES ( 4U * 16U )
|
||||
|
||||
/**
|
||||
* \brief ChaCha20 quarter round operation.
|
||||
*
|
||||
* The quarter round is defined as follows (from RFC 7539):
|
||||
* 1. a += b; d ^= a; d <<<= 16;
|
||||
* 2. c += d; b ^= c; b <<<= 12;
|
||||
* 3. a += b; d ^= a; d <<<= 8;
|
||||
* 4. c += d; b ^= c; b <<<= 7;
|
||||
*
|
||||
* \param state ChaCha20 state to modify.
|
||||
* \param a The index of 'a' in the state.
|
||||
* \param b The index of 'b' in the state.
|
||||
* \param c The index of 'c' in the state.
|
||||
* \param d The index of 'd' in the state.
|
||||
*/
|
||||
static inline void chacha20_quarter_round( uint32_t state[16],
|
||||
size_t a,
|
||||
size_t b,
|
||||
size_t c,
|
||||
size_t d )
|
||||
{
|
||||
/* a += b; d ^= a; d <<<= 16; */
|
||||
state[a] += state[b];
|
||||
state[d] ^= state[a];
|
||||
state[d] = ROTL32( state[d], 16 );
|
||||
|
||||
/* c += d; b ^= c; b <<<= 12 */
|
||||
state[c] += state[d];
|
||||
state[b] ^= state[c];
|
||||
state[b] = ROTL32( state[b], 12 );
|
||||
|
||||
/* a += b; d ^= a; d <<<= 8; */
|
||||
state[a] += state[b];
|
||||
state[d] ^= state[a];
|
||||
state[d] = ROTL32( state[d], 8 );
|
||||
|
||||
/* c += d; b ^= c; b <<<= 7; */
|
||||
state[c] += state[d];
|
||||
state[b] ^= state[c];
|
||||
state[b] = ROTL32( state[b], 7 );
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Perform the ChaCha20 inner block operation.
|
||||
*
|
||||
* This function performs two rounds: the column round and the
|
||||
* diagonal round.
|
||||
*
|
||||
* \param state The ChaCha20 state to update.
|
||||
*/
|
||||
static void chacha20_inner_block( uint32_t state[16] )
|
||||
{
|
||||
chacha20_quarter_round( state, 0, 4, 8, 12 );
|
||||
chacha20_quarter_round( state, 1, 5, 9, 13 );
|
||||
chacha20_quarter_round( state, 2, 6, 10, 14 );
|
||||
chacha20_quarter_round( state, 3, 7, 11, 15 );
|
||||
|
||||
chacha20_quarter_round( state, 0, 5, 10, 15 );
|
||||
chacha20_quarter_round( state, 1, 6, 11, 12 );
|
||||
chacha20_quarter_round( state, 2, 7, 8, 13 );
|
||||
chacha20_quarter_round( state, 3, 4, 9, 14 );
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Generates a keystream block.
|
||||
*
|
||||
* \param initial_state The initial ChaCha20 state (key, nonce, counter).
|
||||
* \param keystream Generated keystream bytes are written to this buffer.
|
||||
*/
|
||||
static void chacha20_block( const uint32_t initial_state[16],
|
||||
unsigned char keystream[64] )
|
||||
{
|
||||
uint32_t working_state[16];
|
||||
size_t i;
|
||||
|
||||
memcpy( working_state,
|
||||
initial_state,
|
||||
CHACHA20_BLOCK_SIZE_BYTES );
|
||||
|
||||
for( i = 0U; i < 10U; i++ )
|
||||
chacha20_inner_block( working_state );
|
||||
|
||||
working_state[ 0] += initial_state[ 0];
|
||||
working_state[ 1] += initial_state[ 1];
|
||||
working_state[ 2] += initial_state[ 2];
|
||||
working_state[ 3] += initial_state[ 3];
|
||||
working_state[ 4] += initial_state[ 4];
|
||||
working_state[ 5] += initial_state[ 5];
|
||||
working_state[ 6] += initial_state[ 6];
|
||||
working_state[ 7] += initial_state[ 7];
|
||||
working_state[ 8] += initial_state[ 8];
|
||||
working_state[ 9] += initial_state[ 9];
|
||||
working_state[10] += initial_state[10];
|
||||
working_state[11] += initial_state[11];
|
||||
working_state[12] += initial_state[12];
|
||||
working_state[13] += initial_state[13];
|
||||
working_state[14] += initial_state[14];
|
||||
working_state[15] += initial_state[15];
|
||||
|
||||
for( i = 0U; i < 16; i++ )
|
||||
{
|
||||
size_t offset = i * 4U;
|
||||
|
||||
keystream[offset ] = (unsigned char)( working_state[i] );
|
||||
keystream[offset + 1U] = (unsigned char)( working_state[i] >> 8 );
|
||||
keystream[offset + 2U] = (unsigned char)( working_state[i] >> 16 );
|
||||
keystream[offset + 3U] = (unsigned char)( working_state[i] >> 24 );
|
||||
}
|
||||
|
||||
mbedtls_platform_zeroize( working_state, sizeof( working_state ) );
|
||||
}
|
||||
|
||||
void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx )
|
||||
{
|
||||
if( ctx != NULL )
|
||||
{
|
||||
mbedtls_platform_zeroize( ctx->state, sizeof( ctx->state ) );
|
||||
mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
|
||||
|
||||
/* Initially, there's no keystream bytes available */
|
||||
ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
|
||||
}
|
||||
}
|
||||
|
||||
void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx )
|
||||
{
|
||||
if( ctx != NULL )
|
||||
{
|
||||
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_chacha20_context ) );
|
||||
}
|
||||
}
|
||||
|
||||
int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx,
|
||||
const unsigned char key[32] )
|
||||
{
|
||||
if( ( ctx == NULL ) || ( key == NULL ) )
|
||||
{
|
||||
return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
|
||||
}
|
||||
|
||||
/* ChaCha20 constants - the string "expand 32-byte k" */
|
||||
ctx->state[0] = 0x61707865;
|
||||
ctx->state[1] = 0x3320646e;
|
||||
ctx->state[2] = 0x79622d32;
|
||||
ctx->state[3] = 0x6b206574;
|
||||
|
||||
/* Set key */
|
||||
ctx->state[4] = BYTES_TO_U32_LE( key, 0 );
|
||||
ctx->state[5] = BYTES_TO_U32_LE( key, 4 );
|
||||
ctx->state[6] = BYTES_TO_U32_LE( key, 8 );
|
||||
ctx->state[7] = BYTES_TO_U32_LE( key, 12 );
|
||||
ctx->state[8] = BYTES_TO_U32_LE( key, 16 );
|
||||
ctx->state[9] = BYTES_TO_U32_LE( key, 20 );
|
||||
ctx->state[10] = BYTES_TO_U32_LE( key, 24 );
|
||||
ctx->state[11] = BYTES_TO_U32_LE( key, 28 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx,
|
||||
const unsigned char nonce[12],
|
||||
uint32_t counter )
|
||||
{
|
||||
if( ( ctx == NULL ) || ( nonce == NULL ) )
|
||||
{
|
||||
return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
|
||||
}
|
||||
|
||||
/* Counter */
|
||||
ctx->state[12] = counter;
|
||||
|
||||
/* Nonce */
|
||||
ctx->state[13] = BYTES_TO_U32_LE( nonce, 0 );
|
||||
ctx->state[14] = BYTES_TO_U32_LE( nonce, 4 );
|
||||
ctx->state[15] = BYTES_TO_U32_LE( nonce, 8 );
|
||||
|
||||
mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
|
||||
|
||||
/* Initially, there's no keystream bytes available */
|
||||
ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx,
|
||||
size_t size,
|
||||
const unsigned char *input,
|
||||
unsigned char *output )
|
||||
{
|
||||
size_t offset = 0U;
|
||||
size_t i;
|
||||
|
||||
if( ctx == NULL )
|
||||
{
|
||||
return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
|
||||
}
|
||||
else if( ( size > 0U ) && ( ( input == NULL ) || ( output == NULL ) ) )
|
||||
{
|
||||
/* input and output pointers are allowed to be NULL only if size == 0 */
|
||||
return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
|
||||
}
|
||||
|
||||
/* Use leftover keystream bytes, if available */
|
||||
while( size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES )
|
||||
{
|
||||
output[offset] = input[offset]
|
||||
^ ctx->keystream8[ctx->keystream_bytes_used];
|
||||
|
||||
ctx->keystream_bytes_used++;
|
||||
offset++;
|
||||
size--;
|
||||
}
|
||||
|
||||
/* Process full blocks */
|
||||
while( size >= CHACHA20_BLOCK_SIZE_BYTES )
|
||||
{
|
||||
/* Generate new keystream block and increment counter */
|
||||
chacha20_block( ctx->state, ctx->keystream8 );
|
||||
ctx->state[CHACHA20_CTR_INDEX]++;
|
||||
|
||||
for( i = 0U; i < 64U; i += 8U )
|
||||
{
|
||||
output[offset + i ] = input[offset + i ] ^ ctx->keystream8[i ];
|
||||
output[offset + i+1] = input[offset + i+1] ^ ctx->keystream8[i+1];
|
||||
output[offset + i+2] = input[offset + i+2] ^ ctx->keystream8[i+2];
|
||||
output[offset + i+3] = input[offset + i+3] ^ ctx->keystream8[i+3];
|
||||
output[offset + i+4] = input[offset + i+4] ^ ctx->keystream8[i+4];
|
||||
output[offset + i+5] = input[offset + i+5] ^ ctx->keystream8[i+5];
|
||||
output[offset + i+6] = input[offset + i+6] ^ ctx->keystream8[i+6];
|
||||
output[offset + i+7] = input[offset + i+7] ^ ctx->keystream8[i+7];
|
||||
}
|
||||
|
||||
offset += CHACHA20_BLOCK_SIZE_BYTES;
|
||||
size -= CHACHA20_BLOCK_SIZE_BYTES;
|
||||
}
|
||||
|
||||
/* Last (partial) block */
|
||||
if( size > 0U )
|
||||
{
|
||||
/* Generate new keystream block and increment counter */
|
||||
chacha20_block( ctx->state, ctx->keystream8 );
|
||||
ctx->state[CHACHA20_CTR_INDEX]++;
|
||||
|
||||
for( i = 0U; i < size; i++)
|
||||
{
|
||||
output[offset + i] = input[offset + i] ^ ctx->keystream8[i];
|
||||
}
|
||||
|
||||
ctx->keystream_bytes_used = size;
|
||||
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int mbedtls_chacha20_crypt( const unsigned char key[32],
|
||||
const unsigned char nonce[12],
|
||||
uint32_t counter,
|
||||
size_t data_len,
|
||||
const unsigned char* input,
|
||||
unsigned char* output )
|
||||
{
|
||||
mbedtls_chacha20_context ctx;
|
||||
int ret;
|
||||
|
||||
mbedtls_chacha20_init( &ctx );
|
||||
|
||||
ret = mbedtls_chacha20_setkey( &ctx, key );
|
||||
if( ret != 0 )
|
||||
goto cleanup;
|
||||
|
||||
ret = mbedtls_chacha20_starts( &ctx, nonce, counter );
|
||||
if( ret != 0 )
|
||||
goto cleanup;
|
||||
|
||||
ret = mbedtls_chacha20_update( &ctx, data_len, input, output );
|
||||
|
||||
cleanup:
|
||||
mbedtls_chacha20_free( &ctx );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
#endif /* !MBEDTLS_CHACHA20_ALT */
|
||||
|
||||
#if defined(MBEDTLS_SELF_TEST)
|
||||
|
||||
static const unsigned char test_keys[2][32] =
|
||||
{
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
},
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
|
||||
}
|
||||
};
|
||||
|
||||
static const unsigned char test_nonces[2][12] =
|
||||
{
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00
|
||||
},
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x02
|
||||
}
|
||||
};
|
||||
|
||||
static const uint32_t test_counters[2] =
|
||||
{
|
||||
0U,
|
||||
1U
|
||||
};
|
||||
|
||||
static const unsigned char test_input[2][375] =
|
||||
{
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
},
|
||||
{
|
||||
0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d,
|
||||
0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74,
|
||||
0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45,
|
||||
0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e,
|
||||
0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74,
|
||||
0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72,
|
||||
0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66,
|
||||
0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69,
|
||||
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61,
|
||||
0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72,
|
||||
0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66,
|
||||
0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46,
|
||||
0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
|
||||
0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20,
|
||||
0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61,
|
||||
0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73,
|
||||
0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74,
|
||||
0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69,
|
||||
0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
|
||||
0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
|
||||
0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49,
|
||||
0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69,
|
||||
0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20,
|
||||
0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72,
|
||||
0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49,
|
||||
0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74,
|
||||
0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20,
|
||||
0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
|
||||
0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75,
|
||||
0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20,
|
||||
0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
|
||||
0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45,
|
||||
0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69,
|
||||
0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20,
|
||||
0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20,
|
||||
0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20,
|
||||
0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63,
|
||||
0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63,
|
||||
0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61,
|
||||
0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e,
|
||||
0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f,
|
||||
0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c,
|
||||
0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61,
|
||||
0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65,
|
||||
0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f
|
||||
}
|
||||
};
|
||||
|
||||
static const unsigned char test_output[2][375] =
|
||||
{
|
||||
{
|
||||
0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
|
||||
0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
|
||||
0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
|
||||
0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
|
||||
0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
|
||||
0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
|
||||
0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
|
||||
0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86
|
||||
},
|
||||
{
|
||||
0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde,
|
||||
0x4f, 0x37, 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70,
|
||||
0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd,
|
||||
0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec,
|
||||
0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15,
|
||||
0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05,
|
||||
0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f,
|
||||
0x56, 0xe0, 0x31, 0xca, 0x5e, 0xb6, 0x25, 0x0d,
|
||||
0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa,
|
||||
0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e,
|
||||
0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7,
|
||||
0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50,
|
||||
0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05,
|
||||
0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, 0x41, 0x1c,
|
||||
0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05,
|
||||
0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a,
|
||||
0xd0, 0x0f, 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0,
|
||||
0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66,
|
||||
0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4,
|
||||
0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d,
|
||||
0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91,
|
||||
0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28,
|
||||
0xe6, 0x35, 0x55, 0x3b, 0xa7, 0x6c, 0x5c, 0x87,
|
||||
0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b,
|
||||
0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2,
|
||||
0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f,
|
||||
0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76,
|
||||
0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c,
|
||||
0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, 0xc9, 0x2b,
|
||||
0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84,
|
||||
0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd,
|
||||
0xa2, 0x36, 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b,
|
||||
0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe,
|
||||
0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0,
|
||||
0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80,
|
||||
0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f,
|
||||
0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3,
|
||||
0x6f, 0xf2, 0x16, 0xb9, 0xc1, 0xd3, 0x00, 0x62,
|
||||
0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91,
|
||||
0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6,
|
||||
0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64,
|
||||
0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85,
|
||||
0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41,
|
||||
0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, 0xd1, 0xab,
|
||||
0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba,
|
||||
0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd,
|
||||
0xc4, 0xfd, 0x80, 0x6c, 0x22, 0xf2, 0x21
|
||||
}
|
||||
};
|
||||
|
||||
static const size_t test_lengths[2] =
|
||||
{
|
||||
64U,
|
||||
375U
|
||||
};
|
||||
|
||||
#define ASSERT( cond, args ) \
|
||||
do \
|
||||
{ \
|
||||
if( ! ( cond ) ) \
|
||||
{ \
|
||||
if( verbose != 0 ) \
|
||||
mbedtls_printf args; \
|
||||
\
|
||||
return( -1 ); \
|
||||
} \
|
||||
} \
|
||||
while( 0 )
|
||||
|
||||
int mbedtls_chacha20_self_test( int verbose )
|
||||
{
|
||||
unsigned char output[381];
|
||||
unsigned i;
|
||||
int ret;
|
||||
|
||||
for( i = 0U; i < 2U; i++ )
|
||||
{
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( " ChaCha20 test %u ", i );
|
||||
|
||||
ret = mbedtls_chacha20_crypt( test_keys[i],
|
||||
test_nonces[i],
|
||||
test_counters[i],
|
||||
test_lengths[i],
|
||||
test_input[i],
|
||||
output );
|
||||
|
||||
ASSERT( 0 == ret, ( "error code: %i\n", ret ) );
|
||||
|
||||
ASSERT( 0 == memcmp( output, test_output[i], test_lengths[i] ),
|
||||
( "failed (output)\n" ) );
|
||||
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( "passed\n" );
|
||||
}
|
||||
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( "\n" );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
#endif /* MBEDTLS_SELF_TEST */
|
||||
|
||||
#endif /* !MBEDTLS_CHACHA20_C */
|
||||
547
library/chachapoly.c
Normal file
547
library/chachapoly.c
Normal file
@@ -0,0 +1,547 @@
|
||||
/**
|
||||
* \file chachapoly.c
|
||||
*
|
||||
* \brief ChaCha20-Poly1305 AEAD construction based on RFC 7539.
|
||||
*
|
||||
* Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is part of mbed TLS (https://tls.mbed.org)
|
||||
*/
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_CHACHAPOLY_C)
|
||||
|
||||
#include "mbedtls/chachapoly.h"
|
||||
#include "mbedtls/platform_util.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#if defined(MBEDTLS_SELF_TEST)
|
||||
#if defined(MBEDTLS_PLATFORM_C)
|
||||
#include "mbedtls/platform.h"
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#define mbedtls_printf printf
|
||||
#endif /* MBEDTLS_PLATFORM_C */
|
||||
#endif /* MBEDTLS_SELF_TEST */
|
||||
|
||||
#if !defined(MBEDTLS_CHACHAPOLY_ALT)
|
||||
|
||||
#define CHACHAPOLY_STATE_INIT ( 0 )
|
||||
#define CHACHAPOLY_STATE_AAD ( 1 )
|
||||
#define CHACHAPOLY_STATE_CIPHERTEXT ( 2 ) /* Encrypting or decrypting */
|
||||
#define CHACHAPOLY_STATE_FINISHED ( 3 )
|
||||
|
||||
/**
|
||||
* \brief Adds nul bytes to pad the AAD for Poly1305.
|
||||
*
|
||||
* \param ctx The ChaCha20-Poly1305 context.
|
||||
*/
|
||||
static int chachapoly_pad_aad( mbedtls_chachapoly_context *ctx )
|
||||
{
|
||||
uint32_t partial_block_len = (uint32_t) ( ctx->aad_len % 16U );
|
||||
unsigned char zeroes[15];
|
||||
|
||||
if( partial_block_len == 0U )
|
||||
return( 0 );
|
||||
|
||||
memset( zeroes, 0, sizeof( zeroes ) );
|
||||
|
||||
return( mbedtls_poly1305_update( &ctx->poly1305_ctx,
|
||||
zeroes,
|
||||
16U - partial_block_len ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Adds nul bytes to pad the ciphertext for Poly1305.
|
||||
*
|
||||
* \param ctx The ChaCha20-Poly1305 context.
|
||||
*/
|
||||
static int chachapoly_pad_ciphertext( mbedtls_chachapoly_context *ctx )
|
||||
{
|
||||
uint32_t partial_block_len = (uint32_t) ( ctx->ciphertext_len % 16U );
|
||||
unsigned char zeroes[15];
|
||||
|
||||
if( partial_block_len == 0U )
|
||||
return( 0 );
|
||||
|
||||
memset( zeroes, 0, sizeof( zeroes ) );
|
||||
return( mbedtls_poly1305_update( &ctx->poly1305_ctx,
|
||||
zeroes,
|
||||
16U - partial_block_len ) );
|
||||
}
|
||||
|
||||
void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx )
|
||||
{
|
||||
if( ctx != NULL )
|
||||
{
|
||||
mbedtls_chacha20_init( &ctx->chacha20_ctx );
|
||||
mbedtls_poly1305_init( &ctx->poly1305_ctx );
|
||||
ctx->aad_len = 0U;
|
||||
ctx->ciphertext_len = 0U;
|
||||
ctx->state = CHACHAPOLY_STATE_INIT;
|
||||
ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
|
||||
}
|
||||
}
|
||||
|
||||
void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx )
|
||||
{
|
||||
if( ctx != NULL )
|
||||
{
|
||||
mbedtls_chacha20_free( &ctx->chacha20_ctx );
|
||||
mbedtls_poly1305_free( &ctx->poly1305_ctx );
|
||||
ctx->aad_len = 0U;
|
||||
ctx->ciphertext_len = 0U;
|
||||
ctx->state = CHACHAPOLY_STATE_INIT;
|
||||
ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
|
||||
}
|
||||
}
|
||||
|
||||
int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx,
|
||||
const unsigned char key[32] )
|
||||
{
|
||||
int ret;
|
||||
|
||||
if( ( ctx == NULL ) || ( key == NULL ) )
|
||||
{
|
||||
return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
|
||||
}
|
||||
|
||||
ret = mbedtls_chacha20_setkey( &ctx->chacha20_ctx, key );
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx,
|
||||
const unsigned char nonce[12],
|
||||
mbedtls_chachapoly_mode_t mode )
|
||||
{
|
||||
int ret;
|
||||
unsigned char poly1305_key[64];
|
||||
|
||||
if( ( ctx == NULL ) || ( nonce == NULL ) )
|
||||
{
|
||||
return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
|
||||
}
|
||||
|
||||
/* Set counter = 0, will be update to 1 when generating Poly1305 key */
|
||||
ret = mbedtls_chacha20_starts( &ctx->chacha20_ctx, nonce, 0U );
|
||||
if( ret != 0 )
|
||||
goto cleanup;
|
||||
|
||||
/* Generate the Poly1305 key by getting the ChaCha20 keystream output with
|
||||
* counter = 0. This is the same as encrypting a buffer of zeroes.
|
||||
* Only the first 256-bits (32 bytes) of the key is used for Poly1305.
|
||||
* The other 256 bits are discarded.
|
||||
*/
|
||||
memset( poly1305_key, 0, sizeof( poly1305_key ) );
|
||||
ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, sizeof( poly1305_key ),
|
||||
poly1305_key, poly1305_key );
|
||||
if( ret != 0 )
|
||||
goto cleanup;
|
||||
|
||||
ret = mbedtls_poly1305_starts( &ctx->poly1305_ctx, poly1305_key );
|
||||
|
||||
if( ret == 0 )
|
||||
{
|
||||
ctx->aad_len = 0U;
|
||||
ctx->ciphertext_len = 0U;
|
||||
ctx->state = CHACHAPOLY_STATE_AAD;
|
||||
ctx->mode = mode;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
mbedtls_platform_zeroize( poly1305_key, 64U );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx,
|
||||
const unsigned char *aad,
|
||||
size_t aad_len )
|
||||
{
|
||||
if( ctx == NULL )
|
||||
{
|
||||
return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
|
||||
}
|
||||
else if( ( aad_len > 0U ) && ( aad == NULL ) )
|
||||
{
|
||||
/* aad pointer is allowed to be NULL if aad_len == 0 */
|
||||
return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
|
||||
}
|
||||
else if( ctx->state != CHACHAPOLY_STATE_AAD )
|
||||
{
|
||||
return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
|
||||
}
|
||||
|
||||
ctx->aad_len += aad_len;
|
||||
|
||||
return( mbedtls_poly1305_update( &ctx->poly1305_ctx, aad, aad_len ) );
|
||||
}
|
||||
|
||||
int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx,
|
||||
size_t len,
|
||||
const unsigned char *input,
|
||||
unsigned char *output )
|
||||
{
|
||||
int ret;
|
||||
|
||||
if( ctx == NULL )
|
||||
{
|
||||
return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
|
||||
}
|
||||
else if( ( len > 0U ) && ( ( input == NULL ) || ( output == NULL ) ) )
|
||||
{
|
||||
/* input and output pointers are allowed to be NULL if len == 0 */
|
||||
return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
|
||||
}
|
||||
else if( ( ctx->state != CHACHAPOLY_STATE_AAD ) &&
|
||||
( ctx->state != CHACHAPOLY_STATE_CIPHERTEXT ) )
|
||||
{
|
||||
return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
|
||||
}
|
||||
|
||||
if( ctx->state == CHACHAPOLY_STATE_AAD )
|
||||
{
|
||||
ctx->state = CHACHAPOLY_STATE_CIPHERTEXT;
|
||||
|
||||
ret = chachapoly_pad_aad( ctx );
|
||||
if( ret != 0 )
|
||||
return( ret );
|
||||
}
|
||||
|
||||
ctx->ciphertext_len += len;
|
||||
|
||||
if( ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT )
|
||||
{
|
||||
ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output );
|
||||
if( ret != 0 )
|
||||
return( ret );
|
||||
|
||||
ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, output, len );
|
||||
if( ret != 0 )
|
||||
return( ret );
|
||||
}
|
||||
else /* DECRYPT */
|
||||
{
|
||||
ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, input, len );
|
||||
if( ret != 0 )
|
||||
return( ret );
|
||||
|
||||
ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output );
|
||||
if( ret != 0 )
|
||||
return( ret );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx,
|
||||
unsigned char mac[16] )
|
||||
{
|
||||
int ret;
|
||||
unsigned char len_block[16];
|
||||
|
||||
if( ( ctx == NULL ) || ( mac == NULL ) )
|
||||
{
|
||||
return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
|
||||
}
|
||||
else if( ctx->state == CHACHAPOLY_STATE_INIT )
|
||||
{
|
||||
return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
|
||||
}
|
||||
|
||||
if( ctx->state == CHACHAPOLY_STATE_AAD )
|
||||
{
|
||||
ret = chachapoly_pad_aad( ctx );
|
||||
if( ret != 0 )
|
||||
return( ret );
|
||||
}
|
||||
else if( ctx->state == CHACHAPOLY_STATE_CIPHERTEXT )
|
||||
{
|
||||
ret = chachapoly_pad_ciphertext( ctx );
|
||||
if( ret != 0 )
|
||||
return( ret );
|
||||
}
|
||||
|
||||
ctx->state = CHACHAPOLY_STATE_FINISHED;
|
||||
|
||||
/* The lengths of the AAD and ciphertext are processed by
|
||||
* Poly1305 as the final 128-bit block, encoded as little-endian integers.
|
||||
*/
|
||||
len_block[ 0] = (unsigned char)( ctx->aad_len );
|
||||
len_block[ 1] = (unsigned char)( ctx->aad_len >> 8 );
|
||||
len_block[ 2] = (unsigned char)( ctx->aad_len >> 16 );
|
||||
len_block[ 3] = (unsigned char)( ctx->aad_len >> 24 );
|
||||
len_block[ 4] = (unsigned char)( ctx->aad_len >> 32 );
|
||||
len_block[ 5] = (unsigned char)( ctx->aad_len >> 40 );
|
||||
len_block[ 6] = (unsigned char)( ctx->aad_len >> 48 );
|
||||
len_block[ 7] = (unsigned char)( ctx->aad_len >> 56 );
|
||||
len_block[ 8] = (unsigned char)( ctx->ciphertext_len );
|
||||
len_block[ 9] = (unsigned char)( ctx->ciphertext_len >> 8 );
|
||||
len_block[10] = (unsigned char)( ctx->ciphertext_len >> 16 );
|
||||
len_block[11] = (unsigned char)( ctx->ciphertext_len >> 24 );
|
||||
len_block[12] = (unsigned char)( ctx->ciphertext_len >> 32 );
|
||||
len_block[13] = (unsigned char)( ctx->ciphertext_len >> 40 );
|
||||
len_block[14] = (unsigned char)( ctx->ciphertext_len >> 48 );
|
||||
len_block[15] = (unsigned char)( ctx->ciphertext_len >> 56 );
|
||||
|
||||
ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, len_block, 16U );
|
||||
if( ret != 0 )
|
||||
return( ret );
|
||||
|
||||
ret = mbedtls_poly1305_finish( &ctx->poly1305_ctx, mac );
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
static int chachapoly_crypt_and_tag( mbedtls_chachapoly_context *ctx,
|
||||
mbedtls_chachapoly_mode_t mode,
|
||||
size_t length,
|
||||
const unsigned char nonce[12],
|
||||
const unsigned char *aad,
|
||||
size_t aad_len,
|
||||
const unsigned char *input,
|
||||
unsigned char *output,
|
||||
unsigned char tag[16] )
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = mbedtls_chachapoly_starts( ctx, nonce, mode );
|
||||
if( ret != 0 )
|
||||
goto cleanup;
|
||||
|
||||
ret = mbedtls_chachapoly_update_aad( ctx, aad, aad_len );
|
||||
if( ret != 0 )
|
||||
goto cleanup;
|
||||
|
||||
ret = mbedtls_chachapoly_update( ctx, length, input, output );
|
||||
if( ret != 0 )
|
||||
goto cleanup;
|
||||
|
||||
ret = mbedtls_chachapoly_finish( ctx, tag );
|
||||
|
||||
cleanup:
|
||||
return( ret );
|
||||
}
|
||||
|
||||
int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx,
|
||||
size_t length,
|
||||
const unsigned char nonce[12],
|
||||
const unsigned char *aad,
|
||||
size_t aad_len,
|
||||
const unsigned char *input,
|
||||
unsigned char *output,
|
||||
unsigned char tag[16] )
|
||||
{
|
||||
return( chachapoly_crypt_and_tag( ctx, MBEDTLS_CHACHAPOLY_ENCRYPT,
|
||||
length, nonce, aad, aad_len,
|
||||
input, output, tag ) );
|
||||
}
|
||||
|
||||
int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx,
|
||||
size_t length,
|
||||
const unsigned char nonce[12],
|
||||
const unsigned char *aad,
|
||||
size_t aad_len,
|
||||
const unsigned char tag[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output )
|
||||
{
|
||||
int ret;
|
||||
unsigned char check_tag[16];
|
||||
size_t i;
|
||||
int diff;
|
||||
|
||||
if( tag == NULL )
|
||||
return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
|
||||
|
||||
if( ( ret = chachapoly_crypt_and_tag( ctx,
|
||||
MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce,
|
||||
aad, aad_len, input, output, check_tag ) ) != 0 )
|
||||
{
|
||||
return( ret );
|
||||
}
|
||||
|
||||
/* Check tag in "constant-time" */
|
||||
for( diff = 0, i = 0; i < sizeof( check_tag ); i++ )
|
||||
diff |= tag[i] ^ check_tag[i];
|
||||
|
||||
if( diff != 0 )
|
||||
{
|
||||
mbedtls_platform_zeroize( output, length );
|
||||
return( MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
#endif /* MBEDTLS_CHACHAPOLY_ALT */
|
||||
|
||||
#if defined(MBEDTLS_SELF_TEST)
|
||||
|
||||
static const unsigned char test_key[1][32] =
|
||||
{
|
||||
{
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
|
||||
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
|
||||
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f
|
||||
}
|
||||
};
|
||||
|
||||
static const unsigned char test_nonce[1][12] =
|
||||
{
|
||||
{
|
||||
0x07, 0x00, 0x00, 0x00, /* 32-bit common part */
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 /* 64-bit IV */
|
||||
}
|
||||
};
|
||||
|
||||
static const unsigned char test_aad[1][12] =
|
||||
{
|
||||
{
|
||||
0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3,
|
||||
0xc4, 0xc5, 0xc6, 0xc7
|
||||
}
|
||||
};
|
||||
|
||||
static const size_t test_aad_len[1] =
|
||||
{
|
||||
12U
|
||||
};
|
||||
|
||||
static const unsigned char test_input[1][114] =
|
||||
{
|
||||
{
|
||||
0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61,
|
||||
0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c,
|
||||
0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
|
||||
0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73,
|
||||
0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39,
|
||||
0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63,
|
||||
0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66,
|
||||
0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f,
|
||||
0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20,
|
||||
0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20,
|
||||
0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75,
|
||||
0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73,
|
||||
0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f,
|
||||
0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69,
|
||||
0x74, 0x2e
|
||||
}
|
||||
};
|
||||
|
||||
static const unsigned char test_output[1][114] =
|
||||
{
|
||||
{
|
||||
0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb,
|
||||
0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2,
|
||||
0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe,
|
||||
0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6,
|
||||
0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12,
|
||||
0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b,
|
||||
0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29,
|
||||
0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36,
|
||||
0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c,
|
||||
0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58,
|
||||
0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94,
|
||||
0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc,
|
||||
0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d,
|
||||
0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b,
|
||||
0x61, 0x16
|
||||
}
|
||||
};
|
||||
|
||||
static const size_t test_input_len[1] =
|
||||
{
|
||||
114U
|
||||
};
|
||||
|
||||
static const unsigned char test_mac[1][16] =
|
||||
{
|
||||
{
|
||||
0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a,
|
||||
0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91
|
||||
}
|
||||
};
|
||||
|
||||
#define ASSERT( cond, args ) \
|
||||
do \
|
||||
{ \
|
||||
if( ! ( cond ) ) \
|
||||
{ \
|
||||
if( verbose != 0 ) \
|
||||
mbedtls_printf args; \
|
||||
\
|
||||
return( -1 ); \
|
||||
} \
|
||||
} \
|
||||
while( 0 )
|
||||
|
||||
int mbedtls_chachapoly_self_test( int verbose )
|
||||
{
|
||||
mbedtls_chachapoly_context ctx;
|
||||
unsigned i;
|
||||
int ret;
|
||||
unsigned char output[200];
|
||||
unsigned char mac[16];
|
||||
|
||||
for( i = 0U; i < 1U; i++ )
|
||||
{
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( " ChaCha20-Poly1305 test %u ", i );
|
||||
|
||||
mbedtls_chachapoly_init( &ctx );
|
||||
|
||||
ret = mbedtls_chachapoly_setkey( &ctx, test_key[i] );
|
||||
ASSERT( 0 == ret, ( "setkey() error code: %i\n", ret ) );
|
||||
|
||||
ret = mbedtls_chachapoly_encrypt_and_tag( &ctx,
|
||||
test_input_len[i],
|
||||
test_nonce[i],
|
||||
test_aad[i],
|
||||
test_aad_len[i],
|
||||
test_input[i],
|
||||
output,
|
||||
mac );
|
||||
|
||||
ASSERT( 0 == ret, ( "crypt_and_tag() error code: %i\n", ret ) );
|
||||
|
||||
ASSERT( 0 == memcmp( output, test_output[i], test_input_len[i] ),
|
||||
( "failure (wrong output)\n" ) );
|
||||
|
||||
ASSERT( 0 == memcmp( mac, test_mac[i], 16U ),
|
||||
( "failure (wrong MAC)\n" ) );
|
||||
|
||||
mbedtls_chachapoly_free( &ctx );
|
||||
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( "passed\n" );
|
||||
}
|
||||
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( "\n" );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
#endif /* MBEDTLS_SELF_TEST */
|
||||
|
||||
#endif /* MBEDTLS_CHACHAPOLY_C */
|
||||
229
library/cipher.c
229
library/cipher.c
@@ -38,6 +38,10 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(MBEDTLS_CHACHAPOLY_C)
|
||||
#include "mbedtls/chachapoly.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_GCM_C)
|
||||
#include "mbedtls/gcm.h"
|
||||
#endif
|
||||
@@ -46,6 +50,10 @@
|
||||
#include "mbedtls/ccm.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_CHACHA20_C)
|
||||
#include "mbedtls/chacha20.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_CMAC_C)
|
||||
#include "mbedtls/cmac.h"
|
||||
#endif
|
||||
@@ -57,9 +65,25 @@
|
||||
#define mbedtls_free free
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER)
|
||||
#define MBEDTLS_CIPHER_MODE_STREAM
|
||||
#endif
|
||||
#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
|
||||
/* Compare the contents of two buffers in constant time.
|
||||
* Returns 0 if the contents are bitwise identical, otherwise returns
|
||||
* a non-zero value.
|
||||
* This is currently only used by GCM and ChaCha20+Poly1305.
|
||||
*/
|
||||
static int mbedtls_constant_time_memcmp( const void *v1, const void *v2, size_t len )
|
||||
{
|
||||
const unsigned char *p1 = (const unsigned char*) v1;
|
||||
const unsigned char *p2 = (const unsigned char*) v2;
|
||||
size_t i;
|
||||
unsigned char diff;
|
||||
|
||||
for( diff = 0, i = 0; i < len; i++ )
|
||||
diff |= p1[i] ^ p2[i];
|
||||
|
||||
return (int)diff;
|
||||
}
|
||||
#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */
|
||||
|
||||
static int supported_init = 0;
|
||||
|
||||
@@ -191,10 +215,11 @@ int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *k
|
||||
ctx->operation = operation;
|
||||
|
||||
/*
|
||||
* For CFB and CTR mode always use the encryption key schedule
|
||||
* For OFB, CFB and CTR mode always use the encryption key schedule
|
||||
*/
|
||||
if( MBEDTLS_ENCRYPT == operation ||
|
||||
MBEDTLS_MODE_CFB == ctx->cipher_info->mode ||
|
||||
MBEDTLS_MODE_OFB == ctx->cipher_info->mode ||
|
||||
MBEDTLS_MODE_CTR == ctx->cipher_info->mode )
|
||||
{
|
||||
return ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key,
|
||||
@@ -212,9 +237,13 @@ int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx,
|
||||
const unsigned char *iv, size_t iv_len )
|
||||
{
|
||||
size_t actual_iv_size;
|
||||
|
||||
if( NULL == ctx || NULL == ctx->cipher_info || NULL == iv )
|
||||
if( NULL == ctx || NULL == ctx->cipher_info )
|
||||
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
|
||||
else if( NULL == iv && iv_len != 0 )
|
||||
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
|
||||
|
||||
if( NULL == iv && iv_len == 0 )
|
||||
ctx->iv_size = 0;
|
||||
|
||||
/* avoid buffer overflow in ctx->iv */
|
||||
if( iv_len > MBEDTLS_MAX_IV_LENGTH )
|
||||
@@ -231,8 +260,23 @@ int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx,
|
||||
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
|
||||
}
|
||||
|
||||
memcpy( ctx->iv, iv, actual_iv_size );
|
||||
ctx->iv_size = actual_iv_size;
|
||||
#if defined(MBEDTLS_CHACHA20_C)
|
||||
if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20 )
|
||||
{
|
||||
if ( 0 != mbedtls_chacha20_starts( (mbedtls_chacha20_context*)ctx->cipher_ctx,
|
||||
iv,
|
||||
0U ) ) /* Initial counter value */
|
||||
{
|
||||
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( actual_iv_size != 0 )
|
||||
{
|
||||
memcpy( ctx->iv, iv, actual_iv_size );
|
||||
ctx->iv_size = actual_iv_size;
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
@@ -247,22 +291,45 @@ int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx )
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_GCM_C)
|
||||
#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
|
||||
int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx,
|
||||
const unsigned char *ad, size_t ad_len )
|
||||
{
|
||||
if( NULL == ctx || NULL == ctx->cipher_info )
|
||||
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
|
||||
|
||||
#if defined(MBEDTLS_GCM_C)
|
||||
if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
|
||||
{
|
||||
return mbedtls_gcm_starts( (mbedtls_gcm_context *) ctx->cipher_ctx, ctx->operation,
|
||||
ctx->iv, ctx->iv_size, ad, ad_len );
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_CHACHAPOLY_C)
|
||||
if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
|
||||
{
|
||||
int result;
|
||||
mbedtls_chachapoly_mode_t mode;
|
||||
|
||||
mode = ( ctx->operation == MBEDTLS_ENCRYPT )
|
||||
? MBEDTLS_CHACHAPOLY_ENCRYPT
|
||||
: MBEDTLS_CHACHAPOLY_DECRYPT;
|
||||
|
||||
result = mbedtls_chachapoly_starts( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
|
||||
ctx->iv,
|
||||
mode );
|
||||
if ( result != 0 )
|
||||
return( result );
|
||||
|
||||
return mbedtls_chachapoly_update_aad( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
|
||||
ad, ad_len );
|
||||
}
|
||||
#endif
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
#endif /* MBEDTLS_GCM_C */
|
||||
#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */
|
||||
|
||||
int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input,
|
||||
size_t ilen, unsigned char *output, size_t *olen )
|
||||
@@ -303,6 +370,15 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_CHACHAPOLY_C)
|
||||
if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 )
|
||||
{
|
||||
*olen = ilen;
|
||||
return mbedtls_chachapoly_update( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
|
||||
ilen, input, output );
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( 0 == block_size )
|
||||
{
|
||||
return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT;
|
||||
@@ -424,6 +500,21 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i
|
||||
}
|
||||
#endif /* MBEDTLS_CIPHER_MODE_CFB */
|
||||
|
||||
#if defined(MBEDTLS_CIPHER_MODE_OFB)
|
||||
if( ctx->cipher_info->mode == MBEDTLS_MODE_OFB )
|
||||
{
|
||||
if( 0 != ( ret = ctx->cipher_info->base->ofb_func( ctx->cipher_ctx,
|
||||
ilen, &ctx->unprocessed_len, ctx->iv, input, output ) ) )
|
||||
{
|
||||
return( ret );
|
||||
}
|
||||
|
||||
*olen = ilen;
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
#endif /* MBEDTLS_CIPHER_MODE_OFB */
|
||||
|
||||
#if defined(MBEDTLS_CIPHER_MODE_CTR)
|
||||
if( ctx->cipher_info->mode == MBEDTLS_MODE_CTR )
|
||||
{
|
||||
@@ -440,6 +531,27 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i
|
||||
}
|
||||
#endif /* MBEDTLS_CIPHER_MODE_CTR */
|
||||
|
||||
#if defined(MBEDTLS_CIPHER_MODE_XTS)
|
||||
if( ctx->cipher_info->mode == MBEDTLS_MODE_XTS )
|
||||
{
|
||||
if( ctx->unprocessed_len > 0 ) {
|
||||
/* We can only process an entire data unit at a time. */
|
||||
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
|
||||
}
|
||||
|
||||
ret = ctx->cipher_info->base->xts_func( ctx->cipher_ctx,
|
||||
ctx->operation, ilen, ctx->iv, input, output );
|
||||
if( ret != 0 )
|
||||
{
|
||||
return( ret );
|
||||
}
|
||||
|
||||
*olen = ilen;
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
#endif /* MBEDTLS_CIPHER_MODE_XTS */
|
||||
|
||||
#if defined(MBEDTLS_CIPHER_MODE_STREAM)
|
||||
if( ctx->cipher_info->mode == MBEDTLS_MODE_STREAM )
|
||||
{
|
||||
@@ -639,13 +751,21 @@ int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx,
|
||||
*olen = 0;
|
||||
|
||||
if( MBEDTLS_MODE_CFB == ctx->cipher_info->mode ||
|
||||
MBEDTLS_MODE_OFB == ctx->cipher_info->mode ||
|
||||
MBEDTLS_MODE_CTR == ctx->cipher_info->mode ||
|
||||
MBEDTLS_MODE_GCM == ctx->cipher_info->mode ||
|
||||
MBEDTLS_MODE_XTS == ctx->cipher_info->mode ||
|
||||
MBEDTLS_MODE_STREAM == ctx->cipher_info->mode )
|
||||
{
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
if ( ( MBEDTLS_CIPHER_CHACHA20 == ctx->cipher_info->type ) ||
|
||||
( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) )
|
||||
{
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
if( MBEDTLS_MODE_ECB == ctx->cipher_info->mode )
|
||||
{
|
||||
if( ctx->unprocessed_len != 0 )
|
||||
@@ -757,7 +877,7 @@ int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_ciph
|
||||
}
|
||||
#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
|
||||
|
||||
#if defined(MBEDTLS_GCM_C)
|
||||
#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
|
||||
int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx,
|
||||
unsigned char *tag, size_t tag_len )
|
||||
{
|
||||
@@ -767,8 +887,22 @@ int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx,
|
||||
if( MBEDTLS_ENCRYPT != ctx->operation )
|
||||
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
|
||||
|
||||
#if defined(MBEDTLS_GCM_C)
|
||||
if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
|
||||
return mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, tag, tag_len );
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_CHACHAPOLY_C)
|
||||
if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
|
||||
{
|
||||
/* Don't allow truncated MAC for Poly1305 */
|
||||
if ( tag_len != 16U )
|
||||
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
|
||||
|
||||
return mbedtls_chachapoly_finish( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
|
||||
tag );
|
||||
}
|
||||
#endif
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
@@ -776,6 +910,7 @@ int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx,
|
||||
int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx,
|
||||
const unsigned char *tag, size_t tag_len )
|
||||
{
|
||||
unsigned char check_tag[16];
|
||||
int ret;
|
||||
|
||||
if( NULL == ctx || NULL == ctx->cipher_info ||
|
||||
@@ -784,12 +919,9 @@ int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx,
|
||||
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_GCM_C)
|
||||
if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
|
||||
{
|
||||
unsigned char check_tag[16];
|
||||
size_t i;
|
||||
int diff;
|
||||
|
||||
if( tag_len > sizeof( check_tag ) )
|
||||
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
|
||||
|
||||
@@ -800,18 +932,38 @@ int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx,
|
||||
}
|
||||
|
||||
/* Check the tag in "constant-time" */
|
||||
for( diff = 0, i = 0; i < tag_len; i++ )
|
||||
diff |= tag[i] ^ check_tag[i];
|
||||
|
||||
if( diff != 0 )
|
||||
if( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 )
|
||||
return( MBEDTLS_ERR_CIPHER_AUTH_FAILED );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
#endif /* MBEDTLS_GCM_C */
|
||||
|
||||
#if defined(MBEDTLS_CHACHAPOLY_C)
|
||||
if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
|
||||
{
|
||||
/* Don't allow truncated MAC for Poly1305 */
|
||||
if ( tag_len != sizeof( check_tag ) )
|
||||
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
|
||||
|
||||
ret = mbedtls_chachapoly_finish( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
|
||||
check_tag );
|
||||
if ( ret != 0 )
|
||||
{
|
||||
return( ret );
|
||||
}
|
||||
|
||||
/* Check the tag in "constant-time" */
|
||||
if( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 )
|
||||
return( MBEDTLS_ERR_CIPHER_AUTH_FAILED );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
#endif /* MBEDTLS_CHACHAPOLY_C */
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
#endif /* MBEDTLS_GCM_C */
|
||||
#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */
|
||||
|
||||
/*
|
||||
* Packet-oriented wrapper for non-AEAD modes
|
||||
@@ -870,6 +1022,21 @@ int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx,
|
||||
tag, tag_len ) );
|
||||
}
|
||||
#endif /* MBEDTLS_CCM_C */
|
||||
#if defined(MBEDTLS_CHACHAPOLY_C)
|
||||
if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
|
||||
{
|
||||
/* ChachaPoly has fixed length nonce and MAC (tag) */
|
||||
if ( ( iv_len != ctx->cipher_info->iv_size ) ||
|
||||
( tag_len != 16U ) )
|
||||
{
|
||||
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
|
||||
}
|
||||
|
||||
*olen = ilen;
|
||||
return( mbedtls_chachapoly_encrypt_and_tag( ctx->cipher_ctx,
|
||||
ilen, iv, ad, ad_len, input, output, tag ) );
|
||||
}
|
||||
#endif /* MBEDTLS_CHACHAPOLY_C */
|
||||
|
||||
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
|
||||
}
|
||||
@@ -916,6 +1083,28 @@ int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx,
|
||||
return( ret );
|
||||
}
|
||||
#endif /* MBEDTLS_CCM_C */
|
||||
#if defined(MBEDTLS_CHACHAPOLY_C)
|
||||
if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* ChachaPoly has fixed length nonce and MAC (tag) */
|
||||
if ( ( iv_len != ctx->cipher_info->iv_size ) ||
|
||||
( tag_len != 16U ) )
|
||||
{
|
||||
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
|
||||
}
|
||||
|
||||
*olen = ilen;
|
||||
ret = mbedtls_chachapoly_auth_decrypt( ctx->cipher_ctx, ilen,
|
||||
iv, ad, ad_len, tag, input, output );
|
||||
|
||||
if( ret == MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED )
|
||||
ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
|
||||
|
||||
return( ret );
|
||||
}
|
||||
#endif /* MBEDTLS_CHACHAPOLY_C */
|
||||
|
||||
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -828,6 +828,7 @@ static int cmac_test_subkeys( int verbose,
|
||||
mbedtls_cipher_free( &ctx );
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
goto exit;
|
||||
|
||||
cleanup:
|
||||
@@ -883,6 +884,7 @@ static int cmac_test_wth_cipher( int verbose,
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( "passed\n" );
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
exit:
|
||||
return( ret );
|
||||
|
||||
@@ -66,6 +66,18 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
|
||||
* Non-public function wrapped by mbedtls_ctr_drbg_seed(). Necessary to allow
|
||||
* NIST tests to succeed (which require known length fixed entropy)
|
||||
*/
|
||||
/* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2)
|
||||
* mbedtls_ctr_drbg_seed_entropy_len(ctx, f_entropy, p_entropy,
|
||||
* custom, len, entropy_len)
|
||||
* implements
|
||||
* CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
|
||||
* security_strength) -> initial_working_state
|
||||
* with inputs
|
||||
* custom[:len] = nonce || personalization_string
|
||||
* where entropy_input comes from f_entropy for entropy_len bytes
|
||||
* and with outputs
|
||||
* ctx = initial_working_state
|
||||
*/
|
||||
int mbedtls_ctr_drbg_seed_entropy_len(
|
||||
mbedtls_ctr_drbg_context *ctx,
|
||||
int (*f_entropy)(void *, unsigned char *, size_t),
|
||||
@@ -256,6 +268,14 @@ exit:
|
||||
return( ret );
|
||||
}
|
||||
|
||||
/* CTR_DRBG_Update (SP 800-90A §10.2.1.2)
|
||||
* ctr_drbg_update_internal(ctx, provided_data)
|
||||
* implements
|
||||
* CTR_DRBG_Update(provided_data, Key, V)
|
||||
* with inputs and outputs
|
||||
* ctx->aes_ctx = Key
|
||||
* ctx->counter = V
|
||||
*/
|
||||
static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
|
||||
const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
|
||||
{
|
||||
@@ -301,6 +321,18 @@ static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2)
|
||||
* mbedtls_ctr_drbg_update(ctx, additional, add_len)
|
||||
* implements
|
||||
* CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
|
||||
* security_strength) -> initial_working_state
|
||||
* with inputs
|
||||
* ctx->counter = all-bits-0
|
||||
* ctx->aes_ctx = context from all-bits-0 key
|
||||
* additional[:add_len] = entropy_input || nonce || personalization_string
|
||||
* and with outputs
|
||||
* ctx = initial_working_state
|
||||
*/
|
||||
void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
|
||||
const unsigned char *additional, size_t add_len )
|
||||
{
|
||||
@@ -318,6 +350,18 @@ void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
|
||||
}
|
||||
}
|
||||
|
||||
/* CTR_DRBG_Reseed with derivation function (SP 800-90A §10.2.1.4.2)
|
||||
* mbedtls_ctr_drbg_reseed(ctx, additional, len)
|
||||
* implements
|
||||
* CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
|
||||
* -> new_working_state
|
||||
* with inputs
|
||||
* ctx contains working_state
|
||||
* additional[:len] = additional_input
|
||||
* and entropy_input comes from calling ctx->f_entropy
|
||||
* and with output
|
||||
* ctx contains new_working_state
|
||||
*/
|
||||
int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
|
||||
const unsigned char *additional, size_t len )
|
||||
{
|
||||
@@ -371,6 +415,25 @@ int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/* CTR_DRBG_Generate with derivation function (SP 800-90A §10.2.1.5.2)
|
||||
* mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
|
||||
* implements
|
||||
* CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
|
||||
* -> working_state_after_reseed
|
||||
* if required, then
|
||||
* CTR_DRBG_Generate(working_state_after_reseed,
|
||||
* requested_number_of_bits, additional_input)
|
||||
* -> status, returned_bits, new_working_state
|
||||
* with inputs
|
||||
* ctx contains working_state
|
||||
* requested_number_of_bits = 8 * output_len
|
||||
* additional[:add_len] = additional_input
|
||||
* and entropy_input comes from calling ctx->f_entropy
|
||||
* and with outputs
|
||||
* status = SUCCESS (this function does the reseed internally)
|
||||
* returned_bits = output[:output_len]
|
||||
* ctx contains new_working_state
|
||||
*/
|
||||
int mbedtls_ctr_drbg_random_with_add( void *p_rng,
|
||||
unsigned char *output, size_t output_len,
|
||||
const unsigned char *additional, size_t add_len )
|
||||
|
||||
125
library/ecdh.c
125
library/ecdh.c
@@ -40,13 +40,41 @@
|
||||
|
||||
#if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT)
|
||||
/*
|
||||
* Generate public key: simple wrapper around mbedtls_ecp_gen_keypair
|
||||
* Generate public key (restartable version)
|
||||
*
|
||||
* Note: this internal function relies on its caller preserving the value of
|
||||
* the output parameter 'd' across continuation calls. This would not be
|
||||
* acceptable for a public function but is OK here as we control call sites.
|
||||
*/
|
||||
static int ecdh_gen_public_restartable( mbedtls_ecp_group *grp,
|
||||
mbedtls_mpi *d, mbedtls_ecp_point *Q,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng,
|
||||
mbedtls_ecp_restart_ctx *rs_ctx )
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* If multiplication is in progress, we already generated a privkey */
|
||||
#if defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
if( rs_ctx == NULL || rs_ctx->rsm == NULL )
|
||||
#endif
|
||||
MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) );
|
||||
|
||||
MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, Q, d, &grp->G,
|
||||
f_rng, p_rng, rs_ctx ) );
|
||||
|
||||
cleanup:
|
||||
return( ret );
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate public key
|
||||
*/
|
||||
int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng )
|
||||
{
|
||||
return mbedtls_ecp_gen_keypair( grp, d, Q, f_rng, p_rng );
|
||||
return( ecdh_gen_public_restartable( grp, d, Q, f_rng, p_rng, NULL ) );
|
||||
}
|
||||
#endif /* MBEDTLS_ECDH_GEN_PUBLIC_ALT */
|
||||
|
||||
@@ -54,22 +82,20 @@ int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp
|
||||
/*
|
||||
* Compute shared secret (SEC1 3.3.1)
|
||||
*/
|
||||
int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z,
|
||||
static int ecdh_compute_shared_restartable( mbedtls_ecp_group *grp,
|
||||
mbedtls_mpi *z,
|
||||
const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng )
|
||||
void *p_rng,
|
||||
mbedtls_ecp_restart_ctx *rs_ctx )
|
||||
{
|
||||
int ret;
|
||||
mbedtls_ecp_point P;
|
||||
|
||||
mbedtls_ecp_point_init( &P );
|
||||
|
||||
/*
|
||||
* Make sure Q is a valid pubkey before using it
|
||||
*/
|
||||
MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, Q ) );
|
||||
|
||||
MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, &P, d, Q, f_rng, p_rng ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &P, d, Q,
|
||||
f_rng, p_rng, rs_ctx ) );
|
||||
|
||||
if( mbedtls_ecp_is_zero( &P ) )
|
||||
{
|
||||
@@ -86,12 +112,37 @@ cleanup:
|
||||
}
|
||||
#endif /* MBEDTLS_ECDH_COMPUTE_SHARED_ALT */
|
||||
|
||||
/*
|
||||
* Compute shared secret (SEC1 3.3.1)
|
||||
*/
|
||||
int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z,
|
||||
const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng )
|
||||
{
|
||||
return( ecdh_compute_shared_restartable( grp, z, Q, d,
|
||||
f_rng, p_rng, NULL ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize context
|
||||
*/
|
||||
void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx )
|
||||
{
|
||||
memset( ctx, 0, sizeof( mbedtls_ecdh_context ) );
|
||||
mbedtls_ecp_group_init( &ctx->grp );
|
||||
mbedtls_mpi_init( &ctx->d );
|
||||
mbedtls_ecp_point_init( &ctx->Q );
|
||||
mbedtls_ecp_point_init( &ctx->Qp );
|
||||
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)
|
||||
ctx->restart_enabled = 0;
|
||||
mbedtls_ecp_restart_init( &ctx->rs );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -103,15 +154,29 @@ void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx )
|
||||
return;
|
||||
|
||||
mbedtls_ecp_group_free( &ctx->grp );
|
||||
mbedtls_mpi_free( &ctx->d );
|
||||
mbedtls_ecp_point_free( &ctx->Q );
|
||||
mbedtls_ecp_point_free( &ctx->Qp );
|
||||
mbedtls_mpi_free( &ctx->z );
|
||||
mbedtls_ecp_point_free( &ctx->Vi );
|
||||
mbedtls_ecp_point_free( &ctx->Vf );
|
||||
mbedtls_mpi_free( &ctx->d );
|
||||
mbedtls_mpi_free( &ctx->z );
|
||||
mbedtls_mpi_free( &ctx->_d );
|
||||
|
||||
#if defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
mbedtls_ecp_restart_free( &ctx->rs );
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
/*
|
||||
* Enable restartable operations for context
|
||||
*/
|
||||
void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx )
|
||||
{
|
||||
ctx->restart_enabled = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Setup and write the ServerKeyExhange parameters (RFC 4492)
|
||||
* struct {
|
||||
@@ -126,12 +191,18 @@ int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen,
|
||||
{
|
||||
int ret;
|
||||
size_t grp_len, pt_len;
|
||||
mbedtls_ecp_restart_ctx *rs_ctx = NULL;
|
||||
|
||||
if( ctx == NULL || ctx->grp.pbits == 0 )
|
||||
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
|
||||
|
||||
if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) )
|
||||
!= 0 )
|
||||
#if defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
if( ctx->restart_enabled )
|
||||
rs_ctx = &ctx->rs;
|
||||
#endif
|
||||
|
||||
if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q,
|
||||
f_rng, p_rng, rs_ctx ) ) != 0 )
|
||||
return( ret );
|
||||
|
||||
if( ( ret = mbedtls_ecp_tls_write_group( &ctx->grp, &grp_len, buf, blen ) )
|
||||
@@ -142,7 +213,7 @@ int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen,
|
||||
blen -= grp_len;
|
||||
|
||||
if( ( ret = mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, ctx->point_format,
|
||||
&pt_len, buf, blen ) ) != 0 )
|
||||
&pt_len, buf, blen ) ) != 0 )
|
||||
return( ret );
|
||||
|
||||
*olen = grp_len + pt_len;
|
||||
@@ -206,12 +277,18 @@ int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen,
|
||||
void *p_rng )
|
||||
{
|
||||
int ret;
|
||||
mbedtls_ecp_restart_ctx *rs_ctx = NULL;
|
||||
|
||||
if( ctx == NULL || ctx->grp.pbits == 0 )
|
||||
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
|
||||
|
||||
if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) )
|
||||
!= 0 )
|
||||
#if defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
if( ctx->restart_enabled )
|
||||
rs_ctx = &ctx->rs;
|
||||
#endif
|
||||
|
||||
if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q,
|
||||
f_rng, p_rng, rs_ctx ) ) != 0 )
|
||||
return( ret );
|
||||
|
||||
return mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, ctx->point_format,
|
||||
@@ -248,12 +325,18 @@ int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen,
|
||||
void *p_rng )
|
||||
{
|
||||
int ret;
|
||||
mbedtls_ecp_restart_ctx *rs_ctx = NULL;
|
||||
|
||||
if( ctx == NULL )
|
||||
if( ctx == NULL || ctx->grp.pbits == 0 )
|
||||
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
|
||||
|
||||
if( ( ret = mbedtls_ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp, &ctx->d,
|
||||
f_rng, p_rng ) ) != 0 )
|
||||
#if defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
if( ctx->restart_enabled )
|
||||
rs_ctx = &ctx->rs;
|
||||
#endif
|
||||
|
||||
if( ( ret = ecdh_compute_shared_restartable( &ctx->grp,
|
||||
&ctx->z, &ctx->Qp, &ctx->d, f_rng, p_rng, rs_ctx ) ) != 0 )
|
||||
{
|
||||
return( ret );
|
||||
}
|
||||
|
||||
481
library/ecdsa.c
481
library/ecdsa.c
@@ -42,6 +42,178 @@
|
||||
#include "mbedtls/hmac_drbg.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_PLATFORM_C)
|
||||
#include "mbedtls/platform.h"
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#define mbedtls_calloc calloc
|
||||
#define mbedtls_free free
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
|
||||
/*
|
||||
* Sub-context for ecdsa_verify()
|
||||
*/
|
||||
struct mbedtls_ecdsa_restart_ver
|
||||
{
|
||||
mbedtls_mpi u1, u2; /* intermediate values */
|
||||
enum { /* what to do next? */
|
||||
ecdsa_ver_init = 0, /* getting started */
|
||||
ecdsa_ver_muladd, /* muladd step */
|
||||
} state;
|
||||
};
|
||||
|
||||
/*
|
||||
* Init verify restart sub-context
|
||||
*/
|
||||
static void ecdsa_restart_ver_init( mbedtls_ecdsa_restart_ver_ctx *ctx )
|
||||
{
|
||||
mbedtls_mpi_init( &ctx->u1 );
|
||||
mbedtls_mpi_init( &ctx->u2 );
|
||||
ctx->state = ecdsa_ver_init;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free the components of a verify restart sub-context
|
||||
*/
|
||||
static void ecdsa_restart_ver_free( mbedtls_ecdsa_restart_ver_ctx *ctx )
|
||||
{
|
||||
if( ctx == NULL )
|
||||
return;
|
||||
|
||||
mbedtls_mpi_free( &ctx->u1 );
|
||||
mbedtls_mpi_free( &ctx->u2 );
|
||||
|
||||
ecdsa_restart_ver_init( ctx );
|
||||
}
|
||||
|
||||
/*
|
||||
* Sub-context for ecdsa_sign()
|
||||
*/
|
||||
struct mbedtls_ecdsa_restart_sig
|
||||
{
|
||||
int sign_tries;
|
||||
int key_tries;
|
||||
mbedtls_mpi k; /* per-signature random */
|
||||
mbedtls_mpi r; /* r value */
|
||||
enum { /* what to do next? */
|
||||
ecdsa_sig_init = 0, /* getting started */
|
||||
ecdsa_sig_mul, /* doing ecp_mul() */
|
||||
ecdsa_sig_modn, /* mod N computations */
|
||||
} state;
|
||||
};
|
||||
|
||||
/*
|
||||
* Init verify sign sub-context
|
||||
*/
|
||||
static void ecdsa_restart_sig_init( mbedtls_ecdsa_restart_sig_ctx *ctx )
|
||||
{
|
||||
ctx->sign_tries = 0;
|
||||
ctx->key_tries = 0;
|
||||
mbedtls_mpi_init( &ctx->k );
|
||||
mbedtls_mpi_init( &ctx->r );
|
||||
ctx->state = ecdsa_sig_init;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free the components of a sign restart sub-context
|
||||
*/
|
||||
static void ecdsa_restart_sig_free( mbedtls_ecdsa_restart_sig_ctx *ctx )
|
||||
{
|
||||
if( ctx == NULL )
|
||||
return;
|
||||
|
||||
mbedtls_mpi_free( &ctx->k );
|
||||
mbedtls_mpi_free( &ctx->r );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
|
||||
/*
|
||||
* Sub-context for ecdsa_sign_det()
|
||||
*/
|
||||
struct mbedtls_ecdsa_restart_det
|
||||
{
|
||||
mbedtls_hmac_drbg_context rng_ctx; /* DRBG state */
|
||||
enum { /* what to do next? */
|
||||
ecdsa_det_init = 0, /* getting started */
|
||||
ecdsa_det_sign, /* make signature */
|
||||
} state;
|
||||
};
|
||||
|
||||
/*
|
||||
* Init verify sign_det sub-context
|
||||
*/
|
||||
static void ecdsa_restart_det_init( mbedtls_ecdsa_restart_det_ctx *ctx )
|
||||
{
|
||||
mbedtls_hmac_drbg_init( &ctx->rng_ctx );
|
||||
ctx->state = ecdsa_det_init;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free the components of a sign_det restart sub-context
|
||||
*/
|
||||
static void ecdsa_restart_det_free( mbedtls_ecdsa_restart_det_ctx *ctx )
|
||||
{
|
||||
if( ctx == NULL )
|
||||
return;
|
||||
|
||||
mbedtls_hmac_drbg_free( &ctx->rng_ctx );
|
||||
|
||||
ecdsa_restart_det_init( ctx );
|
||||
}
|
||||
#endif /* MBEDTLS_ECDSA_DETERMINISTIC */
|
||||
|
||||
#define ECDSA_RS_ECP &rs_ctx->ecp
|
||||
|
||||
/* Utility macro for checking and updating ops budget */
|
||||
#define ECDSA_BUDGET( ops ) \
|
||||
MBEDTLS_MPI_CHK( mbedtls_ecp_check_budget( grp, &rs_ctx->ecp, ops ) );
|
||||
|
||||
/* Call this when entering a function that needs its own sub-context */
|
||||
#define ECDSA_RS_ENTER( SUB ) do { \
|
||||
/* reset ops count for this call if top-level */ \
|
||||
if( rs_ctx != NULL && rs_ctx->ecp.depth++ == 0 ) \
|
||||
rs_ctx->ecp.ops_done = 0; \
|
||||
\
|
||||
/* set up our own sub-context if needed */ \
|
||||
if( mbedtls_ecp_restart_is_enabled() && \
|
||||
rs_ctx != NULL && rs_ctx->SUB == NULL ) \
|
||||
{ \
|
||||
rs_ctx->SUB = mbedtls_calloc( 1, sizeof( *rs_ctx->SUB ) ); \
|
||||
if( rs_ctx->SUB == NULL ) \
|
||||
return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); \
|
||||
\
|
||||
ecdsa_restart_## SUB ##_init( rs_ctx->SUB ); \
|
||||
} \
|
||||
} while( 0 )
|
||||
|
||||
/* Call this when leaving a function that needs its own sub-context */
|
||||
#define ECDSA_RS_LEAVE( SUB ) do { \
|
||||
/* clear our sub-context when not in progress (done or error) */ \
|
||||
if( rs_ctx != NULL && rs_ctx->SUB != NULL && \
|
||||
ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) \
|
||||
{ \
|
||||
ecdsa_restart_## SUB ##_free( rs_ctx->SUB ); \
|
||||
mbedtls_free( rs_ctx->SUB ); \
|
||||
rs_ctx->SUB = NULL; \
|
||||
} \
|
||||
\
|
||||
if( rs_ctx != NULL ) \
|
||||
rs_ctx->ecp.depth--; \
|
||||
} while( 0 )
|
||||
|
||||
#else /* MBEDTLS_ECP_RESTARTABLE */
|
||||
|
||||
#define ECDSA_RS_ECP NULL
|
||||
|
||||
#define ECDSA_BUDGET( ops ) /* no-op; for compatibility */
|
||||
|
||||
#define ECDSA_RS_ENTER( SUB ) (void) rs_ctx
|
||||
#define ECDSA_RS_LEAVE( SUB ) (void) rs_ctx
|
||||
|
||||
#endif /* MBEDTLS_ECP_RESTARTABLE */
|
||||
|
||||
/*
|
||||
* Derive a suitable integer for group grp from a buffer of length len
|
||||
* SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3
|
||||
@@ -70,13 +242,17 @@ cleanup:
|
||||
* Compute ECDSA signature of a hashed message (SEC1 4.1.3)
|
||||
* Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message)
|
||||
*/
|
||||
int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
|
||||
static int ecdsa_sign_restartable( mbedtls_ecp_group *grp,
|
||||
mbedtls_mpi *r, mbedtls_mpi *s,
|
||||
const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
|
||||
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
|
||||
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
|
||||
mbedtls_ecdsa_restart_ctx *rs_ctx )
|
||||
{
|
||||
int ret, key_tries, sign_tries, blind_tries;
|
||||
int ret, key_tries, sign_tries;
|
||||
int *p_sign_tries = &sign_tries, *p_key_tries = &key_tries;
|
||||
mbedtls_ecp_point R;
|
||||
mbedtls_mpi k, e, t;
|
||||
mbedtls_mpi *pk = &k, *pr = r;
|
||||
|
||||
/* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */
|
||||
if( grp->N.p == NULL )
|
||||
@@ -89,26 +265,72 @@ int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
|
||||
mbedtls_ecp_point_init( &R );
|
||||
mbedtls_mpi_init( &k ); mbedtls_mpi_init( &e ); mbedtls_mpi_init( &t );
|
||||
|
||||
sign_tries = 0;
|
||||
ECDSA_RS_ENTER( sig );
|
||||
|
||||
#if defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
if( rs_ctx != NULL && rs_ctx->sig != NULL )
|
||||
{
|
||||
/* redirect to our context */
|
||||
p_sign_tries = &rs_ctx->sig->sign_tries;
|
||||
p_key_tries = &rs_ctx->sig->key_tries;
|
||||
pk = &rs_ctx->sig->k;
|
||||
pr = &rs_ctx->sig->r;
|
||||
|
||||
/* jump to current step */
|
||||
if( rs_ctx->sig->state == ecdsa_sig_mul )
|
||||
goto mul;
|
||||
if( rs_ctx->sig->state == ecdsa_sig_modn )
|
||||
goto modn;
|
||||
}
|
||||
#endif /* MBEDTLS_ECP_RESTARTABLE */
|
||||
|
||||
*p_sign_tries = 0;
|
||||
do
|
||||
{
|
||||
if( *p_sign_tries++ > 10 )
|
||||
{
|
||||
ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
* Steps 1-3: generate a suitable ephemeral keypair
|
||||
* and set r = xR mod n
|
||||
*/
|
||||
key_tries = 0;
|
||||
*p_key_tries = 0;
|
||||
do
|
||||
{
|
||||
MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair( grp, &k, &R, f_rng, p_rng ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( r, &R.X, &grp->N ) );
|
||||
|
||||
if( key_tries++ > 10 )
|
||||
if( *p_key_tries++ > 10 )
|
||||
{
|
||||
ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, pk, f_rng, p_rng ) );
|
||||
|
||||
#if defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
if( rs_ctx != NULL && rs_ctx->sig != NULL )
|
||||
rs_ctx->sig->state = ecdsa_sig_mul;
|
||||
|
||||
mul:
|
||||
#endif
|
||||
MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &R, pk, &grp->G,
|
||||
f_rng, p_rng, ECDSA_RS_ECP ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pr, &R.X, &grp->N ) );
|
||||
}
|
||||
while( mbedtls_mpi_cmp_int( r, 0 ) == 0 );
|
||||
while( mbedtls_mpi_cmp_int( pr, 0 ) == 0 );
|
||||
|
||||
#if defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
if( rs_ctx != NULL && rs_ctx->sig != NULL )
|
||||
rs_ctx->sig->state = ecdsa_sig_modn;
|
||||
|
||||
modn:
|
||||
#endif
|
||||
/*
|
||||
* Accounting for everything up to the end of the loop
|
||||
* (step 6, but checking now avoids saving e and t)
|
||||
*/
|
||||
ECDSA_BUDGET( MBEDTLS_ECP_OPS_INV + 4 );
|
||||
|
||||
/*
|
||||
* Step 5: derive MPI from hashed message
|
||||
@@ -119,57 +341,60 @@ int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
|
||||
* Generate a random value to blind inv_mod in next step,
|
||||
* avoiding a potential timing leak.
|
||||
*/
|
||||
blind_tries = 0;
|
||||
do
|
||||
{
|
||||
size_t n_size = ( grp->nbits + 7 ) / 8;
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &t, n_size, f_rng, p_rng ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &t, 8 * n_size - grp->nbits ) );
|
||||
|
||||
/* See mbedtls_ecp_gen_keypair() */
|
||||
if( ++blind_tries > 30 )
|
||||
return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
|
||||
}
|
||||
while( mbedtls_mpi_cmp_int( &t, 1 ) < 0 ||
|
||||
mbedtls_mpi_cmp_mpi( &t, &grp->N ) >= 0 );
|
||||
MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, &t, f_rng, p_rng ) );
|
||||
|
||||
/*
|
||||
* Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n
|
||||
*/
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, r, d ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, pr, d ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &e, &e, s ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &e, &e, &t ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &k, &k, &t ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, &k, &grp->N ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pk, pk, &t ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, pk, &grp->N ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, s, &e ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( s, s, &grp->N ) );
|
||||
|
||||
if( sign_tries++ > 10 )
|
||||
{
|
||||
ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
while( mbedtls_mpi_cmp_int( s, 0 ) == 0 );
|
||||
|
||||
#if defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
if( rs_ctx != NULL && rs_ctx->sig != NULL )
|
||||
mbedtls_mpi_copy( r, pr );
|
||||
#endif
|
||||
|
||||
cleanup:
|
||||
mbedtls_ecp_point_free( &R );
|
||||
mbedtls_mpi_free( &k ); mbedtls_mpi_free( &e ); mbedtls_mpi_free( &t );
|
||||
|
||||
ECDSA_RS_LEAVE( sig );
|
||||
|
||||
return( ret );
|
||||
}
|
||||
#endif /* MBEDTLS_ECDSA_SIGN_ALT */
|
||||
|
||||
/*
|
||||
* Compute ECDSA signature of a hashed message
|
||||
*/
|
||||
int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
|
||||
const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
|
||||
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
|
||||
{
|
||||
return( ecdsa_sign_restartable( grp, r, s, d, buf, blen,
|
||||
f_rng, p_rng, NULL ) );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
|
||||
/*
|
||||
* Deterministic signature wrapper
|
||||
*/
|
||||
int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
|
||||
static int ecdsa_sign_det_restartable( mbedtls_ecp_group *grp,
|
||||
mbedtls_mpi *r, mbedtls_mpi *s,
|
||||
const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
|
||||
mbedtls_md_type_t md_alg )
|
||||
mbedtls_md_type_t md_alg,
|
||||
mbedtls_ecdsa_restart_ctx *rs_ctx )
|
||||
{
|
||||
int ret;
|
||||
mbedtls_hmac_drbg_context rng_ctx;
|
||||
mbedtls_hmac_drbg_context *p_rng = &rng_ctx;
|
||||
unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES];
|
||||
size_t grp_len = ( grp->nbits + 7 ) / 8;
|
||||
const mbedtls_md_info_t *md_info;
|
||||
@@ -181,21 +406,53 @@ int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi
|
||||
mbedtls_mpi_init( &h );
|
||||
mbedtls_hmac_drbg_init( &rng_ctx );
|
||||
|
||||
ECDSA_RS_ENTER( det );
|
||||
|
||||
#if defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
if( rs_ctx != NULL && rs_ctx->det != NULL )
|
||||
{
|
||||
/* redirect to our context */
|
||||
p_rng = &rs_ctx->det->rng_ctx;
|
||||
|
||||
/* jump to current step */
|
||||
if( rs_ctx->det->state == ecdsa_det_sign )
|
||||
goto sign;
|
||||
}
|
||||
#endif /* MBEDTLS_ECP_RESTARTABLE */
|
||||
|
||||
/* Use private key and message hash (reduced) to initialize HMAC_DRBG */
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( d, data, grp_len ) );
|
||||
MBEDTLS_MPI_CHK( derive_mpi( grp, &h, buf, blen ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, data + grp_len, grp_len ) );
|
||||
mbedtls_hmac_drbg_seed_buf( &rng_ctx, md_info, data, 2 * grp_len );
|
||||
mbedtls_hmac_drbg_seed_buf( p_rng, md_info, data, 2 * grp_len );
|
||||
|
||||
ret = mbedtls_ecdsa_sign( grp, r, s, d, buf, blen,
|
||||
mbedtls_hmac_drbg_random, &rng_ctx );
|
||||
#if defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
if( rs_ctx != NULL && rs_ctx->det != NULL )
|
||||
rs_ctx->det->state = ecdsa_det_sign;
|
||||
|
||||
sign:
|
||||
#endif
|
||||
ret = ecdsa_sign_restartable( grp, r, s, d, buf, blen,
|
||||
mbedtls_hmac_drbg_random, p_rng, rs_ctx );
|
||||
|
||||
cleanup:
|
||||
mbedtls_hmac_drbg_free( &rng_ctx );
|
||||
mbedtls_mpi_free( &h );
|
||||
|
||||
ECDSA_RS_LEAVE( det );
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
/*
|
||||
* Deterministic signature wrapper
|
||||
*/
|
||||
int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
|
||||
const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
|
||||
mbedtls_md_type_t md_alg )
|
||||
{
|
||||
return( ecdsa_sign_det_restartable( grp, r, s, d, buf, blen, md_alg, NULL ) );
|
||||
}
|
||||
#endif /* MBEDTLS_ECDSA_DETERMINISTIC */
|
||||
|
||||
#if !defined(MBEDTLS_ECDSA_VERIFY_ALT)
|
||||
@@ -203,21 +460,40 @@ cleanup:
|
||||
* Verify ECDSA signature of hashed message (SEC1 4.1.4)
|
||||
* Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message)
|
||||
*/
|
||||
int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp,
|
||||
const unsigned char *buf, size_t blen,
|
||||
const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s)
|
||||
static int ecdsa_verify_restartable( mbedtls_ecp_group *grp,
|
||||
const unsigned char *buf, size_t blen,
|
||||
const mbedtls_ecp_point *Q,
|
||||
const mbedtls_mpi *r, const mbedtls_mpi *s,
|
||||
mbedtls_ecdsa_restart_ctx *rs_ctx )
|
||||
{
|
||||
int ret;
|
||||
mbedtls_mpi e, s_inv, u1, u2;
|
||||
mbedtls_ecp_point R;
|
||||
mbedtls_mpi *pu1 = &u1, *pu2 = &u2;
|
||||
|
||||
mbedtls_ecp_point_init( &R );
|
||||
mbedtls_mpi_init( &e ); mbedtls_mpi_init( &s_inv ); mbedtls_mpi_init( &u1 ); mbedtls_mpi_init( &u2 );
|
||||
mbedtls_mpi_init( &e ); mbedtls_mpi_init( &s_inv );
|
||||
mbedtls_mpi_init( &u1 ); mbedtls_mpi_init( &u2 );
|
||||
|
||||
/* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */
|
||||
if( grp->N.p == NULL )
|
||||
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
|
||||
|
||||
ECDSA_RS_ENTER( ver );
|
||||
|
||||
#if defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
if( rs_ctx != NULL && rs_ctx->ver != NULL )
|
||||
{
|
||||
/* redirect to our context */
|
||||
pu1 = &rs_ctx->ver->u1;
|
||||
pu2 = &rs_ctx->ver->u2;
|
||||
|
||||
/* jump to current step */
|
||||
if( rs_ctx->ver->state == ecdsa_ver_muladd )
|
||||
goto muladd;
|
||||
}
|
||||
#endif /* MBEDTLS_ECP_RESTARTABLE */
|
||||
|
||||
/*
|
||||
* Step 1: make sure r and s are in range 1..n-1
|
||||
*/
|
||||
@@ -228,11 +504,6 @@ int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
* Additional precaution: make sure Q is valid
|
||||
*/
|
||||
MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, Q ) );
|
||||
|
||||
/*
|
||||
* Step 3: derive MPI from hashed message
|
||||
*/
|
||||
@@ -241,21 +512,27 @@ int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp,
|
||||
/*
|
||||
* Step 4: u1 = e / s mod n, u2 = r / s mod n
|
||||
*/
|
||||
ECDSA_BUDGET( MBEDTLS_ECP_OPS_CHK + MBEDTLS_ECP_OPS_INV + 2 );
|
||||
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &s_inv, s, &grp->N ) );
|
||||
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u1, &e, &s_inv ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &u1, &u1, &grp->N ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pu1, &e, &s_inv ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pu1, pu1, &grp->N ) );
|
||||
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u2, r, &s_inv ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &u2, &u2, &grp->N ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pu2, r, &s_inv ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pu2, pu2, &grp->N ) );
|
||||
|
||||
#if defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
if( rs_ctx != NULL && rs_ctx->ver != NULL )
|
||||
rs_ctx->ver->state = ecdsa_ver_muladd;
|
||||
|
||||
muladd:
|
||||
#endif
|
||||
/*
|
||||
* Step 5: R = u1 G + u2 Q
|
||||
*
|
||||
* Since we're not using any secret data, no need to pass a RNG to
|
||||
* mbedtls_ecp_mul() for countermesures.
|
||||
*/
|
||||
MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, &R, &u1, &grp->G, &u2, Q ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_ecp_muladd_restartable( grp,
|
||||
&R, pu1, &grp->G, pu2, Q, ECDSA_RS_ECP ) );
|
||||
|
||||
if( mbedtls_ecp_is_zero( &R ) )
|
||||
{
|
||||
@@ -280,12 +557,25 @@ int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp,
|
||||
|
||||
cleanup:
|
||||
mbedtls_ecp_point_free( &R );
|
||||
mbedtls_mpi_free( &e ); mbedtls_mpi_free( &s_inv ); mbedtls_mpi_free( &u1 ); mbedtls_mpi_free( &u2 );
|
||||
mbedtls_mpi_free( &e ); mbedtls_mpi_free( &s_inv );
|
||||
mbedtls_mpi_free( &u1 ); mbedtls_mpi_free( &u2 );
|
||||
|
||||
ECDSA_RS_LEAVE( ver );
|
||||
|
||||
return( ret );
|
||||
}
|
||||
#endif /* MBEDTLS_ECDSA_VERIFY_ALT */
|
||||
|
||||
/*
|
||||
* Verify ECDSA signature of hashed message
|
||||
*/
|
||||
int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp,
|
||||
const unsigned char *buf, size_t blen,
|
||||
const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s)
|
||||
{
|
||||
return( ecdsa_verify_restartable( grp, buf, blen, Q, r, s, NULL ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a signature (given by context) to ASN.1
|
||||
*/
|
||||
@@ -313,11 +603,13 @@ static int ecdsa_signature_to_asn1( const mbedtls_mpi *r, const mbedtls_mpi *s,
|
||||
/*
|
||||
* Compute and write signature
|
||||
*/
|
||||
int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg,
|
||||
int mbedtls_ecdsa_write_signature_restartable( mbedtls_ecdsa_context *ctx,
|
||||
mbedtls_md_type_t md_alg,
|
||||
const unsigned char *hash, size_t hlen,
|
||||
unsigned char *sig, size_t *slen,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng )
|
||||
void *p_rng,
|
||||
mbedtls_ecdsa_restart_ctx *rs_ctx )
|
||||
{
|
||||
int ret;
|
||||
mbedtls_mpi r, s;
|
||||
@@ -329,13 +621,13 @@ int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t
|
||||
(void) f_rng;
|
||||
(void) p_rng;
|
||||
|
||||
MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign_det( &ctx->grp, &r, &s, &ctx->d,
|
||||
hash, hlen, md_alg ) );
|
||||
MBEDTLS_MPI_CHK( ecdsa_sign_det_restartable( &ctx->grp, &r, &s, &ctx->d,
|
||||
hash, hlen, md_alg, rs_ctx ) );
|
||||
#else
|
||||
(void) md_alg;
|
||||
|
||||
MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d,
|
||||
hash, hlen, f_rng, p_rng ) );
|
||||
MBEDTLS_MPI_CHK( ecdsa_sign_restartable( &ctx->grp, &r, &s, &ctx->d,
|
||||
hash, hlen, f_rng, p_rng, rs_ctx ) );
|
||||
#endif
|
||||
|
||||
MBEDTLS_MPI_CHK( ecdsa_signature_to_asn1( &r, &s, sig, slen ) );
|
||||
@@ -347,6 +639,19 @@ cleanup:
|
||||
return( ret );
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute and write signature
|
||||
*/
|
||||
int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg,
|
||||
const unsigned char *hash, size_t hlen,
|
||||
unsigned char *sig, size_t *slen,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng )
|
||||
{
|
||||
return( mbedtls_ecdsa_write_signature_restartable(
|
||||
ctx, md_alg, hash, hlen, sig, slen, f_rng, p_rng, NULL ) );
|
||||
}
|
||||
|
||||
#if ! defined(MBEDTLS_DEPRECATED_REMOVED) && \
|
||||
defined(MBEDTLS_ECDSA_DETERMINISTIC)
|
||||
int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx,
|
||||
@@ -365,6 +670,18 @@ int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx,
|
||||
int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx,
|
||||
const unsigned char *hash, size_t hlen,
|
||||
const unsigned char *sig, size_t slen )
|
||||
{
|
||||
return( mbedtls_ecdsa_read_signature_restartable(
|
||||
ctx, hash, hlen, sig, slen, NULL ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* Restartable read and check signature
|
||||
*/
|
||||
int mbedtls_ecdsa_read_signature_restartable( mbedtls_ecdsa_context *ctx,
|
||||
const unsigned char *hash, size_t hlen,
|
||||
const unsigned char *sig, size_t slen,
|
||||
mbedtls_ecdsa_restart_ctx *rs_ctx )
|
||||
{
|
||||
int ret;
|
||||
unsigned char *p = (unsigned char *) sig;
|
||||
@@ -396,8 +713,8 @@ int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if( ( ret = mbedtls_ecdsa_verify( &ctx->grp, hash, hlen,
|
||||
&ctx->Q, &r, &s ) ) != 0 )
|
||||
if( ( ret = ecdsa_verify_restartable( &ctx->grp, hash, hlen,
|
||||
&ctx->Q, &r, &s, rs_ctx ) ) != 0 )
|
||||
goto cleanup;
|
||||
|
||||
/* At this point we know that the buffer starts with a valid signature.
|
||||
@@ -458,4 +775,42 @@ void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx )
|
||||
mbedtls_ecp_keypair_free( ctx );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
/*
|
||||
* Initialize a restart context
|
||||
*/
|
||||
void mbedtls_ecdsa_restart_init( mbedtls_ecdsa_restart_ctx *ctx )
|
||||
{
|
||||
mbedtls_ecp_restart_init( &ctx->ecp );
|
||||
|
||||
ctx->ver = NULL;
|
||||
ctx->sig = NULL;
|
||||
#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
|
||||
ctx->det = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Free the components of a restart context
|
||||
*/
|
||||
void mbedtls_ecdsa_restart_free( mbedtls_ecdsa_restart_ctx *ctx )
|
||||
{
|
||||
mbedtls_ecp_restart_free( &ctx->ecp );
|
||||
|
||||
ecdsa_restart_ver_free( ctx->ver );
|
||||
mbedtls_free( ctx->ver );
|
||||
ctx->ver = NULL;
|
||||
|
||||
ecdsa_restart_sig_free( ctx->sig );
|
||||
mbedtls_free( ctx->sig );
|
||||
ctx->sig = NULL;
|
||||
|
||||
#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
|
||||
ecdsa_restart_det_free( ctx->det );
|
||||
mbedtls_free( ctx->det );
|
||||
ctx->det = NULL;
|
||||
#endif
|
||||
}
|
||||
#endif /* MBEDTLS_ECP_RESTARTABLE */
|
||||
|
||||
#endif /* MBEDTLS_ECDSA_C */
|
||||
|
||||
1053
library/ecp.c
1053
library/ecp.c
File diff suppressed because it is too large
Load Diff
@@ -19,19 +19,25 @@
|
||||
* This file is part of mbed TLS (https://tls.mbed.org)
|
||||
*/
|
||||
|
||||
#if defined(__linux__)
|
||||
/* Ensure that syscall() is available even when compiling with -std=c99 */
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#if defined(MBEDTLS_ENTROPY_C)
|
||||
|
||||
#include "mbedtls/entropy.h"
|
||||
#include "mbedtls/entropy_poll.h"
|
||||
|
||||
#if defined(MBEDTLS_TIMING_C)
|
||||
#include <string.h>
|
||||
#include "mbedtls/timing.h"
|
||||
#endif
|
||||
#if defined(MBEDTLS_HAVEGE_C)
|
||||
@@ -44,7 +50,8 @@
|
||||
#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY)
|
||||
|
||||
#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \
|
||||
!defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__)
|
||||
!defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \
|
||||
!defined(__HAIKU__)
|
||||
#error "Platform entropy sources only work on Unix and Windows, see MBEDTLS_NO_PLATFORM_ENTROPY in config.h"
|
||||
#endif
|
||||
|
||||
|
||||
@@ -49,6 +49,10 @@
|
||||
#include "mbedtls/arc4.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_ARIA_C)
|
||||
#include "mbedtls/aria.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_BASE64_C)
|
||||
#include "mbedtls/base64.h"
|
||||
#endif
|
||||
@@ -69,6 +73,14 @@
|
||||
#include "mbedtls/ccm.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_CHACHA20_C)
|
||||
#include "mbedtls/chacha20.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_CHACHAPOLY_C)
|
||||
#include "mbedtls/chachapoly.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_CIPHER_C)
|
||||
#include "mbedtls/cipher.h"
|
||||
#endif
|
||||
@@ -101,6 +113,10 @@
|
||||
#include "mbedtls/gcm.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_HKDF_C)
|
||||
#include "mbedtls/hkdf.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_HMAC_DRBG_C)
|
||||
#include "mbedtls/hmac_drbg.h"
|
||||
#endif
|
||||
@@ -149,6 +165,14 @@
|
||||
#include "mbedtls/pkcs5.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_PLATFORM_C)
|
||||
#include "mbedtls/platform.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_POLY1305_C)
|
||||
#include "mbedtls/poly1305.h"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_RIPEMD160_C)
|
||||
#include "mbedtls/ripemd160.h"
|
||||
#endif
|
||||
@@ -269,6 +293,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
|
||||
mbedtls_snprintf( buf, buflen, "ECP - The buffer contains a valid signature followed by more data" );
|
||||
if( use_ret == -(MBEDTLS_ERR_ECP_HW_ACCEL_FAILED) )
|
||||
mbedtls_snprintf( buf, buflen, "ECP - The ECP hardware accelerator failed" );
|
||||
if( use_ret == -(MBEDTLS_ERR_ECP_IN_PROGRESS) )
|
||||
mbedtls_snprintf( buf, buflen, "ECP - Operation in progress, call again with the same parameters to continue" );
|
||||
#endif /* MBEDTLS_ECP_C */
|
||||
|
||||
#if defined(MBEDTLS_MD_C)
|
||||
@@ -493,6 +519,12 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
|
||||
mbedtls_snprintf( buf, buflen, "SSL - Couldn't set the hash for verifying CertificateVerify" );
|
||||
if( use_ret == -(MBEDTLS_ERR_SSL_CONTINUE_PROCESSING) )
|
||||
mbedtls_snprintf( buf, buflen, "SSL - Internal-only message signaling that further message-processing should be done" );
|
||||
if( use_ret == -(MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) )
|
||||
mbedtls_snprintf( buf, buflen, "SSL - The asynchronous operation is not completed yet" );
|
||||
if( use_ret == -(MBEDTLS_ERR_SSL_EARLY_MESSAGE) )
|
||||
mbedtls_snprintf( buf, buflen, "SSL - Internal-only message signaling that a message arrived early" );
|
||||
if( use_ret == -(MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) )
|
||||
mbedtls_snprintf( buf, buflen, "SSL - A cryptographic operation is in progress. Try again later" );
|
||||
#endif /* MBEDTLS_SSL_TLS_C */
|
||||
|
||||
#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C)
|
||||
@@ -572,6 +604,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
|
||||
mbedtls_snprintf( buf, buflen, "AES - Invalid key length" );
|
||||
if( use_ret == -(MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH) )
|
||||
mbedtls_snprintf( buf, buflen, "AES - Invalid data input length" );
|
||||
if( use_ret == -(MBEDTLS_ERR_AES_BAD_INPUT_DATA) )
|
||||
mbedtls_snprintf( buf, buflen, "AES - Invalid input data" );
|
||||
if( use_ret == -(MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE) )
|
||||
mbedtls_snprintf( buf, buflen, "AES - Feature not available. For example, an unsupported AES key size" );
|
||||
if( use_ret == -(MBEDTLS_ERR_AES_HW_ACCEL_FAILED) )
|
||||
@@ -583,6 +617,17 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
|
||||
mbedtls_snprintf( buf, buflen, "ARC4 - ARC4 hardware accelerator failed" );
|
||||
#endif /* MBEDTLS_ARC4_C */
|
||||
|
||||
#if defined(MBEDTLS_ARIA_C)
|
||||
if( use_ret == -(MBEDTLS_ERR_ARIA_INVALID_KEY_LENGTH) )
|
||||
mbedtls_snprintf( buf, buflen, "ARIA - Invalid key length" );
|
||||
if( use_ret == -(MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH) )
|
||||
mbedtls_snprintf( buf, buflen, "ARIA - Invalid data input length" );
|
||||
if( use_ret == -(MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE) )
|
||||
mbedtls_snprintf( buf, buflen, "ARIA - Feature not available. For example, an unsupported ARIA key size" );
|
||||
if( use_ret == -(MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED) )
|
||||
mbedtls_snprintf( buf, buflen, "ARIA - ARIA hardware accelerator failed" );
|
||||
#endif /* MBEDTLS_ARIA_C */
|
||||
|
||||
#if defined(MBEDTLS_ASN1_PARSE_C)
|
||||
if( use_ret == -(MBEDTLS_ERR_ASN1_OUT_OF_DATA) )
|
||||
mbedtls_snprintf( buf, buflen, "ASN1 - Out of data when parsing an ASN1 data structure" );
|
||||
@@ -653,6 +698,22 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
|
||||
mbedtls_snprintf( buf, buflen, "CCM - CCM hardware accelerator failed" );
|
||||
#endif /* MBEDTLS_CCM_C */
|
||||
|
||||
#if defined(MBEDTLS_CHACHA20_C)
|
||||
if( use_ret == -(MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA) )
|
||||
mbedtls_snprintf( buf, buflen, "CHACHA20 - Invalid input parameter(s)" );
|
||||
if( use_ret == -(MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE) )
|
||||
mbedtls_snprintf( buf, buflen, "CHACHA20 - Feature not available. For example, s part of the API is not implemented" );
|
||||
if( use_ret == -(MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED) )
|
||||
mbedtls_snprintf( buf, buflen, "CHACHA20 - Chacha20 hardware accelerator failed" );
|
||||
#endif /* MBEDTLS_CHACHA20_C */
|
||||
|
||||
#if defined(MBEDTLS_CHACHAPOLY_C)
|
||||
if( use_ret == -(MBEDTLS_ERR_CHACHAPOLY_BAD_STATE) )
|
||||
mbedtls_snprintf( buf, buflen, "CHACHAPOLY - The requested operation is not permitted in the current state" );
|
||||
if( use_ret == -(MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED) )
|
||||
mbedtls_snprintf( buf, buflen, "CHACHAPOLY - Authenticated decryption failed: data was not authentic" );
|
||||
#endif /* MBEDTLS_CHACHAPOLY_C */
|
||||
|
||||
#if defined(MBEDTLS_CMAC_C)
|
||||
if( use_ret == -(MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED) )
|
||||
mbedtls_snprintf( buf, buflen, "CMAC - CMAC hardware accelerator failed" );
|
||||
@@ -698,6 +759,11 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
|
||||
mbedtls_snprintf( buf, buflen, "GCM - Bad input parameters to function" );
|
||||
#endif /* MBEDTLS_GCM_C */
|
||||
|
||||
#if defined(MBEDTLS_HKDF_C)
|
||||
if( use_ret == -(MBEDTLS_ERR_HKDF_BAD_INPUT_DATA) )
|
||||
mbedtls_snprintf( buf, buflen, "HKDF - Bad input parameters to function" );
|
||||
#endif /* MBEDTLS_HKDF_C */
|
||||
|
||||
#if defined(MBEDTLS_HMAC_DRBG_C)
|
||||
if( use_ret == -(MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG) )
|
||||
mbedtls_snprintf( buf, buflen, "HMAC_DRBG - Too many random requested in single call" );
|
||||
@@ -765,6 +831,20 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
|
||||
mbedtls_snprintf( buf, buflen, "PADLOCK - Input data should be aligned" );
|
||||
#endif /* MBEDTLS_PADLOCK_C */
|
||||
|
||||
#if defined(MBEDTLS_PLATFORM_C)
|
||||
if( use_ret == -(MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED) )
|
||||
mbedtls_snprintf( buf, buflen, "PLATFORM - Hardware accelerator failed" );
|
||||
#endif /* MBEDTLS_PLATFORM_C */
|
||||
|
||||
#if defined(MBEDTLS_POLY1305_C)
|
||||
if( use_ret == -(MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA) )
|
||||
mbedtls_snprintf( buf, buflen, "POLY1305 - Invalid input parameter(s)" );
|
||||
if( use_ret == -(MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE) )
|
||||
mbedtls_snprintf( buf, buflen, "POLY1305 - Feature not available. For example, s part of the API is not implemented" );
|
||||
if( use_ret == -(MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED) )
|
||||
mbedtls_snprintf( buf, buflen, "POLY1305 - Poly1305 hardware accelerator failed" );
|
||||
#endif /* MBEDTLS_POLY1305_C */
|
||||
|
||||
#if defined(MBEDTLS_RIPEMD160_C)
|
||||
if( use_ret == -(MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED) )
|
||||
mbedtls_snprintf( buf, buflen, "RIPEMD160 - RIPEMD160 hardware accelerator failed" );
|
||||
|
||||
192
library/hkdf.c
Normal file
192
library/hkdf.c
Normal file
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* HKDF implementation -- RFC 5869
|
||||
*
|
||||
* Copyright (C) 2016-2018, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is part of mbed TLS (https://tls.mbed.org)
|
||||
*/
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_HKDF_C)
|
||||
|
||||
#include <string.h>
|
||||
#include "mbedtls/hkdf.h"
|
||||
#include "mbedtls/platform_util.h"
|
||||
|
||||
int mbedtls_hkdf( const mbedtls_md_info_t *md, const unsigned char *salt,
|
||||
size_t salt_len, const unsigned char *ikm, size_t ikm_len,
|
||||
const unsigned char *info, size_t info_len,
|
||||
unsigned char *okm, size_t okm_len )
|
||||
{
|
||||
int ret;
|
||||
unsigned char prk[MBEDTLS_MD_MAX_SIZE];
|
||||
|
||||
ret = mbedtls_hkdf_extract( md, salt, salt_len, ikm, ikm_len, prk );
|
||||
|
||||
if( ret == 0 )
|
||||
{
|
||||
ret = mbedtls_hkdf_expand( md, prk, mbedtls_md_get_size( md ),
|
||||
info, info_len, okm, okm_len );
|
||||
}
|
||||
|
||||
mbedtls_platform_zeroize( prk, sizeof( prk ) );
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
int mbedtls_hkdf_extract( const mbedtls_md_info_t *md,
|
||||
const unsigned char *salt, size_t salt_len,
|
||||
const unsigned char *ikm, size_t ikm_len,
|
||||
unsigned char *prk )
|
||||
{
|
||||
unsigned char null_salt[MBEDTLS_MD_MAX_SIZE] = { '\0' };
|
||||
|
||||
if( salt == NULL )
|
||||
{
|
||||
size_t hash_len;
|
||||
|
||||
if( salt_len != 0 )
|
||||
{
|
||||
return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
hash_len = mbedtls_md_get_size( md );
|
||||
|
||||
if( hash_len == 0 )
|
||||
{
|
||||
return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
salt = null_salt;
|
||||
salt_len = hash_len;
|
||||
}
|
||||
|
||||
return( mbedtls_md_hmac( md, salt, salt_len, ikm, ikm_len, prk ) );
|
||||
}
|
||||
|
||||
int mbedtls_hkdf_expand( const mbedtls_md_info_t *md, const unsigned char *prk,
|
||||
size_t prk_len, const unsigned char *info,
|
||||
size_t info_len, unsigned char *okm, size_t okm_len )
|
||||
{
|
||||
size_t hash_len;
|
||||
size_t where = 0;
|
||||
size_t n;
|
||||
size_t t_len = 0;
|
||||
size_t i;
|
||||
int ret = 0;
|
||||
mbedtls_md_context_t ctx;
|
||||
unsigned char t[MBEDTLS_MD_MAX_SIZE];
|
||||
|
||||
if( okm == NULL )
|
||||
{
|
||||
return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA );
|
||||
}
|
||||
|
||||
hash_len = mbedtls_md_get_size( md );
|
||||
|
||||
if( prk_len < hash_len || hash_len == 0 )
|
||||
{
|
||||
return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA );
|
||||
}
|
||||
|
||||
if( info == NULL )
|
||||
{
|
||||
info = (const unsigned char *) "";
|
||||
info_len = 0;
|
||||
}
|
||||
|
||||
n = okm_len / hash_len;
|
||||
|
||||
if( (okm_len % hash_len) != 0 )
|
||||
{
|
||||
n++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Per RFC 5869 Section 2.3, okm_len must not exceed
|
||||
* 255 times the hash length
|
||||
*/
|
||||
if( n > 255 )
|
||||
{
|
||||
return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA );
|
||||
}
|
||||
|
||||
mbedtls_md_init( &ctx );
|
||||
|
||||
if( (ret = mbedtls_md_setup( &ctx, md, 1) ) != 0 )
|
||||
{
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute T = T(1) | T(2) | T(3) | ... | T(N)
|
||||
* Where T(N) is defined in RFC 5869 Section 2.3
|
||||
*/
|
||||
for( i = 1; i <= n; i++ )
|
||||
{
|
||||
size_t num_to_copy;
|
||||
unsigned char c = i & 0xff;
|
||||
|
||||
ret = mbedtls_md_hmac_starts( &ctx, prk, prk_len );
|
||||
if( ret != 0 )
|
||||
{
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = mbedtls_md_hmac_update( &ctx, t, t_len );
|
||||
if( ret != 0 )
|
||||
{
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = mbedtls_md_hmac_update( &ctx, info, info_len );
|
||||
if( ret != 0 )
|
||||
{
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* The constant concatenated to the end of each T(n) is a single octet.
|
||||
* */
|
||||
ret = mbedtls_md_hmac_update( &ctx, &c, 1 );
|
||||
if( ret != 0 )
|
||||
{
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = mbedtls_md_hmac_finish( &ctx, t );
|
||||
if( ret != 0 )
|
||||
{
|
||||
goto exit;
|
||||
}
|
||||
|
||||
num_to_copy = i != n ? hash_len : okm_len - where;
|
||||
memcpy( okm + where, t, num_to_copy );
|
||||
where += hash_len;
|
||||
t_len = hash_len;
|
||||
}
|
||||
|
||||
exit:
|
||||
mbedtls_md_free( &ctx );
|
||||
mbedtls_platform_zeroize( t, sizeof( t ) );
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
#endif /* MBEDTLS_HKDF_C */
|
||||
@@ -309,14 +309,6 @@ void mbedtls_md5_update( mbedtls_md5_context *ctx,
|
||||
}
|
||||
#endif
|
||||
|
||||
static const unsigned char md5_padding[64] =
|
||||
{
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
/*
|
||||
* MD5 final digest
|
||||
*/
|
||||
@@ -324,26 +316,48 @@ int mbedtls_md5_finish_ret( mbedtls_md5_context *ctx,
|
||||
unsigned char output[16] )
|
||||
{
|
||||
int ret;
|
||||
uint32_t last, padn;
|
||||
uint32_t used;
|
||||
uint32_t high, low;
|
||||
unsigned char msglen[8];
|
||||
|
||||
/*
|
||||
* Add padding: 0x80 then 0x00 until 8 bytes remain for the length
|
||||
*/
|
||||
used = ctx->total[0] & 0x3F;
|
||||
|
||||
ctx->buffer[used++] = 0x80;
|
||||
|
||||
if( used <= 56 )
|
||||
{
|
||||
/* Enough room for padding + length in current block */
|
||||
memset( ctx->buffer + used, 0, 56 - used );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We'll need an extra block */
|
||||
memset( ctx->buffer + used, 0, 64 - used );
|
||||
|
||||
if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 )
|
||||
return( ret );
|
||||
|
||||
memset( ctx->buffer, 0, 56 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Add message length
|
||||
*/
|
||||
high = ( ctx->total[0] >> 29 )
|
||||
| ( ctx->total[1] << 3 );
|
||||
low = ( ctx->total[0] << 3 );
|
||||
|
||||
PUT_UINT32_LE( low, msglen, 0 );
|
||||
PUT_UINT32_LE( high, msglen, 4 );
|
||||
PUT_UINT32_LE( low, ctx->buffer, 56 );
|
||||
PUT_UINT32_LE( high, ctx->buffer, 60 );
|
||||
|
||||
last = ctx->total[0] & 0x3F;
|
||||
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
|
||||
|
||||
if( ( ret = mbedtls_md5_update_ret( ctx, md5_padding, padn ) ) != 0 )
|
||||
return( ret );
|
||||
|
||||
if( ( ret = mbedtls_md5_update_ret( ctx, msglen, 8 ) ) != 0 )
|
||||
return( ret );
|
||||
if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 )
|
||||
return( ret );
|
||||
|
||||
/*
|
||||
* Output final state
|
||||
*/
|
||||
PUT_UINT32_LE( ctx->state[0], output, 0 );
|
||||
PUT_UINT32_LE( ctx->state[1], output, 4 );
|
||||
PUT_UINT32_LE( ctx->state[2], output, 8 );
|
||||
|
||||
@@ -518,7 +518,9 @@ void mbedtls_memory_buffer_alloc_status( void )
|
||||
heap.alloc_count, heap.free_count );
|
||||
|
||||
if( heap.first->next == NULL )
|
||||
{
|
||||
mbedtls_fprintf( stderr, "All memory de-allocated in stack buffer\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
mbedtls_fprintf( stderr, "Memory currently allocated:\n" );
|
||||
|
||||
@@ -19,6 +19,11 @@
|
||||
* This file is part of mbed TLS (https://tls.mbed.org)
|
||||
*/
|
||||
|
||||
/* Enable definition of getaddrinfo() even when compiling with -std=c99. Must
|
||||
* be set before config.h, which pulls in glibc's features.h indirectly.
|
||||
* Harmless on other platforms. */
|
||||
#define _POSIX_C_SOURCE 200112L
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
@@ -28,7 +33,8 @@
|
||||
#if defined(MBEDTLS_NET_C)
|
||||
|
||||
#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \
|
||||
!defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__)
|
||||
!defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \
|
||||
!defined(__HAIKU__)
|
||||
#error "This module only works on Unix and Windows, see MBEDTLS_NET_C in config.h"
|
||||
#endif
|
||||
|
||||
@@ -47,11 +53,12 @@
|
||||
|
||||
#define IS_EINTR( ret ) ( ( ret ) == WSAEINTR )
|
||||
|
||||
#ifdef _WIN32_WINNT
|
||||
#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0501)
|
||||
#undef _WIN32_WINNT
|
||||
#endif
|
||||
/* Enables getaddrinfo() & Co */
|
||||
#define _WIN32_WINNT 0x0501
|
||||
#endif
|
||||
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
#include <winsock2.h>
|
||||
|
||||
755
library/nist_kw.c
Normal file
755
library/nist_kw.c
Normal file
@@ -0,0 +1,755 @@
|
||||
/*
|
||||
* Implementation of NIST SP 800-38F key wrapping, supporting KW and KWP modes
|
||||
* only
|
||||
*
|
||||
* Copyright (C) 2018, Arm Limited (or its affiliates), All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is part of Mbed TLS (https://tls.mbed.org)
|
||||
*/
|
||||
/*
|
||||
* Definition of Key Wrapping:
|
||||
* https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf
|
||||
* RFC 3394 "Advanced Encryption Standard (AES) Key Wrap Algorithm"
|
||||
* RFC 5649 "Advanced Encryption Standard (AES) Key Wrap with Padding Algorithm"
|
||||
*
|
||||
* Note: RFC 3394 defines different methodology for intermediate operations for
|
||||
* the wrapping and unwrapping operation than the definition in NIST SP 800-38F.
|
||||
*/
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_NIST_KW_C)
|
||||
|
||||
#include "mbedtls/nist_kw.h"
|
||||
#include "mbedtls/platform_util.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
|
||||
#if defined(MBEDTLS_PLATFORM_C)
|
||||
#include "mbedtls/platform.h"
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#define mbedtls_printf printf
|
||||
#endif /* MBEDTLS_PLATFORM_C */
|
||||
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
|
||||
|
||||
#if !defined(MBEDTLS_NIST_KW_ALT)
|
||||
|
||||
#define KW_SEMIBLOCK_LENGTH 8
|
||||
#define MIN_SEMIBLOCKS_COUNT 3
|
||||
|
||||
/* constant-time buffer comparison */
|
||||
static inline unsigned char mbedtls_nist_kw_safer_memcmp( const void *a, const void *b, size_t n )
|
||||
{
|
||||
size_t i;
|
||||
volatile const unsigned char *A = (volatile const unsigned char *) a;
|
||||
volatile const unsigned char *B = (volatile const unsigned char *) b;
|
||||
volatile unsigned char diff = 0;
|
||||
|
||||
for( i = 0; i < n; i++ )
|
||||
{
|
||||
/* Read volatile data in order before computing diff.
|
||||
* This avoids IAR compiler warning:
|
||||
* 'the order of volatile accesses is undefined ..' */
|
||||
unsigned char x = A[i], y = B[i];
|
||||
diff |= x ^ y;
|
||||
}
|
||||
|
||||
return( diff );
|
||||
}
|
||||
|
||||
/*! The 64-bit default integrity check value (ICV) for KW mode. */
|
||||
static const unsigned char NIST_KW_ICV1[] = {0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6};
|
||||
/*! The 32-bit default integrity check value (ICV) for KWP mode. */
|
||||
static const unsigned char NIST_KW_ICV2[] = {0xA6, 0x59, 0x59, 0xA6};
|
||||
|
||||
#ifndef GET_UINT32_BE
|
||||
#define GET_UINT32_BE(n,b,i) \
|
||||
do { \
|
||||
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \
|
||||
| ( (uint32_t) (b)[(i) + 1] << 16 ) \
|
||||
| ( (uint32_t) (b)[(i) + 2] << 8 ) \
|
||||
| ( (uint32_t) (b)[(i) + 3] ); \
|
||||
} while( 0 )
|
||||
#endif
|
||||
|
||||
#ifndef PUT_UINT32_BE
|
||||
#define PUT_UINT32_BE(n,b,i) \
|
||||
do { \
|
||||
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
|
||||
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
|
||||
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
|
||||
(b)[(i) + 3] = (unsigned char) ( (n) ); \
|
||||
} while( 0 )
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Initialize context
|
||||
*/
|
||||
void mbedtls_nist_kw_init( mbedtls_nist_kw_context *ctx )
|
||||
{
|
||||
memset( ctx, 0, sizeof( mbedtls_nist_kw_context ) );
|
||||
}
|
||||
|
||||
int mbedtls_nist_kw_setkey( mbedtls_nist_kw_context *ctx,
|
||||
mbedtls_cipher_id_t cipher,
|
||||
const unsigned char *key,
|
||||
unsigned int keybits,
|
||||
const int is_wrap )
|
||||
{
|
||||
int ret;
|
||||
const mbedtls_cipher_info_t *cipher_info;
|
||||
|
||||
cipher_info = mbedtls_cipher_info_from_values( cipher,
|
||||
keybits,
|
||||
MBEDTLS_MODE_ECB );
|
||||
if( cipher_info == NULL )
|
||||
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
|
||||
|
||||
if( cipher_info->block_size != 16 )
|
||||
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
|
||||
|
||||
/*
|
||||
* SP 800-38F currently defines AES cipher as the only block cipher allowed:
|
||||
* "For KW and KWP, the underlying block cipher shall be approved, and the
|
||||
* block size shall be 128 bits. Currently, the AES block cipher, with key
|
||||
* lengths of 128, 192, or 256 bits, is the only block cipher that fits
|
||||
* this profile."
|
||||
* Currently we don't support other 128 bit block ciphers for key wrapping,
|
||||
* such as Camellia and Aria.
|
||||
*/
|
||||
if( cipher != MBEDTLS_CIPHER_ID_AES )
|
||||
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
|
||||
|
||||
mbedtls_cipher_free( &ctx->cipher_ctx );
|
||||
|
||||
if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 )
|
||||
return( ret );
|
||||
|
||||
if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits,
|
||||
is_wrap ? MBEDTLS_ENCRYPT :
|
||||
MBEDTLS_DECRYPT )
|
||||
) != 0 )
|
||||
{
|
||||
return( ret );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Free context
|
||||
*/
|
||||
void mbedtls_nist_kw_free( mbedtls_nist_kw_context *ctx )
|
||||
{
|
||||
mbedtls_cipher_free( &ctx->cipher_ctx );
|
||||
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_nist_kw_context ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function for Xoring the uint64_t "t" with the encrypted A.
|
||||
* Defined in NIST SP 800-38F section 6.1
|
||||
*/
|
||||
static void calc_a_xor_t( unsigned char A[KW_SEMIBLOCK_LENGTH], uint64_t t )
|
||||
{
|
||||
size_t i = 0;
|
||||
for( i = 0; i < sizeof( t ); i++ )
|
||||
{
|
||||
A[i] ^= ( t >> ( ( sizeof( t ) - 1 - i ) * 8 ) ) & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* KW-AE as defined in SP 800-38F section 6.2
|
||||
* KWP-AE as defined in SP 800-38F section 6.3
|
||||
*/
|
||||
int mbedtls_nist_kw_wrap( mbedtls_nist_kw_context *ctx,
|
||||
mbedtls_nist_kw_mode_t mode,
|
||||
const unsigned char *input, size_t in_len,
|
||||
unsigned char *output, size_t *out_len, size_t out_size )
|
||||
{
|
||||
int ret = 0;
|
||||
size_t semiblocks = 0;
|
||||
size_t s;
|
||||
size_t olen, padlen = 0;
|
||||
uint64_t t = 0;
|
||||
unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
|
||||
unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
|
||||
unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH;
|
||||
unsigned char *A = output;
|
||||
|
||||
*out_len = 0;
|
||||
/*
|
||||
* Generate the String to work on
|
||||
*/
|
||||
if( mode == MBEDTLS_KW_MODE_KW )
|
||||
{
|
||||
if( out_size < in_len + KW_SEMIBLOCK_LENGTH )
|
||||
{
|
||||
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
|
||||
}
|
||||
|
||||
/*
|
||||
* According to SP 800-38F Table 1, the plaintext length for KW
|
||||
* must be between 2 to 2^54-1 semiblocks inclusive.
|
||||
*/
|
||||
if( in_len < 16 ||
|
||||
#if SIZE_MAX > 0x1FFFFFFFFFFFFF8
|
||||
in_len > 0x1FFFFFFFFFFFFF8 ||
|
||||
#endif
|
||||
in_len % KW_SEMIBLOCK_LENGTH != 0 )
|
||||
{
|
||||
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
|
||||
}
|
||||
|
||||
memcpy( output, NIST_KW_ICV1, KW_SEMIBLOCK_LENGTH );
|
||||
memmove( output + KW_SEMIBLOCK_LENGTH, input, in_len );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( in_len % 8 != 0 )
|
||||
{
|
||||
padlen = ( 8 - ( in_len % 8 ) );
|
||||
}
|
||||
|
||||
if( out_size < in_len + KW_SEMIBLOCK_LENGTH + padlen )
|
||||
{
|
||||
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
|
||||
}
|
||||
|
||||
/*
|
||||
* According to SP 800-38F Table 1, the plaintext length for KWP
|
||||
* must be between 1 and 2^32-1 octets inclusive.
|
||||
*/
|
||||
if( in_len < 1
|
||||
#if SIZE_MAX > 0xFFFFFFFF
|
||||
|| in_len > 0xFFFFFFFF
|
||||
#endif
|
||||
)
|
||||
{
|
||||
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
|
||||
}
|
||||
|
||||
memcpy( output, NIST_KW_ICV2, KW_SEMIBLOCK_LENGTH / 2 );
|
||||
PUT_UINT32_BE( ( in_len & 0xffffffff ), output,
|
||||
KW_SEMIBLOCK_LENGTH / 2 );
|
||||
|
||||
memcpy( output + KW_SEMIBLOCK_LENGTH, input, in_len );
|
||||
memset( output + KW_SEMIBLOCK_LENGTH + in_len, 0, padlen );
|
||||
}
|
||||
semiblocks = ( ( in_len + padlen ) / KW_SEMIBLOCK_LENGTH ) + 1;
|
||||
|
||||
s = 6 * ( semiblocks - 1 );
|
||||
|
||||
if( mode == MBEDTLS_KW_MODE_KWP
|
||||
&& in_len <= KW_SEMIBLOCK_LENGTH )
|
||||
{
|
||||
memcpy( inbuff, output, 16 );
|
||||
ret = mbedtls_cipher_update( &ctx->cipher_ctx,
|
||||
inbuff, 16, output, &olen );
|
||||
if( ret != 0 )
|
||||
goto cleanup;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Do the wrapping function W, as defined in RFC 3394 section 2.2.1
|
||||
*/
|
||||
if( semiblocks < MIN_SEMIBLOCKS_COUNT )
|
||||
{
|
||||
ret = MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Calculate intermediate values */
|
||||
for( t = 1; t <= s; t++ )
|
||||
{
|
||||
memcpy( inbuff, A, KW_SEMIBLOCK_LENGTH );
|
||||
memcpy( inbuff + KW_SEMIBLOCK_LENGTH, R2, KW_SEMIBLOCK_LENGTH );
|
||||
|
||||
ret = mbedtls_cipher_update( &ctx->cipher_ctx,
|
||||
inbuff, 16, outbuff, &olen );
|
||||
if( ret != 0 )
|
||||
goto cleanup;
|
||||
|
||||
memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH );
|
||||
calc_a_xor_t( A, t );
|
||||
|
||||
memcpy( R2, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH );
|
||||
R2 += KW_SEMIBLOCK_LENGTH;
|
||||
if( R2 >= output + ( semiblocks * KW_SEMIBLOCK_LENGTH ) )
|
||||
R2 = output + KW_SEMIBLOCK_LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
*out_len = semiblocks * KW_SEMIBLOCK_LENGTH;
|
||||
|
||||
cleanup:
|
||||
|
||||
if( ret != 0)
|
||||
{
|
||||
memset( output, 0, semiblocks * KW_SEMIBLOCK_LENGTH );
|
||||
}
|
||||
mbedtls_platform_zeroize( inbuff, KW_SEMIBLOCK_LENGTH * 2 );
|
||||
mbedtls_platform_zeroize( outbuff, KW_SEMIBLOCK_LENGTH * 2 );
|
||||
mbedtls_cipher_finish( &ctx->cipher_ctx, NULL, &olen );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
/*
|
||||
* W-1 function as defined in RFC 3394 section 2.2.2
|
||||
* This function assumes the following:
|
||||
* 1. Output buffer is at least of size ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH.
|
||||
* 2. The input buffer is of size semiblocks * KW_SEMIBLOCK_LENGTH.
|
||||
* 3. Minimal number of semiblocks is 3.
|
||||
* 4. A is a buffer to hold the first semiblock of the input buffer.
|
||||
*/
|
||||
static int unwrap( mbedtls_nist_kw_context *ctx,
|
||||
const unsigned char *input, size_t semiblocks,
|
||||
unsigned char A[KW_SEMIBLOCK_LENGTH],
|
||||
unsigned char *output, size_t* out_len )
|
||||
{
|
||||
int ret = 0;
|
||||
const size_t s = 6 * ( semiblocks - 1 );
|
||||
size_t olen;
|
||||
uint64_t t = 0;
|
||||
unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
|
||||
unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
|
||||
unsigned char *R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH;
|
||||
*out_len = 0;
|
||||
|
||||
if( semiblocks < MIN_SEMIBLOCKS_COUNT )
|
||||
{
|
||||
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
|
||||
}
|
||||
|
||||
memcpy( A, input, KW_SEMIBLOCK_LENGTH );
|
||||
memmove( output, input + KW_SEMIBLOCK_LENGTH, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH );
|
||||
|
||||
/* Calculate intermediate values */
|
||||
for( t = s; t >= 1; t-- )
|
||||
{
|
||||
calc_a_xor_t( A, t );
|
||||
|
||||
memcpy( inbuff, A, KW_SEMIBLOCK_LENGTH );
|
||||
memcpy( inbuff + KW_SEMIBLOCK_LENGTH, R, KW_SEMIBLOCK_LENGTH );
|
||||
|
||||
ret = mbedtls_cipher_update( &ctx->cipher_ctx,
|
||||
inbuff, 16, outbuff, &olen );
|
||||
if( ret != 0 )
|
||||
goto cleanup;
|
||||
|
||||
memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH );
|
||||
|
||||
/* Set R as LSB64 of outbuff */
|
||||
memcpy( R, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH );
|
||||
|
||||
if( R == output )
|
||||
R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH;
|
||||
else
|
||||
R -= KW_SEMIBLOCK_LENGTH;
|
||||
}
|
||||
|
||||
*out_len = ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH;
|
||||
|
||||
cleanup:
|
||||
if( ret != 0)
|
||||
memset( output, 0, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH );
|
||||
mbedtls_platform_zeroize( inbuff, sizeof( inbuff ) );
|
||||
mbedtls_platform_zeroize( outbuff, sizeof( outbuff ) );
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
/*
|
||||
* KW-AD as defined in SP 800-38F section 6.2
|
||||
* KWP-AD as defined in SP 800-38F section 6.3
|
||||
*/
|
||||
int mbedtls_nist_kw_unwrap( mbedtls_nist_kw_context *ctx,
|
||||
mbedtls_nist_kw_mode_t mode,
|
||||
const unsigned char *input, size_t in_len,
|
||||
unsigned char *output, size_t *out_len, size_t out_size )
|
||||
{
|
||||
int ret = 0;
|
||||
size_t i, olen;
|
||||
unsigned char A[KW_SEMIBLOCK_LENGTH];
|
||||
unsigned char diff, bad_padding = 0;
|
||||
|
||||
*out_len = 0;
|
||||
if( out_size < in_len - KW_SEMIBLOCK_LENGTH )
|
||||
{
|
||||
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
|
||||
}
|
||||
|
||||
if( mode == MBEDTLS_KW_MODE_KW )
|
||||
{
|
||||
/*
|
||||
* According to SP 800-38F Table 1, the ciphertext length for KW
|
||||
* must be between 3 to 2^54 semiblocks inclusive.
|
||||
*/
|
||||
if( in_len < 24 ||
|
||||
#if SIZE_MAX > 0x200000000000000
|
||||
in_len > 0x200000000000000 ||
|
||||
#endif
|
||||
in_len % KW_SEMIBLOCK_LENGTH != 0 )
|
||||
{
|
||||
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
|
||||
}
|
||||
|
||||
ret = unwrap( ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
|
||||
A, output, out_len );
|
||||
if( ret != 0 )
|
||||
goto cleanup;
|
||||
|
||||
/* Check ICV in "constant-time" */
|
||||
diff = mbedtls_nist_kw_safer_memcmp( NIST_KW_ICV1, A, KW_SEMIBLOCK_LENGTH );
|
||||
|
||||
if( diff != 0 )
|
||||
{
|
||||
ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
}
|
||||
else if( mode == MBEDTLS_KW_MODE_KWP )
|
||||
{
|
||||
size_t padlen = 0;
|
||||
uint32_t Plen;
|
||||
/*
|
||||
* According to SP 800-38F Table 1, the ciphertext length for KWP
|
||||
* must be between 2 to 2^29 semiblocks inclusive.
|
||||
*/
|
||||
if( in_len < KW_SEMIBLOCK_LENGTH * 2 ||
|
||||
#if SIZE_MAX > 0x100000000
|
||||
in_len > 0x100000000 ||
|
||||
#endif
|
||||
in_len % KW_SEMIBLOCK_LENGTH != 0 )
|
||||
{
|
||||
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
|
||||
}
|
||||
|
||||
if( in_len == KW_SEMIBLOCK_LENGTH * 2 )
|
||||
{
|
||||
unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
|
||||
ret = mbedtls_cipher_update( &ctx->cipher_ctx,
|
||||
input, 16, outbuff, &olen );
|
||||
if( ret != 0 )
|
||||
goto cleanup;
|
||||
|
||||
memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH );
|
||||
memcpy( output, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH );
|
||||
mbedtls_platform_zeroize( outbuff, sizeof( outbuff ) );
|
||||
*out_len = KW_SEMIBLOCK_LENGTH;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* in_len >= KW_SEMIBLOCK_LENGTH * 3 */
|
||||
ret = unwrap( ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
|
||||
A, output, out_len );
|
||||
if( ret != 0 )
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Check ICV in "constant-time" */
|
||||
diff = mbedtls_nist_kw_safer_memcmp( NIST_KW_ICV2, A, KW_SEMIBLOCK_LENGTH / 2 );
|
||||
|
||||
if( diff != 0 )
|
||||
{
|
||||
ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
|
||||
}
|
||||
|
||||
GET_UINT32_BE( Plen, A, KW_SEMIBLOCK_LENGTH / 2 );
|
||||
|
||||
/*
|
||||
* Plen is the length of the plaintext, when the input is valid.
|
||||
* If Plen is larger than the plaintext and padding, padlen will be
|
||||
* larger than 8, because of the type wrap around.
|
||||
*/
|
||||
padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen;
|
||||
if ( padlen > 7 )
|
||||
{
|
||||
padlen &= 7;
|
||||
ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
|
||||
}
|
||||
|
||||
/* Check padding in "constant-time" */
|
||||
for( diff = 0, i = 0; i < KW_SEMIBLOCK_LENGTH; i++ )
|
||||
{
|
||||
if( i >= KW_SEMIBLOCK_LENGTH - padlen )
|
||||
diff |= output[*out_len - KW_SEMIBLOCK_LENGTH + i];
|
||||
else
|
||||
bad_padding |= output[*out_len - KW_SEMIBLOCK_LENGTH + i];
|
||||
}
|
||||
|
||||
if( diff != 0 )
|
||||
{
|
||||
ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
|
||||
}
|
||||
|
||||
if( ret != 0 )
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
memset( output + Plen, 0, padlen );
|
||||
*out_len = Plen;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if( ret != 0 )
|
||||
{
|
||||
memset( output, 0, *out_len );
|
||||
*out_len = 0;
|
||||
}
|
||||
|
||||
mbedtls_platform_zeroize( &bad_padding, sizeof( bad_padding) );
|
||||
mbedtls_platform_zeroize( &diff, sizeof( diff ) );
|
||||
mbedtls_platform_zeroize( A, sizeof( A ) );
|
||||
mbedtls_cipher_finish( &ctx->cipher_ctx, NULL, &olen );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
#endif /* !MBEDTLS_NIST_KW_ALT */
|
||||
|
||||
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
|
||||
|
||||
#define KW_TESTS 3
|
||||
|
||||
/*
|
||||
* Test vectors taken from NIST
|
||||
* https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES#KW
|
||||
*/
|
||||
static const unsigned int key_len[KW_TESTS] = { 16, 24, 32 };
|
||||
|
||||
static const unsigned char kw_key[KW_TESTS][32] = {
|
||||
{ 0x75, 0x75, 0xda, 0x3a, 0x93, 0x60, 0x7c, 0xc2,
|
||||
0xbf, 0xd8, 0xce, 0xc7, 0xaa, 0xdf, 0xd9, 0xa6 },
|
||||
{ 0x2d, 0x85, 0x26, 0x08, 0x1d, 0x02, 0xfb, 0x5b,
|
||||
0x85, 0xf6, 0x9a, 0xc2, 0x86, 0xec, 0xd5, 0x7d,
|
||||
0x40, 0xdf, 0x5d, 0xf3, 0x49, 0x47, 0x44, 0xd3 },
|
||||
{ 0x11, 0x2a, 0xd4, 0x1b, 0x48, 0x56, 0xc7, 0x25,
|
||||
0x4a, 0x98, 0x48, 0xd3, 0x0f, 0xdd, 0x78, 0x33,
|
||||
0x5b, 0x03, 0x9a, 0x48, 0xa8, 0x96, 0x2c, 0x4d,
|
||||
0x1c, 0xb7, 0x8e, 0xab, 0xd5, 0xda, 0xd7, 0x88 }
|
||||
};
|
||||
|
||||
static const unsigned char kw_msg[KW_TESTS][40] = {
|
||||
{ 0x42, 0x13, 0x6d, 0x3c, 0x38, 0x4a, 0x3e, 0xea,
|
||||
0xc9, 0x5a, 0x06, 0x6f, 0xd2, 0x8f, 0xed, 0x3f },
|
||||
{ 0x95, 0xc1, 0x1b, 0xf5, 0x35, 0x3a, 0xfe, 0xdb,
|
||||
0x98, 0xfd, 0xd6, 0xc8, 0xca, 0x6f, 0xdb, 0x6d,
|
||||
0xa5, 0x4b, 0x74, 0xb4, 0x99, 0x0f, 0xdc, 0x45,
|
||||
0xc0, 0x9d, 0x15, 0x8f, 0x51, 0xce, 0x62, 0x9d,
|
||||
0xe2, 0xaf, 0x26, 0xe3, 0x25, 0x0e, 0x6b, 0x4c },
|
||||
{ 0x1b, 0x20, 0xbf, 0x19, 0x90, 0xb0, 0x65, 0xd7,
|
||||
0x98, 0xe1, 0xb3, 0x22, 0x64, 0xad, 0x50, 0xa8,
|
||||
0x74, 0x74, 0x92, 0xba, 0x09, 0xa0, 0x4d, 0xd1 }
|
||||
};
|
||||
|
||||
static const size_t kw_msg_len[KW_TESTS] = { 16, 40, 24 };
|
||||
static const size_t kw_out_len[KW_TESTS] = { 24, 48, 32 };
|
||||
static const unsigned char kw_res[KW_TESTS][48] = {
|
||||
{ 0x03, 0x1f, 0x6b, 0xd7, 0xe6, 0x1e, 0x64, 0x3d,
|
||||
0xf6, 0x85, 0x94, 0x81, 0x6f, 0x64, 0xca, 0xa3,
|
||||
0xf5, 0x6f, 0xab, 0xea, 0x25, 0x48, 0xf5, 0xfb },
|
||||
{ 0x44, 0x3c, 0x6f, 0x15, 0x09, 0x83, 0x71, 0x91,
|
||||
0x3e, 0x5c, 0x81, 0x4c, 0xa1, 0xa0, 0x42, 0xec,
|
||||
0x68, 0x2f, 0x7b, 0x13, 0x6d, 0x24, 0x3a, 0x4d,
|
||||
0x6c, 0x42, 0x6f, 0xc6, 0x97, 0x15, 0x63, 0xe8,
|
||||
0xa1, 0x4a, 0x55, 0x8e, 0x09, 0x64, 0x16, 0x19,
|
||||
0xbf, 0x03, 0xfc, 0xaf, 0x90, 0xb1, 0xfc, 0x2d },
|
||||
{ 0xba, 0x8a, 0x25, 0x9a, 0x47, 0x1b, 0x78, 0x7d,
|
||||
0xd5, 0xd5, 0x40, 0xec, 0x25, 0xd4, 0x3d, 0x87,
|
||||
0x20, 0x0f, 0xda, 0xdc, 0x6d, 0x1f, 0x05, 0xd9,
|
||||
0x16, 0x58, 0x4f, 0xa9, 0xf6, 0xcb, 0xf5, 0x12 }
|
||||
};
|
||||
|
||||
static const unsigned char kwp_key[KW_TESTS][32] = {
|
||||
{ 0x78, 0x65, 0xe2, 0x0f, 0x3c, 0x21, 0x65, 0x9a,
|
||||
0xb4, 0x69, 0x0b, 0x62, 0x9c, 0xdf, 0x3c, 0xc4 },
|
||||
{ 0xf5, 0xf8, 0x96, 0xa3, 0xbd, 0x2f, 0x4a, 0x98,
|
||||
0x23, 0xef, 0x16, 0x2b, 0x00, 0xb8, 0x05, 0xd7,
|
||||
0xde, 0x1e, 0xa4, 0x66, 0x26, 0x96, 0xa2, 0x58 },
|
||||
{ 0x95, 0xda, 0x27, 0x00, 0xca, 0x6f, 0xd9, 0xa5,
|
||||
0x25, 0x54, 0xee, 0x2a, 0x8d, 0xf1, 0x38, 0x6f,
|
||||
0x5b, 0x94, 0xa1, 0xa6, 0x0e, 0xd8, 0xa4, 0xae,
|
||||
0xf6, 0x0a, 0x8d, 0x61, 0xab, 0x5f, 0x22, 0x5a }
|
||||
};
|
||||
|
||||
static const unsigned char kwp_msg[KW_TESTS][31] = {
|
||||
{ 0xbd, 0x68, 0x43, 0xd4, 0x20, 0x37, 0x8d, 0xc8,
|
||||
0x96 },
|
||||
{ 0x6c, 0xcd, 0xd5, 0x85, 0x18, 0x40, 0x97, 0xeb,
|
||||
0xd5, 0xc3, 0xaf, 0x3e, 0x47, 0xd0, 0x2c, 0x19,
|
||||
0x14, 0x7b, 0x4d, 0x99, 0x5f, 0x96, 0x43, 0x66,
|
||||
0x91, 0x56, 0x75, 0x8c, 0x13, 0x16, 0x8f },
|
||||
{ 0xd1 }
|
||||
};
|
||||
static const size_t kwp_msg_len[KW_TESTS] = { 9, 31, 1 };
|
||||
|
||||
static const unsigned char kwp_res[KW_TESTS][48] = {
|
||||
{ 0x41, 0xec, 0xa9, 0x56, 0xd4, 0xaa, 0x04, 0x7e,
|
||||
0xb5, 0xcf, 0x4e, 0xfe, 0x65, 0x96, 0x61, 0xe7,
|
||||
0x4d, 0xb6, 0xf8, 0xc5, 0x64, 0xe2, 0x35, 0x00 },
|
||||
{ 0x4e, 0x9b, 0xc2, 0xbc, 0xbc, 0x6c, 0x1e, 0x13,
|
||||
0xd3, 0x35, 0xbc, 0xc0, 0xf7, 0x73, 0x6a, 0x88,
|
||||
0xfa, 0x87, 0x53, 0x66, 0x15, 0xbb, 0x8e, 0x63,
|
||||
0x8b, 0xcc, 0x81, 0x66, 0x84, 0x68, 0x17, 0x90,
|
||||
0x67, 0xcf, 0xa9, 0x8a, 0x9d, 0x0e, 0x33, 0x26 },
|
||||
{ 0x06, 0xba, 0x7a, 0xe6, 0xf3, 0x24, 0x8c, 0xfd,
|
||||
0xcf, 0x26, 0x75, 0x07, 0xfa, 0x00, 0x1b, 0xc4 }
|
||||
};
|
||||
static const size_t kwp_out_len[KW_TESTS] = { 24, 40, 16 };
|
||||
|
||||
int mbedtls_nist_kw_self_test( int verbose )
|
||||
{
|
||||
mbedtls_nist_kw_context ctx;
|
||||
unsigned char out[48];
|
||||
size_t olen;
|
||||
int i;
|
||||
int ret = 0;
|
||||
mbedtls_nist_kw_init( &ctx );
|
||||
|
||||
for( i = 0; i < KW_TESTS; i++ )
|
||||
{
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( " KW-AES-%u ", (unsigned int) key_len[i] * 8 );
|
||||
|
||||
ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES,
|
||||
kw_key[i], key_len[i] * 8, 1 );
|
||||
if( ret != 0 )
|
||||
{
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( " KW: setup failed " );
|
||||
|
||||
goto end;
|
||||
}
|
||||
|
||||
ret = mbedtls_nist_kw_wrap( &ctx, MBEDTLS_KW_MODE_KW, kw_msg[i],
|
||||
kw_msg_len[i], out, &olen, sizeof( out ) );
|
||||
if( ret != 0 || kw_out_len[i] != olen ||
|
||||
memcmp( out, kw_res[i], kw_out_len[i] ) != 0 )
|
||||
{
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( "failed. ");
|
||||
|
||||
ret = 1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if( ( ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES,
|
||||
kw_key[i], key_len[i] * 8, 0 ) )
|
||||
!= 0 )
|
||||
{
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( " KW: setup failed ");
|
||||
|
||||
goto end;
|
||||
}
|
||||
|
||||
ret = mbedtls_nist_kw_unwrap( &ctx, MBEDTLS_KW_MODE_KW,
|
||||
out, olen, out, &olen, sizeof( out ) );
|
||||
|
||||
if( ret != 0 || olen != kw_msg_len[i] ||
|
||||
memcmp( out, kw_msg[i], kw_msg_len[i] ) != 0 )
|
||||
{
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( "failed\n" );
|
||||
|
||||
ret = 1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( " passed\n" );
|
||||
}
|
||||
|
||||
for( i = 0; i < KW_TESTS; i++ )
|
||||
{
|
||||
olen = sizeof( out );
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( " KWP-AES-%u ", (unsigned int) key_len[i] * 8 );
|
||||
|
||||
ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i],
|
||||
key_len[i] * 8, 1 );
|
||||
if( ret != 0 )
|
||||
{
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( " KWP: setup failed " );
|
||||
|
||||
goto end;
|
||||
}
|
||||
ret = mbedtls_nist_kw_wrap( &ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i],
|
||||
kwp_msg_len[i], out, &olen, sizeof( out ) );
|
||||
|
||||
if( ret != 0 || kwp_out_len[i] != olen ||
|
||||
memcmp( out, kwp_res[i], kwp_out_len[i] ) != 0 )
|
||||
{
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( "failed. ");
|
||||
|
||||
ret = 1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if( ( ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES,
|
||||
kwp_key[i], key_len[i] * 8, 0 ) )
|
||||
!= 0 )
|
||||
{
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( " KWP: setup failed ");
|
||||
|
||||
goto end;
|
||||
}
|
||||
|
||||
ret = mbedtls_nist_kw_unwrap( &ctx, MBEDTLS_KW_MODE_KWP, out,
|
||||
olen, out, &olen, sizeof( out ) );
|
||||
|
||||
if( ret != 0 || olen != kwp_msg_len[i] ||
|
||||
memcmp( out, kwp_msg[i], kwp_msg_len[i] ) != 0 )
|
||||
{
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( "failed. ");
|
||||
|
||||
ret = 1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( " passed\n" );
|
||||
}
|
||||
end:
|
||||
mbedtls_nist_kw_free( &ctx );
|
||||
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( "\n" );
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
|
||||
|
||||
#endif /* MBEDTLS_NIST_KW_C */
|
||||
161
library/pk.c
161
library/pk.c
@@ -69,6 +69,34 @@ void mbedtls_pk_free( mbedtls_pk_context *ctx )
|
||||
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_pk_context ) );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
/*
|
||||
* Initialize a restart context
|
||||
*/
|
||||
void mbedtls_pk_restart_init( mbedtls_pk_restart_ctx *ctx )
|
||||
{
|
||||
ctx->pk_info = NULL;
|
||||
ctx->rs_ctx = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free the components of a restart context
|
||||
*/
|
||||
void mbedtls_pk_restart_free( mbedtls_pk_restart_ctx *ctx )
|
||||
{
|
||||
if( ctx == NULL || ctx->pk_info == NULL ||
|
||||
ctx->pk_info->rs_free_func == NULL )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ctx->pk_info->rs_free_func( ctx->rs_ctx );
|
||||
|
||||
ctx->pk_info = NULL;
|
||||
ctx->rs_ctx = NULL;
|
||||
}
|
||||
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
|
||||
|
||||
/*
|
||||
* Get pk_info structure from type
|
||||
*/
|
||||
@@ -171,6 +199,73 @@ static inline int pk_hashlen_helper( mbedtls_md_type_t md_alg, size_t *hash_len
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
/*
|
||||
* Helper to set up a restart context if needed
|
||||
*/
|
||||
static int pk_restart_setup( mbedtls_pk_restart_ctx *ctx,
|
||||
const mbedtls_pk_info_t *info )
|
||||
{
|
||||
/* Don't do anything if already set up or invalid */
|
||||
if( ctx == NULL || ctx->pk_info != NULL )
|
||||
return( 0 );
|
||||
|
||||
/* Should never happen when we're called */
|
||||
if( info->rs_alloc_func == NULL || info->rs_free_func == NULL )
|
||||
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
|
||||
|
||||
if( ( ctx->rs_ctx = info->rs_alloc_func() ) == NULL )
|
||||
return( MBEDTLS_ERR_PK_ALLOC_FAILED );
|
||||
|
||||
ctx->pk_info = info;
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
|
||||
|
||||
/*
|
||||
* Verify a signature (restartable)
|
||||
*/
|
||||
int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx,
|
||||
mbedtls_md_type_t md_alg,
|
||||
const unsigned char *hash, size_t hash_len,
|
||||
const unsigned char *sig, size_t sig_len,
|
||||
mbedtls_pk_restart_ctx *rs_ctx )
|
||||
{
|
||||
if( ctx == NULL || ctx->pk_info == NULL ||
|
||||
pk_hashlen_helper( md_alg, &hash_len ) != 0 )
|
||||
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
|
||||
|
||||
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
/* optimization: use non-restartable version if restart disabled */
|
||||
if( rs_ctx != NULL &&
|
||||
mbedtls_ecp_restart_is_enabled() &&
|
||||
ctx->pk_info->verify_rs_func != NULL )
|
||||
{
|
||||
int ret;
|
||||
|
||||
if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 )
|
||||
return( ret );
|
||||
|
||||
ret = ctx->pk_info->verify_rs_func( ctx->pk_ctx,
|
||||
md_alg, hash, hash_len, sig, sig_len, rs_ctx->rs_ctx );
|
||||
|
||||
if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
|
||||
mbedtls_pk_restart_free( rs_ctx );
|
||||
|
||||
return( ret );
|
||||
}
|
||||
#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
|
||||
(void) rs_ctx;
|
||||
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
|
||||
|
||||
if( ctx->pk_info->verify_func == NULL )
|
||||
return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
|
||||
|
||||
return( ctx->pk_info->verify_func( ctx->pk_ctx, md_alg, hash, hash_len,
|
||||
sig, sig_len ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify a signature
|
||||
*/
|
||||
@@ -178,15 +273,8 @@ int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
|
||||
const unsigned char *hash, size_t hash_len,
|
||||
const unsigned char *sig, size_t sig_len )
|
||||
{
|
||||
if( ctx == NULL || ctx->pk_info == NULL ||
|
||||
pk_hashlen_helper( md_alg, &hash_len ) != 0 )
|
||||
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
|
||||
|
||||
if( ctx->pk_info->verify_func == NULL )
|
||||
return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
|
||||
|
||||
return( ctx->pk_info->verify_func( ctx->pk_ctx, md_alg, hash, hash_len,
|
||||
sig, sig_len ) );
|
||||
return( mbedtls_pk_verify_restartable( ctx, md_alg, hash, hash_len,
|
||||
sig, sig_len, NULL ) );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -247,6 +335,50 @@ int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options,
|
||||
return( mbedtls_pk_verify( ctx, md_alg, hash, hash_len, sig, sig_len ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* Make a signature (restartable)
|
||||
*/
|
||||
int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx,
|
||||
mbedtls_md_type_t md_alg,
|
||||
const unsigned char *hash, size_t hash_len,
|
||||
unsigned char *sig, size_t *sig_len,
|
||||
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
|
||||
mbedtls_pk_restart_ctx *rs_ctx )
|
||||
{
|
||||
if( ctx == NULL || ctx->pk_info == NULL ||
|
||||
pk_hashlen_helper( md_alg, &hash_len ) != 0 )
|
||||
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
|
||||
|
||||
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
/* optimization: use non-restartable version if restart disabled */
|
||||
if( rs_ctx != NULL &&
|
||||
mbedtls_ecp_restart_is_enabled() &&
|
||||
ctx->pk_info->sign_rs_func != NULL )
|
||||
{
|
||||
int ret;
|
||||
|
||||
if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 )
|
||||
return( ret );
|
||||
|
||||
ret = ctx->pk_info->sign_rs_func( ctx->pk_ctx, md_alg,
|
||||
hash, hash_len, sig, sig_len, f_rng, p_rng, rs_ctx->rs_ctx );
|
||||
|
||||
if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
|
||||
mbedtls_pk_restart_free( rs_ctx );
|
||||
|
||||
return( ret );
|
||||
}
|
||||
#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
|
||||
(void) rs_ctx;
|
||||
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
|
||||
|
||||
if( ctx->pk_info->sign_func == NULL )
|
||||
return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
|
||||
|
||||
return( ctx->pk_info->sign_func( ctx->pk_ctx, md_alg, hash, hash_len,
|
||||
sig, sig_len, f_rng, p_rng ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* Make a signature
|
||||
*/
|
||||
@@ -255,15 +387,8 @@ int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
|
||||
unsigned char *sig, size_t *sig_len,
|
||||
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
|
||||
{
|
||||
if( ctx == NULL || ctx->pk_info == NULL ||
|
||||
pk_hashlen_helper( md_alg, &hash_len ) != 0 )
|
||||
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
|
||||
|
||||
if( ctx->pk_info->sign_func == NULL )
|
||||
return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
|
||||
|
||||
return( ctx->pk_info->sign_func( ctx->pk_ctx, md_alg, hash, hash_len,
|
||||
sig, sig_len, f_rng, p_rng ) );
|
||||
return( mbedtls_pk_sign_restartable( ctx, md_alg, hash, hash_len,
|
||||
sig, sig_len, f_rng, p_rng, NULL ) );
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -190,11 +190,19 @@ const mbedtls_pk_info_t mbedtls_rsa_info = {
|
||||
rsa_can_do,
|
||||
rsa_verify_wrap,
|
||||
rsa_sign_wrap,
|
||||
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
NULL,
|
||||
NULL,
|
||||
#endif
|
||||
rsa_decrypt_wrap,
|
||||
rsa_encrypt_wrap,
|
||||
rsa_check_pair_wrap,
|
||||
rsa_alloc_wrap,
|
||||
rsa_free_wrap,
|
||||
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
NULL,
|
||||
NULL,
|
||||
#endif
|
||||
rsa_debug,
|
||||
};
|
||||
#endif /* MBEDTLS_RSA_C */
|
||||
@@ -262,6 +270,110 @@ static int eckey_sign_wrap( void *ctx, mbedtls_md_type_t md_alg,
|
||||
return( ret );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
/* Forward declarations */
|
||||
static int ecdsa_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
|
||||
const unsigned char *hash, size_t hash_len,
|
||||
const unsigned char *sig, size_t sig_len,
|
||||
void *rs_ctx );
|
||||
|
||||
static int ecdsa_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
|
||||
const unsigned char *hash, size_t hash_len,
|
||||
unsigned char *sig, size_t *sig_len,
|
||||
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
|
||||
void *rs_ctx );
|
||||
|
||||
/*
|
||||
* Restart context for ECDSA operations with ECKEY context
|
||||
*
|
||||
* We need to store an actual ECDSA context, as we need to pass the same to
|
||||
* the underlying ecdsa function, so we can't create it on the fly every time.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
mbedtls_ecdsa_restart_ctx ecdsa_rs;
|
||||
mbedtls_ecdsa_context ecdsa_ctx;
|
||||
} eckey_restart_ctx;
|
||||
|
||||
static void *eckey_rs_alloc( void )
|
||||
{
|
||||
eckey_restart_ctx *rs_ctx;
|
||||
|
||||
void *ctx = mbedtls_calloc( 1, sizeof( eckey_restart_ctx ) );
|
||||
|
||||
if( ctx != NULL )
|
||||
{
|
||||
rs_ctx = ctx;
|
||||
mbedtls_ecdsa_restart_init( &rs_ctx->ecdsa_rs );
|
||||
mbedtls_ecdsa_init( &rs_ctx->ecdsa_ctx );
|
||||
}
|
||||
|
||||
return( ctx );
|
||||
}
|
||||
|
||||
static void eckey_rs_free( void *ctx )
|
||||
{
|
||||
eckey_restart_ctx *rs_ctx;
|
||||
|
||||
if( ctx == NULL)
|
||||
return;
|
||||
|
||||
rs_ctx = ctx;
|
||||
mbedtls_ecdsa_restart_free( &rs_ctx->ecdsa_rs );
|
||||
mbedtls_ecdsa_free( &rs_ctx->ecdsa_ctx );
|
||||
|
||||
mbedtls_free( ctx );
|
||||
}
|
||||
|
||||
static int eckey_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
|
||||
const unsigned char *hash, size_t hash_len,
|
||||
const unsigned char *sig, size_t sig_len,
|
||||
void *rs_ctx )
|
||||
{
|
||||
int ret;
|
||||
eckey_restart_ctx *rs = rs_ctx;
|
||||
|
||||
/* Should never happen */
|
||||
if( rs == NULL )
|
||||
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
|
||||
|
||||
/* set up our own sub-context if needed (that is, on first run) */
|
||||
if( rs->ecdsa_ctx.grp.pbits == 0 )
|
||||
MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( &rs->ecdsa_ctx, ctx ) );
|
||||
|
||||
MBEDTLS_MPI_CHK( ecdsa_verify_rs_wrap( &rs->ecdsa_ctx,
|
||||
md_alg, hash, hash_len,
|
||||
sig, sig_len, &rs->ecdsa_rs ) );
|
||||
|
||||
cleanup:
|
||||
return( ret );
|
||||
}
|
||||
|
||||
static int eckey_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
|
||||
const unsigned char *hash, size_t hash_len,
|
||||
unsigned char *sig, size_t *sig_len,
|
||||
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
|
||||
void *rs_ctx )
|
||||
{
|
||||
int ret;
|
||||
eckey_restart_ctx *rs = rs_ctx;
|
||||
|
||||
/* Should never happen */
|
||||
if( rs == NULL )
|
||||
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
|
||||
|
||||
/* set up our own sub-context if needed (that is, on first run) */
|
||||
if( rs->ecdsa_ctx.grp.pbits == 0 )
|
||||
MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( &rs->ecdsa_ctx, ctx ) );
|
||||
|
||||
MBEDTLS_MPI_CHK( ecdsa_sign_rs_wrap( &rs->ecdsa_ctx, md_alg,
|
||||
hash, hash_len, sig, sig_len,
|
||||
f_rng, p_rng, &rs->ecdsa_rs ) );
|
||||
|
||||
cleanup:
|
||||
return( ret );
|
||||
}
|
||||
#endif /* MBEDTLS_ECP_RESTARTABLE */
|
||||
#endif /* MBEDTLS_ECDSA_C */
|
||||
|
||||
static int eckey_check_pair( const void *pub, const void *prv )
|
||||
@@ -301,15 +413,23 @@ const mbedtls_pk_info_t mbedtls_eckey_info = {
|
||||
#if defined(MBEDTLS_ECDSA_C)
|
||||
eckey_verify_wrap,
|
||||
eckey_sign_wrap,
|
||||
#else
|
||||
NULL,
|
||||
NULL,
|
||||
#if defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
eckey_verify_rs_wrap,
|
||||
eckey_sign_rs_wrap,
|
||||
#endif
|
||||
#else /* MBEDTLS_ECDSA_C */
|
||||
NULL,
|
||||
NULL,
|
||||
#endif /* MBEDTLS_ECDSA_C */
|
||||
NULL,
|
||||
NULL,
|
||||
eckey_check_pair,
|
||||
eckey_alloc_wrap,
|
||||
eckey_free_wrap,
|
||||
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
eckey_rs_alloc,
|
||||
eckey_rs_free,
|
||||
#endif
|
||||
eckey_debug,
|
||||
};
|
||||
|
||||
@@ -329,11 +449,19 @@ const mbedtls_pk_info_t mbedtls_eckeydh_info = {
|
||||
eckeydh_can_do,
|
||||
NULL,
|
||||
NULL,
|
||||
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
NULL,
|
||||
NULL,
|
||||
#endif
|
||||
NULL,
|
||||
NULL,
|
||||
eckey_check_pair,
|
||||
eckey_alloc_wrap, /* Same underlying key structure */
|
||||
eckey_free_wrap, /* Same underlying key structure */
|
||||
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
NULL,
|
||||
NULL,
|
||||
#endif
|
||||
eckey_debug, /* Same underlying key structure */
|
||||
};
|
||||
#endif /* MBEDTLS_ECP_C */
|
||||
@@ -369,6 +497,40 @@ static int ecdsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg,
|
||||
md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng ) );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
static int ecdsa_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
|
||||
const unsigned char *hash, size_t hash_len,
|
||||
const unsigned char *sig, size_t sig_len,
|
||||
void *rs_ctx )
|
||||
{
|
||||
int ret;
|
||||
((void) md_alg);
|
||||
|
||||
ret = mbedtls_ecdsa_read_signature_restartable(
|
||||
(mbedtls_ecdsa_context *) ctx,
|
||||
hash, hash_len, sig, sig_len,
|
||||
(mbedtls_ecdsa_restart_ctx *) rs_ctx );
|
||||
|
||||
if( ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH )
|
||||
return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH );
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
static int ecdsa_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
|
||||
const unsigned char *hash, size_t hash_len,
|
||||
unsigned char *sig, size_t *sig_len,
|
||||
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
|
||||
void *rs_ctx )
|
||||
{
|
||||
return( mbedtls_ecdsa_write_signature_restartable(
|
||||
(mbedtls_ecdsa_context *) ctx,
|
||||
md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng,
|
||||
(mbedtls_ecdsa_restart_ctx *) rs_ctx ) );
|
||||
|
||||
}
|
||||
#endif /* MBEDTLS_ECP_RESTARTABLE */
|
||||
|
||||
static void *ecdsa_alloc_wrap( void )
|
||||
{
|
||||
void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_context ) );
|
||||
@@ -385,6 +547,24 @@ static void ecdsa_free_wrap( void *ctx )
|
||||
mbedtls_free( ctx );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
static void *ecdsa_rs_alloc( void )
|
||||
{
|
||||
void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_restart_ctx ) );
|
||||
|
||||
if( ctx != NULL )
|
||||
mbedtls_ecdsa_restart_init( ctx );
|
||||
|
||||
return( ctx );
|
||||
}
|
||||
|
||||
static void ecdsa_rs_free( void *ctx )
|
||||
{
|
||||
mbedtls_ecdsa_restart_free( ctx );
|
||||
mbedtls_free( ctx );
|
||||
}
|
||||
#endif /* MBEDTLS_ECP_RESTARTABLE */
|
||||
|
||||
const mbedtls_pk_info_t mbedtls_ecdsa_info = {
|
||||
MBEDTLS_PK_ECDSA,
|
||||
"ECDSA",
|
||||
@@ -392,11 +572,19 @@ const mbedtls_pk_info_t mbedtls_ecdsa_info = {
|
||||
ecdsa_can_do,
|
||||
ecdsa_verify_wrap,
|
||||
ecdsa_sign_wrap,
|
||||
#if defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
ecdsa_verify_rs_wrap,
|
||||
ecdsa_sign_rs_wrap,
|
||||
#endif
|
||||
NULL,
|
||||
NULL,
|
||||
eckey_check_pair, /* Compatible key structures */
|
||||
ecdsa_alloc_wrap,
|
||||
ecdsa_free_wrap,
|
||||
#if defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
ecdsa_rs_alloc,
|
||||
ecdsa_rs_free,
|
||||
#endif
|
||||
eckey_debug, /* Compatible key structures */
|
||||
};
|
||||
#endif /* MBEDTLS_ECDSA_C */
|
||||
@@ -506,6 +694,10 @@ const mbedtls_pk_info_t mbedtls_rsa_alt_info = {
|
||||
rsa_alt_can_do,
|
||||
NULL,
|
||||
rsa_alt_sign_wrap,
|
||||
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
NULL,
|
||||
NULL,
|
||||
#endif
|
||||
rsa_alt_decrypt_wrap,
|
||||
NULL,
|
||||
#if defined(MBEDTLS_RSA_C)
|
||||
@@ -515,6 +707,10 @@ const mbedtls_pk_info_t mbedtls_rsa_alt_info = {
|
||||
#endif
|
||||
rsa_alt_alloc_wrap,
|
||||
rsa_alt_free_wrap,
|
||||
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
NULL,
|
||||
NULL,
|
||||
#endif
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
||||
@@ -249,8 +249,10 @@ int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx, const unsigned char *p
|
||||
memset( counter, 0, 4 );
|
||||
counter[3] = 1;
|
||||
|
||||
#if UINT_MAX > 0xFFFFFFFF
|
||||
if( iteration_count > 0xFFFFFFFF )
|
||||
return( MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA );
|
||||
#endif
|
||||
|
||||
while( key_length )
|
||||
{
|
||||
|
||||
@@ -1261,7 +1261,6 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk,
|
||||
return( ret );
|
||||
#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */
|
||||
#else
|
||||
((void) ret);
|
||||
((void) pwd);
|
||||
((void) pwdlen);
|
||||
#endif /* MBEDTLS_PEM_PARSE_C */
|
||||
|
||||
@@ -51,14 +51,24 @@ static void platform_free_uninit( void *ptr )
|
||||
#define MBEDTLS_PLATFORM_STD_FREE platform_free_uninit
|
||||
#endif /* !MBEDTLS_PLATFORM_STD_FREE */
|
||||
|
||||
void * (*mbedtls_calloc)( size_t, size_t ) = MBEDTLS_PLATFORM_STD_CALLOC;
|
||||
void (*mbedtls_free)( void * ) = MBEDTLS_PLATFORM_STD_FREE;
|
||||
static void * (*mbedtls_calloc_func)( size_t, size_t ) = MBEDTLS_PLATFORM_STD_CALLOC;
|
||||
static void (*mbedtls_free_func)( void * ) = MBEDTLS_PLATFORM_STD_FREE;
|
||||
|
||||
void * mbedtls_calloc( size_t nmemb, size_t size )
|
||||
{
|
||||
return (*mbedtls_calloc_func)( nmemb, size );
|
||||
}
|
||||
|
||||
void mbedtls_free( void * ptr )
|
||||
{
|
||||
(*mbedtls_free_func)( ptr );
|
||||
}
|
||||
|
||||
int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ),
|
||||
void (*free_func)( void * ) )
|
||||
{
|
||||
mbedtls_calloc = calloc_func;
|
||||
mbedtls_free = free_func;
|
||||
mbedtls_calloc_func = calloc_func;
|
||||
mbedtls_free_func = free_func;
|
||||
return( 0 );
|
||||
}
|
||||
#endif /* MBEDTLS_PLATFORM_MEMORY */
|
||||
|
||||
@@ -20,6 +20,14 @@
|
||||
* This file is part of Mbed TLS (https://tls.mbed.org)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Ensure gmtime_r is available even with -std=c99; must be defined before
|
||||
* config.h, which pulls in glibc's features.h. Harmless on other platforms.
|
||||
*/
|
||||
#if !defined(_POSIX_C_SOURCE)
|
||||
#define _POSIX_C_SOURCE 200112L
|
||||
#endif
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
@@ -27,6 +35,7 @@
|
||||
#endif
|
||||
|
||||
#include "mbedtls/platform_util.h"
|
||||
#include "mbedtls/threading.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
@@ -65,3 +74,62 @@ void mbedtls_platform_zeroize( void *buf, size_t len )
|
||||
memset_func( buf, 0, len );
|
||||
}
|
||||
#endif /* MBEDTLS_PLATFORM_ZEROIZE_ALT */
|
||||
|
||||
#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT)
|
||||
#include <time.h>
|
||||
#if !defined(_WIN32) && (defined(unix) || \
|
||||
defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \
|
||||
defined(__MACH__)))
|
||||
#include <unistd.h>
|
||||
#endif /* !_WIN32 && (unix || __unix || __unix__ ||
|
||||
* (__APPLE__ && __MACH__)) */
|
||||
|
||||
#if !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \
|
||||
( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \
|
||||
_POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) )
|
||||
/*
|
||||
* This is a convenience shorthand macro to avoid checking the long
|
||||
* preprocessor conditions above. Ideally, we could expose this macro in
|
||||
* platform_util.h and simply use it in platform_util.c, threading.c and
|
||||
* threading.h. However, this macro is not part of the Mbed TLS public API, so
|
||||
* we keep it private by only defining it in this file
|
||||
*/
|
||||
#if ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) )
|
||||
#define PLATFORM_UTIL_USE_GMTIME
|
||||
#endif /* ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) */
|
||||
|
||||
#endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \
|
||||
( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \
|
||||
_POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) ) */
|
||||
|
||||
struct tm *mbedtls_platform_gmtime_r( const mbedtls_time_t *tt,
|
||||
struct tm *tm_buf )
|
||||
{
|
||||
#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
|
||||
return( ( gmtime_s( tm_buf, tt ) == 0 ) ? tm_buf : NULL );
|
||||
#elif !defined(PLATFORM_UTIL_USE_GMTIME)
|
||||
return( gmtime_r( tt, tm_buf ) );
|
||||
#else
|
||||
struct tm *lt;
|
||||
|
||||
#if defined(MBEDTLS_THREADING_C)
|
||||
if( mbedtls_mutex_lock( &mbedtls_threading_gmtime_mutex ) != 0 )
|
||||
return( NULL );
|
||||
#endif /* MBEDTLS_THREADING_C */
|
||||
|
||||
lt = gmtime( tt );
|
||||
|
||||
if( lt != NULL )
|
||||
{
|
||||
memcpy( tm_buf, lt, sizeof( struct tm ) );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_THREADING_C)
|
||||
if( mbedtls_mutex_unlock( &mbedtls_threading_gmtime_mutex ) != 0 )
|
||||
return( NULL );
|
||||
#endif /* MBEDTLS_THREADING_C */
|
||||
|
||||
return( ( lt == NULL ) ? NULL : tm_buf );
|
||||
#endif /* _WIN32 && !EFIX64 && !EFI32 */
|
||||
}
|
||||
#endif /* MBEDTLS_HAVE_TIME_DATE && MBEDTLS_PLATFORM_GMTIME_R_ALT */
|
||||
|
||||
563
library/poly1305.c
Normal file
563
library/poly1305.c
Normal file
@@ -0,0 +1,563 @@
|
||||
/**
|
||||
* \file poly1305.c
|
||||
*
|
||||
* \brief Poly1305 authentication algorithm.
|
||||
*
|
||||
* Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is part of mbed TLS (https://tls.mbed.org)
|
||||
*/
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_POLY1305_C)
|
||||
|
||||
#include "mbedtls/poly1305.h"
|
||||
#include "mbedtls/platform_util.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#if defined(MBEDTLS_SELF_TEST)
|
||||
#if defined(MBEDTLS_PLATFORM_C)
|
||||
#include "mbedtls/platform.h"
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#define mbedtls_printf printf
|
||||
#endif /* MBEDTLS_PLATFORM_C */
|
||||
#endif /* MBEDTLS_SELF_TEST */
|
||||
|
||||
#if !defined(MBEDTLS_POLY1305_ALT)
|
||||
|
||||
#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
|
||||
!defined(inline) && !defined(__cplusplus)
|
||||
#define inline __inline
|
||||
#endif
|
||||
|
||||
#define POLY1305_BLOCK_SIZE_BYTES ( 16U )
|
||||
|
||||
#define BYTES_TO_U32_LE( data, offset ) \
|
||||
( (uint32_t) data[offset] \
|
||||
| (uint32_t) ( (uint32_t) data[( offset ) + 1] << 8 ) \
|
||||
| (uint32_t) ( (uint32_t) data[( offset ) + 2] << 16 ) \
|
||||
| (uint32_t) ( (uint32_t) data[( offset ) + 3] << 24 ) \
|
||||
)
|
||||
|
||||
/*
|
||||
* Our implementation is tuned for 32-bit platforms with a 64-bit multiplier.
|
||||
* However we provided an alternative for platforms without such a multiplier.
|
||||
*/
|
||||
#if defined(MBEDTLS_NO_64BIT_MULTIPLICATION)
|
||||
static uint64_t mul64( uint32_t a, uint32_t b )
|
||||
{
|
||||
/* a = al + 2**16 ah, b = bl + 2**16 bh */
|
||||
const uint16_t al = (uint16_t) a;
|
||||
const uint16_t bl = (uint16_t) b;
|
||||
const uint16_t ah = a >> 16;
|
||||
const uint16_t bh = b >> 16;
|
||||
|
||||
/* ab = al*bl + 2**16 (ah*bl + bl*bh) + 2**32 ah*bh */
|
||||
const uint32_t lo = (uint32_t) al * bl;
|
||||
const uint64_t me = (uint64_t)( (uint32_t) ah * bl ) + (uint32_t) al * bh;
|
||||
const uint32_t hi = (uint32_t) ah * bh;
|
||||
|
||||
return( lo + ( me << 16 ) + ( (uint64_t) hi << 32 ) );
|
||||
}
|
||||
#else
|
||||
static inline uint64_t mul64( uint32_t a, uint32_t b )
|
||||
{
|
||||
return( (uint64_t) a * b );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* \brief Process blocks with Poly1305.
|
||||
*
|
||||
* \param ctx The Poly1305 context.
|
||||
* \param nblocks Number of blocks to process. Note that this
|
||||
* function only processes full blocks.
|
||||
* \param input Buffer containing the input block(s).
|
||||
* \param needs_padding Set to 0 if the padding bit has already been
|
||||
* applied to the input data before calling this
|
||||
* function. Otherwise, set this parameter to 1.
|
||||
*/
|
||||
static void poly1305_process( mbedtls_poly1305_context *ctx,
|
||||
size_t nblocks,
|
||||
const unsigned char *input,
|
||||
uint32_t needs_padding )
|
||||
{
|
||||
uint64_t d0, d1, d2, d3;
|
||||
uint32_t acc0, acc1, acc2, acc3, acc4;
|
||||
uint32_t r0, r1, r2, r3;
|
||||
uint32_t rs1, rs2, rs3;
|
||||
size_t offset = 0U;
|
||||
size_t i;
|
||||
|
||||
r0 = ctx->r[0];
|
||||
r1 = ctx->r[1];
|
||||
r2 = ctx->r[2];
|
||||
r3 = ctx->r[3];
|
||||
|
||||
rs1 = r1 + ( r1 >> 2U );
|
||||
rs2 = r2 + ( r2 >> 2U );
|
||||
rs3 = r3 + ( r3 >> 2U );
|
||||
|
||||
acc0 = ctx->acc[0];
|
||||
acc1 = ctx->acc[1];
|
||||
acc2 = ctx->acc[2];
|
||||
acc3 = ctx->acc[3];
|
||||
acc4 = ctx->acc[4];
|
||||
|
||||
/* Process full blocks */
|
||||
for( i = 0U; i < nblocks; i++ )
|
||||
{
|
||||
/* The input block is treated as a 128-bit little-endian integer */
|
||||
d0 = BYTES_TO_U32_LE( input, offset + 0 );
|
||||
d1 = BYTES_TO_U32_LE( input, offset + 4 );
|
||||
d2 = BYTES_TO_U32_LE( input, offset + 8 );
|
||||
d3 = BYTES_TO_U32_LE( input, offset + 12 );
|
||||
|
||||
/* Compute: acc += (padded) block as a 130-bit integer */
|
||||
d0 += (uint64_t) acc0;
|
||||
d1 += (uint64_t) acc1 + ( d0 >> 32U );
|
||||
d2 += (uint64_t) acc2 + ( d1 >> 32U );
|
||||
d3 += (uint64_t) acc3 + ( d2 >> 32U );
|
||||
acc0 = (uint32_t) d0;
|
||||
acc1 = (uint32_t) d1;
|
||||
acc2 = (uint32_t) d2;
|
||||
acc3 = (uint32_t) d3;
|
||||
acc4 += (uint32_t) ( d3 >> 32U ) + needs_padding;
|
||||
|
||||
/* Compute: acc *= r */
|
||||
d0 = mul64( acc0, r0 ) +
|
||||
mul64( acc1, rs3 ) +
|
||||
mul64( acc2, rs2 ) +
|
||||
mul64( acc3, rs1 );
|
||||
d1 = mul64( acc0, r1 ) +
|
||||
mul64( acc1, r0 ) +
|
||||
mul64( acc2, rs3 ) +
|
||||
mul64( acc3, rs2 ) +
|
||||
mul64( acc4, rs1 );
|
||||
d2 = mul64( acc0, r2 ) +
|
||||
mul64( acc1, r1 ) +
|
||||
mul64( acc2, r0 ) +
|
||||
mul64( acc3, rs3 ) +
|
||||
mul64( acc4, rs2 );
|
||||
d3 = mul64( acc0, r3 ) +
|
||||
mul64( acc1, r2 ) +
|
||||
mul64( acc2, r1 ) +
|
||||
mul64( acc3, r0 ) +
|
||||
mul64( acc4, rs3 );
|
||||
acc4 *= r0;
|
||||
|
||||
/* Compute: acc %= (2^130 - 5) (partial remainder) */
|
||||
d1 += ( d0 >> 32 );
|
||||
d2 += ( d1 >> 32 );
|
||||
d3 += ( d2 >> 32 );
|
||||
acc0 = (uint32_t) d0;
|
||||
acc1 = (uint32_t) d1;
|
||||
acc2 = (uint32_t) d2;
|
||||
acc3 = (uint32_t) d3;
|
||||
acc4 = (uint32_t) ( d3 >> 32 ) + acc4;
|
||||
|
||||
d0 = (uint64_t) acc0 + ( acc4 >> 2 ) + ( acc4 & 0xFFFFFFFCU );
|
||||
acc4 &= 3U;
|
||||
acc0 = (uint32_t) d0;
|
||||
d0 = (uint64_t) acc1 + ( d0 >> 32U );
|
||||
acc1 = (uint32_t) d0;
|
||||
d0 = (uint64_t) acc2 + ( d0 >> 32U );
|
||||
acc2 = (uint32_t) d0;
|
||||
d0 = (uint64_t) acc3 + ( d0 >> 32U );
|
||||
acc3 = (uint32_t) d0;
|
||||
d0 = (uint64_t) acc4 + ( d0 >> 32U );
|
||||
acc4 = (uint32_t) d0;
|
||||
|
||||
offset += POLY1305_BLOCK_SIZE_BYTES;
|
||||
}
|
||||
|
||||
ctx->acc[0] = acc0;
|
||||
ctx->acc[1] = acc1;
|
||||
ctx->acc[2] = acc2;
|
||||
ctx->acc[3] = acc3;
|
||||
ctx->acc[4] = acc4;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Compute the Poly1305 MAC
|
||||
*
|
||||
* \param ctx The Poly1305 context.
|
||||
* \param mac The buffer to where the MAC is written. Must be
|
||||
* big enough to contain the 16-byte MAC.
|
||||
*/
|
||||
static void poly1305_compute_mac( const mbedtls_poly1305_context *ctx,
|
||||
unsigned char mac[16] )
|
||||
{
|
||||
uint64_t d;
|
||||
uint32_t g0, g1, g2, g3, g4;
|
||||
uint32_t acc0, acc1, acc2, acc3, acc4;
|
||||
uint32_t mask;
|
||||
uint32_t mask_inv;
|
||||
|
||||
acc0 = ctx->acc[0];
|
||||
acc1 = ctx->acc[1];
|
||||
acc2 = ctx->acc[2];
|
||||
acc3 = ctx->acc[3];
|
||||
acc4 = ctx->acc[4];
|
||||
|
||||
/* Before adding 's' we ensure that the accumulator is mod 2^130 - 5.
|
||||
* We do this by calculating acc - (2^130 - 5), then checking if
|
||||
* the 131st bit is set. If it is, then reduce: acc -= (2^130 - 5)
|
||||
*/
|
||||
|
||||
/* Calculate acc + -(2^130 - 5) */
|
||||
d = ( (uint64_t) acc0 + 5U );
|
||||
g0 = (uint32_t) d;
|
||||
d = ( (uint64_t) acc1 + ( d >> 32 ) );
|
||||
g1 = (uint32_t) d;
|
||||
d = ( (uint64_t) acc2 + ( d >> 32 ) );
|
||||
g2 = (uint32_t) d;
|
||||
d = ( (uint64_t) acc3 + ( d >> 32 ) );
|
||||
g3 = (uint32_t) d;
|
||||
g4 = acc4 + (uint32_t) ( d >> 32U );
|
||||
|
||||
/* mask == 0xFFFFFFFF if 131st bit is set, otherwise mask == 0 */
|
||||
mask = (uint32_t) 0U - ( g4 >> 2U );
|
||||
mask_inv = ~mask;
|
||||
|
||||
/* If 131st bit is set then acc=g, otherwise, acc is unmodified */
|
||||
acc0 = ( acc0 & mask_inv ) | ( g0 & mask );
|
||||
acc1 = ( acc1 & mask_inv ) | ( g1 & mask );
|
||||
acc2 = ( acc2 & mask_inv ) | ( g2 & mask );
|
||||
acc3 = ( acc3 & mask_inv ) | ( g3 & mask );
|
||||
|
||||
/* Add 's' */
|
||||
d = (uint64_t) acc0 + ctx->s[0];
|
||||
acc0 = (uint32_t) d;
|
||||
d = (uint64_t) acc1 + ctx->s[1] + ( d >> 32U );
|
||||
acc1 = (uint32_t) d;
|
||||
d = (uint64_t) acc2 + ctx->s[2] + ( d >> 32U );
|
||||
acc2 = (uint32_t) d;
|
||||
acc3 += ctx->s[3] + (uint32_t) ( d >> 32U );
|
||||
|
||||
/* Compute MAC (128 least significant bits of the accumulator) */
|
||||
mac[ 0] = (unsigned char)( acc0 );
|
||||
mac[ 1] = (unsigned char)( acc0 >> 8 );
|
||||
mac[ 2] = (unsigned char)( acc0 >> 16 );
|
||||
mac[ 3] = (unsigned char)( acc0 >> 24 );
|
||||
mac[ 4] = (unsigned char)( acc1 );
|
||||
mac[ 5] = (unsigned char)( acc1 >> 8 );
|
||||
mac[ 6] = (unsigned char)( acc1 >> 16 );
|
||||
mac[ 7] = (unsigned char)( acc1 >> 24 );
|
||||
mac[ 8] = (unsigned char)( acc2 );
|
||||
mac[ 9] = (unsigned char)( acc2 >> 8 );
|
||||
mac[10] = (unsigned char)( acc2 >> 16 );
|
||||
mac[11] = (unsigned char)( acc2 >> 24 );
|
||||
mac[12] = (unsigned char)( acc3 );
|
||||
mac[13] = (unsigned char)( acc3 >> 8 );
|
||||
mac[14] = (unsigned char)( acc3 >> 16 );
|
||||
mac[15] = (unsigned char)( acc3 >> 24 );
|
||||
}
|
||||
|
||||
void mbedtls_poly1305_init( mbedtls_poly1305_context *ctx )
|
||||
{
|
||||
if( ctx != NULL )
|
||||
{
|
||||
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_poly1305_context ) );
|
||||
}
|
||||
}
|
||||
|
||||
void mbedtls_poly1305_free( mbedtls_poly1305_context *ctx )
|
||||
{
|
||||
if( ctx != NULL )
|
||||
{
|
||||
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_poly1305_context ) );
|
||||
}
|
||||
}
|
||||
|
||||
int mbedtls_poly1305_starts( mbedtls_poly1305_context *ctx,
|
||||
const unsigned char key[32] )
|
||||
{
|
||||
if( ctx == NULL || key == NULL )
|
||||
{
|
||||
return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
|
||||
}
|
||||
|
||||
/* r &= 0x0ffffffc0ffffffc0ffffffc0fffffff */
|
||||
ctx->r[0] = BYTES_TO_U32_LE( key, 0 ) & 0x0FFFFFFFU;
|
||||
ctx->r[1] = BYTES_TO_U32_LE( key, 4 ) & 0x0FFFFFFCU;
|
||||
ctx->r[2] = BYTES_TO_U32_LE( key, 8 ) & 0x0FFFFFFCU;
|
||||
ctx->r[3] = BYTES_TO_U32_LE( key, 12 ) & 0x0FFFFFFCU;
|
||||
|
||||
ctx->s[0] = BYTES_TO_U32_LE( key, 16 );
|
||||
ctx->s[1] = BYTES_TO_U32_LE( key, 20 );
|
||||
ctx->s[2] = BYTES_TO_U32_LE( key, 24 );
|
||||
ctx->s[3] = BYTES_TO_U32_LE( key, 28 );
|
||||
|
||||
/* Initial accumulator state */
|
||||
ctx->acc[0] = 0U;
|
||||
ctx->acc[1] = 0U;
|
||||
ctx->acc[2] = 0U;
|
||||
ctx->acc[3] = 0U;
|
||||
ctx->acc[4] = 0U;
|
||||
|
||||
/* Queue initially empty */
|
||||
mbedtls_platform_zeroize( ctx->queue, sizeof( ctx->queue ) );
|
||||
ctx->queue_len = 0U;
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int mbedtls_poly1305_update( mbedtls_poly1305_context *ctx,
|
||||
const unsigned char *input,
|
||||
size_t ilen )
|
||||
{
|
||||
size_t offset = 0U;
|
||||
size_t remaining = ilen;
|
||||
size_t queue_free_len;
|
||||
size_t nblocks;
|
||||
|
||||
if( ctx == NULL )
|
||||
{
|
||||
return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
|
||||
}
|
||||
else if( ( ilen > 0U ) && ( input == NULL ) )
|
||||
{
|
||||
/* input pointer is allowed to be NULL only if ilen == 0 */
|
||||
return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
|
||||
}
|
||||
|
||||
if( ( remaining > 0U ) && ( ctx->queue_len > 0U ) )
|
||||
{
|
||||
queue_free_len = ( POLY1305_BLOCK_SIZE_BYTES - ctx->queue_len );
|
||||
|
||||
if( ilen < queue_free_len )
|
||||
{
|
||||
/* Not enough data to complete the block.
|
||||
* Store this data with the other leftovers.
|
||||
*/
|
||||
memcpy( &ctx->queue[ctx->queue_len],
|
||||
input,
|
||||
ilen );
|
||||
|
||||
ctx->queue_len += ilen;
|
||||
|
||||
remaining = 0U;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Enough data to produce a complete block */
|
||||
memcpy( &ctx->queue[ctx->queue_len],
|
||||
input,
|
||||
queue_free_len );
|
||||
|
||||
ctx->queue_len = 0U;
|
||||
|
||||
poly1305_process( ctx, 1U, ctx->queue, 1U ); /* add padding bit */
|
||||
|
||||
offset += queue_free_len;
|
||||
remaining -= queue_free_len;
|
||||
}
|
||||
}
|
||||
|
||||
if( remaining >= POLY1305_BLOCK_SIZE_BYTES )
|
||||
{
|
||||
nblocks = remaining / POLY1305_BLOCK_SIZE_BYTES;
|
||||
|
||||
poly1305_process( ctx, nblocks, &input[offset], 1U );
|
||||
|
||||
offset += nblocks * POLY1305_BLOCK_SIZE_BYTES;
|
||||
remaining %= POLY1305_BLOCK_SIZE_BYTES;
|
||||
}
|
||||
|
||||
if( remaining > 0U )
|
||||
{
|
||||
/* Store partial block */
|
||||
ctx->queue_len = remaining;
|
||||
memcpy( ctx->queue, &input[offset], remaining );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int mbedtls_poly1305_finish( mbedtls_poly1305_context *ctx,
|
||||
unsigned char mac[16] )
|
||||
{
|
||||
if( ( ctx == NULL ) || ( mac == NULL ) )
|
||||
{
|
||||
return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
|
||||
}
|
||||
|
||||
/* Process any leftover data */
|
||||
if( ctx->queue_len > 0U )
|
||||
{
|
||||
/* Add padding bit */
|
||||
ctx->queue[ctx->queue_len] = 1U;
|
||||
ctx->queue_len++;
|
||||
|
||||
/* Pad with zeroes */
|
||||
memset( &ctx->queue[ctx->queue_len],
|
||||
0,
|
||||
POLY1305_BLOCK_SIZE_BYTES - ctx->queue_len );
|
||||
|
||||
poly1305_process( ctx, 1U, /* Process 1 block */
|
||||
ctx->queue, 0U ); /* Already padded above */
|
||||
}
|
||||
|
||||
poly1305_compute_mac( ctx, mac );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int mbedtls_poly1305_mac( const unsigned char key[32],
|
||||
const unsigned char *input,
|
||||
size_t ilen,
|
||||
unsigned char mac[16] )
|
||||
{
|
||||
mbedtls_poly1305_context ctx;
|
||||
int ret;
|
||||
|
||||
mbedtls_poly1305_init( &ctx );
|
||||
|
||||
ret = mbedtls_poly1305_starts( &ctx, key );
|
||||
if( ret != 0 )
|
||||
goto cleanup;
|
||||
|
||||
ret = mbedtls_poly1305_update( &ctx, input, ilen );
|
||||
if( ret != 0 )
|
||||
goto cleanup;
|
||||
|
||||
ret = mbedtls_poly1305_finish( &ctx, mac );
|
||||
|
||||
cleanup:
|
||||
mbedtls_poly1305_free( &ctx );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
#endif /* MBEDTLS_POLY1305_ALT */
|
||||
|
||||
#if defined(MBEDTLS_SELF_TEST)
|
||||
|
||||
static const unsigned char test_keys[2][32] =
|
||||
{
|
||||
{
|
||||
0x85, 0xd6, 0xbe, 0x78, 0x57, 0x55, 0x6d, 0x33,
|
||||
0x7f, 0x44, 0x52, 0xfe, 0x42, 0xd5, 0x06, 0xa8,
|
||||
0x01, 0x03, 0x80, 0x8a, 0xfb, 0x0d, 0xb2, 0xfd,
|
||||
0x4a, 0xbf, 0xf6, 0xaf, 0x41, 0x49, 0xf5, 0x1b
|
||||
},
|
||||
{
|
||||
0x1c, 0x92, 0x40, 0xa5, 0xeb, 0x55, 0xd3, 0x8a,
|
||||
0xf3, 0x33, 0x88, 0x86, 0x04, 0xf6, 0xb5, 0xf0,
|
||||
0x47, 0x39, 0x17, 0xc1, 0x40, 0x2b, 0x80, 0x09,
|
||||
0x9d, 0xca, 0x5c, 0xbc, 0x20, 0x70, 0x75, 0xc0
|
||||
}
|
||||
};
|
||||
|
||||
static const unsigned char test_data[2][127] =
|
||||
{
|
||||
{
|
||||
0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x67, 0x72,
|
||||
0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x46, 0x6f,
|
||||
0x72, 0x75, 0x6d, 0x20, 0x52, 0x65, 0x73, 0x65,
|
||||
0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6f,
|
||||
0x75, 0x70
|
||||
},
|
||||
{
|
||||
0x27, 0x54, 0x77, 0x61, 0x73, 0x20, 0x62, 0x72,
|
||||
0x69, 0x6c, 0x6c, 0x69, 0x67, 0x2c, 0x20, 0x61,
|
||||
0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
|
||||
0x6c, 0x69, 0x74, 0x68, 0x79, 0x20, 0x74, 0x6f,
|
||||
0x76, 0x65, 0x73, 0x0a, 0x44, 0x69, 0x64, 0x20,
|
||||
0x67, 0x79, 0x72, 0x65, 0x20, 0x61, 0x6e, 0x64,
|
||||
0x20, 0x67, 0x69, 0x6d, 0x62, 0x6c, 0x65, 0x20,
|
||||
0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77,
|
||||
0x61, 0x62, 0x65, 0x3a, 0x0a, 0x41, 0x6c, 0x6c,
|
||||
0x20, 0x6d, 0x69, 0x6d, 0x73, 0x79, 0x20, 0x77,
|
||||
0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20,
|
||||
0x62, 0x6f, 0x72, 0x6f, 0x67, 0x6f, 0x76, 0x65,
|
||||
0x73, 0x2c, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
|
||||
0x68, 0x65, 0x20, 0x6d, 0x6f, 0x6d, 0x65, 0x20,
|
||||
0x72, 0x61, 0x74, 0x68, 0x73, 0x20, 0x6f, 0x75,
|
||||
0x74, 0x67, 0x72, 0x61, 0x62, 0x65, 0x2e
|
||||
}
|
||||
};
|
||||
|
||||
static const size_t test_data_len[2] =
|
||||
{
|
||||
34U,
|
||||
127U
|
||||
};
|
||||
|
||||
static const unsigned char test_mac[2][16] =
|
||||
{
|
||||
{
|
||||
0xa8, 0x06, 0x1d, 0xc1, 0x30, 0x51, 0x36, 0xc6,
|
||||
0xc2, 0x2b, 0x8b, 0xaf, 0x0c, 0x01, 0x27, 0xa9
|
||||
},
|
||||
{
|
||||
0x45, 0x41, 0x66, 0x9a, 0x7e, 0xaa, 0xee, 0x61,
|
||||
0xe7, 0x08, 0xdc, 0x7c, 0xbc, 0xc5, 0xeb, 0x62
|
||||
}
|
||||
};
|
||||
|
||||
#define ASSERT( cond, args ) \
|
||||
do \
|
||||
{ \
|
||||
if( ! ( cond ) ) \
|
||||
{ \
|
||||
if( verbose != 0 ) \
|
||||
mbedtls_printf args; \
|
||||
\
|
||||
return( -1 ); \
|
||||
} \
|
||||
} \
|
||||
while( 0 )
|
||||
|
||||
int mbedtls_poly1305_self_test( int verbose )
|
||||
{
|
||||
unsigned char mac[16];
|
||||
unsigned i;
|
||||
int ret;
|
||||
|
||||
for( i = 0U; i < 2U; i++ )
|
||||
{
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( " Poly1305 test %u ", i );
|
||||
|
||||
ret = mbedtls_poly1305_mac( test_keys[i],
|
||||
test_data[i],
|
||||
test_data_len[i],
|
||||
mac );
|
||||
ASSERT( 0 == ret, ( "error code: %i\n", ret ) );
|
||||
|
||||
ASSERT( 0 == memcmp( mac, test_mac[i], 16U ), ( "failed (mac)\n" ) );
|
||||
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( "passed\n" );
|
||||
}
|
||||
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( "\n" );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
#endif /* MBEDTLS_SELF_TEST */
|
||||
|
||||
#endif /* MBEDTLS_POLY1305_C */
|
||||
@@ -342,14 +342,6 @@ void mbedtls_sha1_update( mbedtls_sha1_context *ctx,
|
||||
}
|
||||
#endif
|
||||
|
||||
static const unsigned char sha1_padding[64] =
|
||||
{
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
/*
|
||||
* SHA-1 final digest
|
||||
*/
|
||||
@@ -357,25 +349,48 @@ int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx,
|
||||
unsigned char output[20] )
|
||||
{
|
||||
int ret;
|
||||
uint32_t last, padn;
|
||||
uint32_t used;
|
||||
uint32_t high, low;
|
||||
unsigned char msglen[8];
|
||||
|
||||
/*
|
||||
* Add padding: 0x80 then 0x00 until 8 bytes remain for the length
|
||||
*/
|
||||
used = ctx->total[0] & 0x3F;
|
||||
|
||||
ctx->buffer[used++] = 0x80;
|
||||
|
||||
if( used <= 56 )
|
||||
{
|
||||
/* Enough room for padding + length in current block */
|
||||
memset( ctx->buffer + used, 0, 56 - used );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We'll need an extra block */
|
||||
memset( ctx->buffer + used, 0, 64 - used );
|
||||
|
||||
if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 )
|
||||
return( ret );
|
||||
|
||||
memset( ctx->buffer, 0, 56 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Add message length
|
||||
*/
|
||||
high = ( ctx->total[0] >> 29 )
|
||||
| ( ctx->total[1] << 3 );
|
||||
low = ( ctx->total[0] << 3 );
|
||||
|
||||
PUT_UINT32_BE( high, msglen, 0 );
|
||||
PUT_UINT32_BE( low, msglen, 4 );
|
||||
PUT_UINT32_BE( high, ctx->buffer, 56 );
|
||||
PUT_UINT32_BE( low, ctx->buffer, 60 );
|
||||
|
||||
last = ctx->total[0] & 0x3F;
|
||||
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
|
||||
|
||||
if( ( ret = mbedtls_sha1_update_ret( ctx, sha1_padding, padn ) ) != 0 )
|
||||
return( ret );
|
||||
if( ( ret = mbedtls_sha1_update_ret( ctx, msglen, 8 ) ) != 0 )
|
||||
if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 )
|
||||
return( ret );
|
||||
|
||||
/*
|
||||
* Output final state
|
||||
*/
|
||||
PUT_UINT32_BE( ctx->state[0], output, 0 );
|
||||
PUT_UINT32_BE( ctx->state[1], output, 4 );
|
||||
PUT_UINT32_BE( ctx->state[2], output, 8 );
|
||||
|
||||
@@ -311,14 +311,6 @@ void mbedtls_sha256_update( mbedtls_sha256_context *ctx,
|
||||
}
|
||||
#endif
|
||||
|
||||
static const unsigned char sha256_padding[64] =
|
||||
{
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
/*
|
||||
* SHA-256 final digest
|
||||
*/
|
||||
@@ -326,26 +318,48 @@ int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx,
|
||||
unsigned char output[32] )
|
||||
{
|
||||
int ret;
|
||||
uint32_t last, padn;
|
||||
uint32_t used;
|
||||
uint32_t high, low;
|
||||
unsigned char msglen[8];
|
||||
|
||||
/*
|
||||
* Add padding: 0x80 then 0x00 until 8 bytes remain for the length
|
||||
*/
|
||||
used = ctx->total[0] & 0x3F;
|
||||
|
||||
ctx->buffer[used++] = 0x80;
|
||||
|
||||
if( used <= 56 )
|
||||
{
|
||||
/* Enough room for padding + length in current block */
|
||||
memset( ctx->buffer + used, 0, 56 - used );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We'll need an extra block */
|
||||
memset( ctx->buffer + used, 0, 64 - used );
|
||||
|
||||
if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 )
|
||||
return( ret );
|
||||
|
||||
memset( ctx->buffer, 0, 56 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Add message length
|
||||
*/
|
||||
high = ( ctx->total[0] >> 29 )
|
||||
| ( ctx->total[1] << 3 );
|
||||
low = ( ctx->total[0] << 3 );
|
||||
|
||||
PUT_UINT32_BE( high, msglen, 0 );
|
||||
PUT_UINT32_BE( low, msglen, 4 );
|
||||
PUT_UINT32_BE( high, ctx->buffer, 56 );
|
||||
PUT_UINT32_BE( low, ctx->buffer, 60 );
|
||||
|
||||
last = ctx->total[0] & 0x3F;
|
||||
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
|
||||
|
||||
if( ( ret = mbedtls_sha256_update_ret( ctx, sha256_padding, padn ) ) != 0 )
|
||||
return( ret );
|
||||
|
||||
if( ( ret = mbedtls_sha256_update_ret( ctx, msglen, 8 ) ) != 0 )
|
||||
if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 )
|
||||
return( ret );
|
||||
|
||||
/*
|
||||
* Output final state
|
||||
*/
|
||||
PUT_UINT32_BE( ctx->state[0], output, 0 );
|
||||
PUT_UINT32_BE( ctx->state[1], output, 4 );
|
||||
PUT_UINT32_BE( ctx->state[2], output, 8 );
|
||||
|
||||
@@ -341,18 +341,6 @@ void mbedtls_sha512_update( mbedtls_sha512_context *ctx,
|
||||
}
|
||||
#endif
|
||||
|
||||
static const unsigned char sha512_padding[128] =
|
||||
{
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
/*
|
||||
* SHA-512 final digest
|
||||
*/
|
||||
@@ -360,26 +348,48 @@ int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx,
|
||||
unsigned char output[64] )
|
||||
{
|
||||
int ret;
|
||||
size_t last, padn;
|
||||
unsigned used;
|
||||
uint64_t high, low;
|
||||
unsigned char msglen[16];
|
||||
|
||||
/*
|
||||
* Add padding: 0x80 then 0x00 until 16 bytes remain for the length
|
||||
*/
|
||||
used = ctx->total[0] & 0x7F;
|
||||
|
||||
ctx->buffer[used++] = 0x80;
|
||||
|
||||
if( used <= 112 )
|
||||
{
|
||||
/* Enough room for padding + length in current block */
|
||||
memset( ctx->buffer + used, 0, 112 - used );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We'll need an extra block */
|
||||
memset( ctx->buffer + used, 0, 128 - used );
|
||||
|
||||
if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 )
|
||||
return( ret );
|
||||
|
||||
memset( ctx->buffer, 0, 112 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Add message length
|
||||
*/
|
||||
high = ( ctx->total[0] >> 61 )
|
||||
| ( ctx->total[1] << 3 );
|
||||
low = ( ctx->total[0] << 3 );
|
||||
|
||||
PUT_UINT64_BE( high, msglen, 0 );
|
||||
PUT_UINT64_BE( low, msglen, 8 );
|
||||
PUT_UINT64_BE( high, ctx->buffer, 112 );
|
||||
PUT_UINT64_BE( low, ctx->buffer, 120 );
|
||||
|
||||
last = (size_t)( ctx->total[0] & 0x7F );
|
||||
padn = ( last < 112 ) ? ( 112 - last ) : ( 240 - last );
|
||||
|
||||
if( ( ret = mbedtls_sha512_update_ret( ctx, sha512_padding, padn ) ) != 0 )
|
||||
return( ret );
|
||||
|
||||
if( ( ret = mbedtls_sha512_update_ret( ctx, msglen, 16 ) ) != 0 )
|
||||
return( ret );
|
||||
if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 )
|
||||
return( ret );
|
||||
|
||||
/*
|
||||
* Output final state
|
||||
*/
|
||||
PUT_UINT64_BE( ctx->state[0], output, 0 );
|
||||
PUT_UINT64_BE( ctx->state[1], output, 8 );
|
||||
PUT_UINT64_BE( ctx->state[2], output, 16 );
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
* 1. By key exchange:
|
||||
* Forward-secure non-PSK > forward-secure PSK > ECJPAKE > other non-PSK > other PSK
|
||||
* 2. By key length and cipher:
|
||||
* AES-256 > Camellia-256 > AES-128 > Camellia-128 > 3DES
|
||||
* ChaCha > AES-256 > Camellia-256 > ARIA-256 > AES-128 > Camellia-128 > ARIA-128 > 3DES
|
||||
* 3. By cipher mode when relevant GCM > CCM > CBC > CCM_8
|
||||
* 4. By hash function used when relevant
|
||||
* 5. By key exchange/auth again: EC > non-EC
|
||||
@@ -57,6 +57,11 @@ static const int ciphersuite_preference[] =
|
||||
#if defined(MBEDTLS_SSL_CIPHERSUITES)
|
||||
MBEDTLS_SSL_CIPHERSUITES,
|
||||
#else
|
||||
/* Chacha-Poly ephemeral suites */
|
||||
MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
|
||||
MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
|
||||
MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
|
||||
|
||||
/* All AES-256 ephemeral suites */
|
||||
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||
MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||
@@ -81,6 +86,14 @@ static const int ciphersuite_preference[] =
|
||||
MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,
|
||||
MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
|
||||
|
||||
/* All ARIA-256 ephemeral suites */
|
||||
MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384,
|
||||
MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384,
|
||||
MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384,
|
||||
MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384,
|
||||
MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384,
|
||||
MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384,
|
||||
|
||||
/* All AES-128 ephemeral suites */
|
||||
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||
MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||
@@ -105,12 +118,22 @@ static const int ciphersuite_preference[] =
|
||||
MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||
MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
|
||||
|
||||
/* All ARIA-128 ephemeral suites */
|
||||
MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256,
|
||||
MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256,
|
||||
MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256,
|
||||
MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256,
|
||||
MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256,
|
||||
MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256,
|
||||
|
||||
/* All remaining >= 128-bit ephemeral suites */
|
||||
MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
|
||||
MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||
MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||
|
||||
/* The PSK ephemeral suites */
|
||||
MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
|
||||
MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
|
||||
MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384,
|
||||
MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM,
|
||||
MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
|
||||
@@ -121,6 +144,9 @@ static const int ciphersuite_preference[] =
|
||||
MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
|
||||
MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
|
||||
MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8,
|
||||
MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384,
|
||||
MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,
|
||||
MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384,
|
||||
|
||||
MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256,
|
||||
MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM,
|
||||
@@ -132,6 +158,9 @@ static const int ciphersuite_preference[] =
|
||||
MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
|
||||
MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
|
||||
MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8,
|
||||
MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256,
|
||||
MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256,
|
||||
MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256,
|
||||
|
||||
MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA,
|
||||
MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA,
|
||||
@@ -161,6 +190,14 @@ static const int ciphersuite_preference[] =
|
||||
MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384,
|
||||
MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
|
||||
|
||||
/* All ARIA-256 suites */
|
||||
MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384,
|
||||
MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384,
|
||||
MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384,
|
||||
MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384,
|
||||
MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384,
|
||||
MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384,
|
||||
|
||||
/* All AES-128 suites */
|
||||
MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256,
|
||||
MBEDTLS_TLS_RSA_WITH_AES_128_CCM,
|
||||
@@ -183,27 +220,41 @@ static const int ciphersuite_preference[] =
|
||||
MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256,
|
||||
MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
|
||||
|
||||
/* All ARIA-128 suites */
|
||||
MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256,
|
||||
MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256,
|
||||
MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256,
|
||||
MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256,
|
||||
MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256,
|
||||
MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256,
|
||||
|
||||
/* All remaining >= 128-bit suites */
|
||||
MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||
MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||
MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
|
||||
|
||||
/* The RSA PSK suites */
|
||||
MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256,
|
||||
MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384,
|
||||
MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384,
|
||||
MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA,
|
||||
MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384,
|
||||
MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384,
|
||||
MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384,
|
||||
MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384,
|
||||
|
||||
MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256,
|
||||
MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256,
|
||||
MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA,
|
||||
MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256,
|
||||
MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256,
|
||||
MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256,
|
||||
MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256,
|
||||
|
||||
MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA,
|
||||
|
||||
/* The PSK suites */
|
||||
MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256,
|
||||
MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384,
|
||||
MBEDTLS_TLS_PSK_WITH_AES_256_CCM,
|
||||
MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384,
|
||||
@@ -211,6 +262,8 @@ static const int ciphersuite_preference[] =
|
||||
MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384,
|
||||
MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384,
|
||||
MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8,
|
||||
MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384,
|
||||
MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384,
|
||||
|
||||
MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256,
|
||||
MBEDTLS_TLS_PSK_WITH_AES_128_CCM,
|
||||
@@ -219,6 +272,8 @@ static const int ciphersuite_preference[] =
|
||||
MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256,
|
||||
MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256,
|
||||
MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8,
|
||||
MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256,
|
||||
MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256,
|
||||
|
||||
MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA,
|
||||
|
||||
@@ -266,6 +321,75 @@ static const int ciphersuite_preference[] =
|
||||
|
||||
static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
|
||||
{
|
||||
#if defined(MBEDTLS_CHACHAPOLY_C) && \
|
||||
defined(MBEDTLS_SHA256_C) && \
|
||||
defined(MBEDTLS_SSL_PROTO_TLS1_2)
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED)
|
||||
{ MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
|
||||
"TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256",
|
||||
MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,
|
||||
MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
|
||||
{ MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
|
||||
"TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256",
|
||||
MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,
|
||||
MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED)
|
||||
{ MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
|
||||
"TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256",
|
||||
MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,
|
||||
MBEDTLS_KEY_EXCHANGE_DHE_RSA,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
|
||||
{ MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256,
|
||||
"TLS-PSK-WITH-CHACHA20-POLY1305-SHA256",
|
||||
MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,
|
||||
MBEDTLS_KEY_EXCHANGE_PSK,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
|
||||
{ MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
|
||||
"TLS-ECDHE-PSK-WITH-CHACHA20-POLY1305-SHA256",
|
||||
MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,
|
||||
MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
|
||||
{ MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
|
||||
"TLS-DHE-PSK-WITH-CHACHA20-POLY1305-SHA256",
|
||||
MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,
|
||||
MBEDTLS_KEY_EXCHANGE_DHE_PSK,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
|
||||
{ MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256,
|
||||
"TLS-RSA-PSK-WITH-CHACHA20-POLY1305-SHA256",
|
||||
MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,
|
||||
MBEDTLS_KEY_EXCHANGE_RSA_PSK,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
#endif /* MBEDTLS_CHACHAPOLY_C &&
|
||||
MBEDTLS_SHA256_C &&
|
||||
MBEDTLS_SSL_PROTO_TLS1_2 */
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
|
||||
#if defined(MBEDTLS_AES_C)
|
||||
#if defined(MBEDTLS_SHA1_C)
|
||||
@@ -1688,6 +1812,365 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
|
||||
#endif /* MBEDTLS_DES_C */
|
||||
#endif /* MBEDTLS_ENABLE_WEAK_CIPHERSUITES */
|
||||
|
||||
#if defined(MBEDTLS_ARIA_C)
|
||||
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED)
|
||||
|
||||
#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C))
|
||||
{ MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384,
|
||||
"TLS-RSA-WITH-ARIA-256-GCM-SHA384",
|
||||
MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C))
|
||||
{ MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384,
|
||||
"TLS-RSA-WITH-ARIA-256-CBC-SHA384",
|
||||
MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C))
|
||||
{ MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256,
|
||||
"TLS-RSA-WITH-ARIA-128-GCM-SHA256",
|
||||
MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C))
|
||||
{ MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256,
|
||||
"TLS-RSA-WITH-ARIA-128-CBC-SHA256",
|
||||
MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
|
||||
#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */
|
||||
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
|
||||
|
||||
#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C))
|
||||
{ MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384,
|
||||
"TLS-RSA-PSK-WITH-ARIA-256-GCM-SHA384",
|
||||
MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C))
|
||||
{ MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384,
|
||||
"TLS-RSA-PSK-WITH-ARIA-256-CBC-SHA384",
|
||||
MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C))
|
||||
{ MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256,
|
||||
"TLS-RSA-PSK-WITH-ARIA-128-GCM-SHA256",
|
||||
MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C))
|
||||
{ MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256,
|
||||
"TLS-RSA-PSK-WITH-ARIA-128-CBC-SHA256",
|
||||
MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
|
||||
#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */
|
||||
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
|
||||
|
||||
#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C))
|
||||
{ MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384,
|
||||
"TLS-PSK-WITH-ARIA-256-GCM-SHA384",
|
||||
MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384,MBEDTLS_KEY_EXCHANGE_PSK,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C))
|
||||
{ MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384,
|
||||
"TLS-PSK-WITH-ARIA-256-CBC-SHA384",
|
||||
MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C))
|
||||
{ MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256,
|
||||
"TLS-PSK-WITH-ARIA-128-GCM-SHA256",
|
||||
MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C))
|
||||
{ MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256,
|
||||
"TLS-PSK-WITH-ARIA-128-CBC-SHA256",
|
||||
MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
|
||||
#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */
|
||||
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED)
|
||||
|
||||
#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C))
|
||||
{ MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384,
|
||||
"TLS-ECDH-RSA-WITH-ARIA-256-GCM-SHA384",
|
||||
MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C))
|
||||
{ MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384,
|
||||
"TLS-ECDH-RSA-WITH-ARIA-256-CBC-SHA384",
|
||||
MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C))
|
||||
{ MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256,
|
||||
"TLS-ECDH-RSA-WITH-ARIA-128-GCM-SHA256",
|
||||
MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C))
|
||||
{ MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256,
|
||||
"TLS-ECDH-RSA-WITH-ARIA-128-CBC-SHA256",
|
||||
MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
|
||||
#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */
|
||||
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED)
|
||||
|
||||
#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C))
|
||||
{ MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384,
|
||||
"TLS-ECDHE-RSA-WITH-ARIA-256-GCM-SHA384",
|
||||
MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C))
|
||||
{ MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384,
|
||||
"TLS-ECDHE-RSA-WITH-ARIA-256-CBC-SHA384",
|
||||
MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C))
|
||||
{ MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256,
|
||||
"TLS-ECDHE-RSA-WITH-ARIA-128-GCM-SHA256",
|
||||
MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C))
|
||||
{ MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256,
|
||||
"TLS-ECDHE-RSA-WITH-ARIA-128-CBC-SHA256",
|
||||
MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
|
||||
#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */
|
||||
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
|
||||
|
||||
#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C))
|
||||
{ MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,
|
||||
"TLS-ECDHE-PSK-WITH-ARIA-256-CBC-SHA384",
|
||||
MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C))
|
||||
{ MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256,
|
||||
"TLS-ECDHE-PSK-WITH-ARIA-128-CBC-SHA256",
|
||||
MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
|
||||
#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
|
||||
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
|
||||
|
||||
#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C))
|
||||
{ MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384,
|
||||
"TLS-ECDHE-ECDSA-WITH-ARIA-256-GCM-SHA384",
|
||||
MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C))
|
||||
{ MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384,
|
||||
"TLS-ECDHE-ECDSA-WITH-ARIA-256-CBC-SHA384",
|
||||
MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C))
|
||||
{ MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256,
|
||||
"TLS-ECDHE-ECDSA-WITH-ARIA-128-GCM-SHA256",
|
||||
MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C))
|
||||
{ MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256,
|
||||
"TLS-ECDHE-ECDSA-WITH-ARIA-128-CBC-SHA256",
|
||||
MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
|
||||
#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
|
||||
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
|
||||
|
||||
#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C))
|
||||
{ MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384,
|
||||
"TLS-ECDH-ECDSA-WITH-ARIA-256-GCM-SHA384",
|
||||
MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C))
|
||||
{ MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384,
|
||||
"TLS-ECDH-ECDSA-WITH-ARIA-256-CBC-SHA384",
|
||||
MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C))
|
||||
{ MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256,
|
||||
"TLS-ECDH-ECDSA-WITH-ARIA-128-GCM-SHA256",
|
||||
MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C))
|
||||
{ MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256,
|
||||
"TLS-ECDH-ECDSA-WITH-ARIA-128-CBC-SHA256",
|
||||
MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
|
||||
#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
|
||||
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED)
|
||||
|
||||
#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C))
|
||||
{ MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384,
|
||||
"TLS-DHE-RSA-WITH-ARIA-256-GCM-SHA384",
|
||||
MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C))
|
||||
{ MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384,
|
||||
"TLS-DHE-RSA-WITH-ARIA-256-CBC-SHA384",
|
||||
MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C))
|
||||
{ MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256,
|
||||
"TLS-DHE-RSA-WITH-ARIA-128-GCM-SHA256",
|
||||
MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C))
|
||||
{ MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256,
|
||||
"TLS-DHE-RSA-WITH-ARIA-128-CBC-SHA256",
|
||||
MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
|
||||
#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */
|
||||
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
|
||||
|
||||
#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C))
|
||||
{ MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384,
|
||||
"TLS-DHE-PSK-WITH-ARIA-256-GCM-SHA384",
|
||||
MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C))
|
||||
{ MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384,
|
||||
"TLS-DHE-PSK-WITH-ARIA-256-CBC-SHA384",
|
||||
MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C))
|
||||
{ MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256,
|
||||
"TLS-DHE-PSK-WITH-ARIA-128-GCM-SHA256",
|
||||
MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C))
|
||||
{ MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256,
|
||||
"TLS-DHE-PSK-WITH-ARIA-128-CBC-SHA256",
|
||||
MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
|
||||
0 },
|
||||
#endif
|
||||
|
||||
#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */
|
||||
|
||||
#endif /* MBEDTLS_ARIA_C */
|
||||
|
||||
|
||||
{ 0, "",
|
||||
MBEDTLS_CIPHER_NONE, MBEDTLS_MD_NONE, MBEDTLS_KEY_EXCHANGE_NONE,
|
||||
0, 0, 0, 0, 0 }
|
||||
@@ -1837,7 +2320,8 @@ mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg( const mbedtls_ssl_ciphers
|
||||
|
||||
#endif /* MBEDTLS_PK_C */
|
||||
|
||||
#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C)
|
||||
#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
|
||||
defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
|
||||
int mbedtls_ssl_ciphersuite_uses_ec( const mbedtls_ssl_ciphersuite_t *info )
|
||||
{
|
||||
switch( info->key_exchange )
|
||||
@@ -1847,13 +2331,14 @@ int mbedtls_ssl_ciphersuite_uses_ec( const mbedtls_ssl_ciphersuite_t *info )
|
||||
case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK:
|
||||
case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:
|
||||
case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:
|
||||
case MBEDTLS_KEY_EXCHANGE_ECJPAKE:
|
||||
return( 1 );
|
||||
|
||||
default:
|
||||
return( 0 );
|
||||
}
|
||||
}
|
||||
#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C */
|
||||
#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED*/
|
||||
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
|
||||
int mbedtls_ssl_ciphersuite_uses_psk( const mbedtls_ssl_ciphersuite_t *info )
|
||||
|
||||
@@ -57,7 +57,7 @@ static void ssl_write_hostname_ext( mbedtls_ssl_context *ssl,
|
||||
size_t *olen )
|
||||
{
|
||||
unsigned char *p = buf;
|
||||
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
|
||||
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
|
||||
size_t hostname_len;
|
||||
|
||||
*olen = 0;
|
||||
@@ -127,7 +127,7 @@ static void ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl,
|
||||
size_t *olen )
|
||||
{
|
||||
unsigned char *p = buf;
|
||||
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
|
||||
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
|
||||
|
||||
*olen = 0;
|
||||
|
||||
@@ -171,7 +171,7 @@ static void ssl_write_signature_algorithms_ext( mbedtls_ssl_context *ssl,
|
||||
size_t *olen )
|
||||
{
|
||||
unsigned char *p = buf;
|
||||
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
|
||||
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
|
||||
size_t sig_alg_len = 0;
|
||||
const int *md;
|
||||
#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C)
|
||||
@@ -256,7 +256,7 @@ static void ssl_write_supported_elliptic_curves_ext( mbedtls_ssl_context *ssl,
|
||||
size_t *olen )
|
||||
{
|
||||
unsigned char *p = buf;
|
||||
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
|
||||
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
|
||||
unsigned char *elliptic_curve_list = p + 6;
|
||||
size_t elliptic_curve_len = 0;
|
||||
const mbedtls_ecp_curve_info *info;
|
||||
@@ -329,7 +329,7 @@ static void ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl,
|
||||
size_t *olen )
|
||||
{
|
||||
unsigned char *p = buf;
|
||||
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
|
||||
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
|
||||
|
||||
*olen = 0;
|
||||
|
||||
@@ -362,7 +362,7 @@ static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl,
|
||||
{
|
||||
int ret;
|
||||
unsigned char *p = buf;
|
||||
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
|
||||
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
|
||||
size_t kkpp_len;
|
||||
|
||||
*olen = 0;
|
||||
@@ -439,7 +439,7 @@ static void ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl,
|
||||
size_t *olen )
|
||||
{
|
||||
unsigned char *p = buf;
|
||||
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
|
||||
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
|
||||
|
||||
*olen = 0;
|
||||
|
||||
@@ -472,7 +472,7 @@ static void ssl_write_truncated_hmac_ext( mbedtls_ssl_context *ssl,
|
||||
unsigned char *buf, size_t *olen )
|
||||
{
|
||||
unsigned char *p = buf;
|
||||
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
|
||||
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
|
||||
|
||||
*olen = 0;
|
||||
|
||||
@@ -504,7 +504,7 @@ static void ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl,
|
||||
unsigned char *buf, size_t *olen )
|
||||
{
|
||||
unsigned char *p = buf;
|
||||
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
|
||||
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
|
||||
|
||||
*olen = 0;
|
||||
|
||||
@@ -538,7 +538,7 @@ static void ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl,
|
||||
unsigned char *buf, size_t *olen )
|
||||
{
|
||||
unsigned char *p = buf;
|
||||
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
|
||||
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
|
||||
|
||||
*olen = 0;
|
||||
|
||||
@@ -572,7 +572,7 @@ static void ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl,
|
||||
unsigned char *buf, size_t *olen )
|
||||
{
|
||||
unsigned char *p = buf;
|
||||
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
|
||||
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
|
||||
size_t tlen = ssl->session_negotiate->ticket_len;
|
||||
|
||||
*olen = 0;
|
||||
@@ -616,7 +616,7 @@ static void ssl_write_alpn_ext( mbedtls_ssl_context *ssl,
|
||||
unsigned char *buf, size_t *olen )
|
||||
{
|
||||
unsigned char *p = buf;
|
||||
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
|
||||
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
|
||||
size_t alpnlen = 0;
|
||||
const char **cur;
|
||||
|
||||
@@ -766,6 +766,10 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl )
|
||||
unsigned char offer_compress;
|
||||
const int *ciphersuites;
|
||||
const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
|
||||
#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
|
||||
defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
|
||||
int uses_ec = 0;
|
||||
#endif
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write client hello" ) );
|
||||
|
||||
@@ -917,6 +921,11 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl )
|
||||
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %04x",
|
||||
ciphersuites[i] ) );
|
||||
|
||||
#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
|
||||
defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
|
||||
uses_ec |= mbedtls_ssl_ciphersuite_uses_ec( ciphersuite_info );
|
||||
#endif
|
||||
|
||||
n++;
|
||||
*p++ = (unsigned char)( ciphersuites[i] >> 8 );
|
||||
*p++ = (unsigned char)( ciphersuites[i] );
|
||||
@@ -1010,11 +1019,14 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl )
|
||||
|
||||
#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
|
||||
defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
|
||||
ssl_write_supported_elliptic_curves_ext( ssl, p + 2 + ext_len, &olen );
|
||||
ext_len += olen;
|
||||
if( uses_ec )
|
||||
{
|
||||
ssl_write_supported_elliptic_curves_ext( ssl, p + 2 + ext_len, &olen );
|
||||
ext_len += olen;
|
||||
|
||||
ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen );
|
||||
ext_len += olen;
|
||||
ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen );
|
||||
ext_len += olen;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
|
||||
@@ -1076,12 +1088,21 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl )
|
||||
mbedtls_ssl_send_flight_completed( ssl );
|
||||
#endif
|
||||
|
||||
if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
|
||||
if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
||||
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
|
||||
( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret );
|
||||
return( ret );
|
||||
}
|
||||
#endif /* MBEDTLS_SSL_PROTO_DTLS */
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write client hello" ) );
|
||||
|
||||
return( 0 );
|
||||
@@ -1247,14 +1268,14 @@ static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl,
|
||||
size_t list_size;
|
||||
const unsigned char *p;
|
||||
|
||||
list_size = buf[0];
|
||||
if( list_size + 1 != len )
|
||||
if( len == 0 || (size_t)( buf[0] + 1 ) != len )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
|
||||
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
|
||||
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
|
||||
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
|
||||
}
|
||||
list_size = buf[0];
|
||||
|
||||
p = buf + 1;
|
||||
while( list_size > 0 )
|
||||
@@ -1479,7 +1500,7 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
|
||||
|
||||
buf = ssl->in_msg;
|
||||
|
||||
if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
|
||||
if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
|
||||
{
|
||||
/* No alert on a read error. */
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
|
||||
@@ -1742,6 +1763,14 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s", suite_info->name ) );
|
||||
|
||||
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
|
||||
if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA &&
|
||||
ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
|
||||
{
|
||||
ssl->handshake->ecrs_enabled = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if( comp != MBEDTLS_SSL_COMPRESS_NULL
|
||||
#if defined(MBEDTLS_ZLIB_SUPPORT)
|
||||
&& comp != MBEDTLS_SSL_COMPRESS_DEFLATE
|
||||
@@ -2047,6 +2076,10 @@ static int ssl_parse_server_ecdh_params( mbedtls_ssl_context *ssl,
|
||||
(const unsigned char **) p, end ) ) != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_read_params" ), ret );
|
||||
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
|
||||
if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
|
||||
ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
|
||||
#endif
|
||||
return( ret );
|
||||
}
|
||||
|
||||
@@ -2117,7 +2150,7 @@ static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl,
|
||||
size_t len_bytes = ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ? 0 : 2;
|
||||
unsigned char *p = ssl->handshake->premaster + pms_offset;
|
||||
|
||||
if( offset + len_bytes > MBEDTLS_SSL_MAX_CONTENT_LEN )
|
||||
if( offset + len_bytes > MBEDTLS_SSL_OUT_CONTENT_LEN )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small for encrypted pms" ) );
|
||||
return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
|
||||
@@ -2160,7 +2193,7 @@ static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl,
|
||||
if( ( ret = mbedtls_pk_encrypt( &ssl->session_negotiate->peer_cert->pk,
|
||||
p, ssl->handshake->pmslen,
|
||||
ssl->out_msg + offset + len_bytes, olen,
|
||||
MBEDTLS_SSL_MAX_CONTENT_LEN - offset - len_bytes,
|
||||
MBEDTLS_SSL_OUT_CONTENT_LEN - offset - len_bytes,
|
||||
ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_rsa_pkcs1_encrypt", ret );
|
||||
@@ -2328,7 +2361,15 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
|
||||
#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED ||
|
||||
MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
|
||||
|
||||
if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
|
||||
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
|
||||
if( ssl->handshake->ecrs_enabled &&
|
||||
ssl->handshake->ecrs_state == ssl_ecrs_ske_start_processing )
|
||||
{
|
||||
goto start_processing;
|
||||
}
|
||||
#endif
|
||||
|
||||
if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
|
||||
return( ret );
|
||||
@@ -2365,6 +2406,12 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
|
||||
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
|
||||
if( ssl->handshake->ecrs_enabled )
|
||||
ssl->handshake->ecrs_state = ssl_ecrs_ske_start_processing;
|
||||
|
||||
start_processing:
|
||||
#endif
|
||||
p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl );
|
||||
end = ssl->in_msg + ssl->in_hslen;
|
||||
MBEDTLS_SSL_DEBUG_BUF( 3, "server key exchange", p, end - p );
|
||||
@@ -2457,6 +2504,7 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
|
||||
mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE;
|
||||
unsigned char *params = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl );
|
||||
size_t params_len = p - params;
|
||||
void *rs_ctx = NULL;
|
||||
|
||||
/*
|
||||
* Handle the digitally-signed structure
|
||||
@@ -2544,10 +2592,9 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
|
||||
defined(MBEDTLS_SSL_PROTO_TLS1_2)
|
||||
if( md_alg != MBEDTLS_MD_NONE )
|
||||
{
|
||||
/* Info from md_alg will be used instead */
|
||||
hashlen = 0;
|
||||
ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash, params,
|
||||
params_len, md_alg );
|
||||
ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash, &hashlen,
|
||||
params, params_len,
|
||||
md_alg );
|
||||
if( ret != 0 )
|
||||
return( ret );
|
||||
}
|
||||
@@ -2559,8 +2606,7 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
|
||||
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
|
||||
}
|
||||
|
||||
MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen != 0 ? hashlen :
|
||||
(unsigned int) ( mbedtls_md_get_size( mbedtls_md_info_from_type( md_alg ) ) ) );
|
||||
MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen );
|
||||
|
||||
if( ssl->session_negotiate->peer_cert == NULL )
|
||||
{
|
||||
@@ -2581,12 +2627,25 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
|
||||
return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH );
|
||||
}
|
||||
|
||||
if( ( ret = mbedtls_pk_verify( &ssl->session_negotiate->peer_cert->pk,
|
||||
md_alg, hash, hashlen, p, sig_len ) ) != 0 )
|
||||
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
|
||||
if( ssl->handshake->ecrs_enabled )
|
||||
rs_ctx = &ssl->handshake->ecrs_ctx.pk;
|
||||
#endif
|
||||
|
||||
if( ( ret = mbedtls_pk_verify_restartable(
|
||||
&ssl->session_negotiate->peer_cert->pk,
|
||||
md_alg, hash, hashlen, p, sig_len, rs_ctx ) ) != 0 )
|
||||
{
|
||||
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
|
||||
MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR );
|
||||
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
|
||||
if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
|
||||
#endif
|
||||
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
|
||||
MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR );
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret );
|
||||
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
|
||||
if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
|
||||
ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
|
||||
#endif
|
||||
return( ret );
|
||||
}
|
||||
}
|
||||
@@ -2637,7 +2696,7 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl )
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
|
||||
if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
|
||||
return( ret );
|
||||
@@ -2789,7 +2848,7 @@ static int ssl_parse_server_hello_done( mbedtls_ssl_context *ssl )
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server hello done" ) );
|
||||
|
||||
if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
|
||||
if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
|
||||
return( ret );
|
||||
@@ -2884,6 +2943,16 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
|
||||
*/
|
||||
i = 4;
|
||||
|
||||
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
|
||||
if( ssl->handshake->ecrs_enabled )
|
||||
{
|
||||
if( ssl->handshake->ecrs_state == ssl_ecrs_cke_ecdh_calc_secret )
|
||||
goto ecdh_calc_secret;
|
||||
|
||||
mbedtls_ecdh_enable_restart( &ssl->handshake->ecdh_ctx );
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx,
|
||||
&n,
|
||||
&ssl->out_msg[i], 1000,
|
||||
@@ -2891,11 +2960,26 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
|
||||
if( ret != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_public", ret );
|
||||
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
|
||||
if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
|
||||
ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
|
||||
#endif
|
||||
return( ret );
|
||||
}
|
||||
|
||||
MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q", &ssl->handshake->ecdh_ctx.Q );
|
||||
|
||||
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
|
||||
if( ssl->handshake->ecrs_enabled )
|
||||
{
|
||||
ssl->handshake->ecrs_n = n;
|
||||
ssl->handshake->ecrs_state = ssl_ecrs_cke_ecdh_calc_secret;
|
||||
}
|
||||
|
||||
ecdh_calc_secret:
|
||||
if( ssl->handshake->ecrs_enabled )
|
||||
n = ssl->handshake->ecrs_n;
|
||||
#endif
|
||||
if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx,
|
||||
&ssl->handshake->pmslen,
|
||||
ssl->handshake->premaster,
|
||||
@@ -2903,6 +2987,10 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
|
||||
ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret );
|
||||
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
|
||||
if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
|
||||
ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
|
||||
#endif
|
||||
return( ret );
|
||||
}
|
||||
|
||||
@@ -2928,7 +3016,7 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
|
||||
i = 4;
|
||||
n = ssl->conf->psk_identity_len;
|
||||
|
||||
if( i + 2 + n > MBEDTLS_SSL_MAX_CONTENT_LEN )
|
||||
if( i + 2 + n > MBEDTLS_SSL_OUT_CONTENT_LEN )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "psk identity too long or "
|
||||
"SSL buffer too short" ) );
|
||||
@@ -2964,7 +3052,7 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
|
||||
*/
|
||||
n = ssl->handshake->dhm_ctx.len;
|
||||
|
||||
if( i + 2 + n > MBEDTLS_SSL_MAX_CONTENT_LEN )
|
||||
if( i + 2 + n > MBEDTLS_SSL_OUT_CONTENT_LEN )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "psk identity or DHM size too long"
|
||||
" or SSL buffer too short" ) );
|
||||
@@ -2993,7 +3081,7 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
|
||||
* ClientECDiffieHellmanPublic public;
|
||||
*/
|
||||
ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx, &n,
|
||||
&ssl->out_msg[i], MBEDTLS_SSL_MAX_CONTENT_LEN - i,
|
||||
&ssl->out_msg[i], MBEDTLS_SSL_OUT_CONTENT_LEN - i,
|
||||
ssl->conf->f_rng, ssl->conf->p_rng );
|
||||
if( ret != 0 )
|
||||
{
|
||||
@@ -3034,7 +3122,7 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
|
||||
i = 4;
|
||||
|
||||
ret = mbedtls_ecjpake_write_round_two( &ssl->handshake->ecjpake_ctx,
|
||||
ssl->out_msg + i, MBEDTLS_SSL_MAX_CONTENT_LEN - i, &n,
|
||||
ssl->out_msg + i, MBEDTLS_SSL_OUT_CONTENT_LEN - i, &n,
|
||||
ssl->conf->f_rng, ssl->conf->p_rng );
|
||||
if( ret != 0 )
|
||||
{
|
||||
@@ -3065,9 +3153,9 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
|
||||
|
||||
ssl->state++;
|
||||
|
||||
if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
|
||||
if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
@@ -3121,9 +3209,18 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl )
|
||||
unsigned char *hash_start = hash;
|
||||
mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE;
|
||||
unsigned int hashlen;
|
||||
void *rs_ctx = NULL;
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) );
|
||||
|
||||
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
|
||||
if( ssl->handshake->ecrs_enabled &&
|
||||
ssl->handshake->ecrs_state == ssl_ecrs_crt_vrfy_sign )
|
||||
{
|
||||
goto sign;
|
||||
}
|
||||
#endif
|
||||
|
||||
if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret );
|
||||
@@ -3155,8 +3252,15 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl )
|
||||
}
|
||||
|
||||
/*
|
||||
* Make an RSA signature of the handshake digests
|
||||
* Make a signature of the handshake digests
|
||||
*/
|
||||
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
|
||||
if( ssl->handshake->ecrs_enabled )
|
||||
ssl->handshake->ecrs_state = ssl_ecrs_crt_vrfy_sign;
|
||||
|
||||
sign:
|
||||
#endif
|
||||
|
||||
ssl->handshake->calc_verify( ssl, hash );
|
||||
|
||||
#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
|
||||
@@ -3233,11 +3337,21 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl )
|
||||
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
|
||||
}
|
||||
|
||||
if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ), md_alg, hash_start, hashlen,
|
||||
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
|
||||
if( ssl->handshake->ecrs_enabled )
|
||||
rs_ctx = &ssl->handshake->ecrs_ctx.pk;
|
||||
#endif
|
||||
|
||||
if( ( ret = mbedtls_pk_sign_restartable( mbedtls_ssl_own_key( ssl ),
|
||||
md_alg, hash_start, hashlen,
|
||||
ssl->out_msg + 6 + offset, &n,
|
||||
ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
|
||||
ssl->conf->f_rng, ssl->conf->p_rng, rs_ctx ) ) != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret );
|
||||
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
|
||||
if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
|
||||
ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
|
||||
#endif
|
||||
return( ret );
|
||||
}
|
||||
|
||||
@@ -3250,9 +3364,9 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl )
|
||||
|
||||
ssl->state++;
|
||||
|
||||
if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
|
||||
if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
@@ -3278,7 +3392,7 @@ static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl )
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse new session ticket" ) );
|
||||
|
||||
if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
|
||||
if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
|
||||
return( ret );
|
||||
@@ -3313,8 +3427,8 @@ static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl )
|
||||
|
||||
msg = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl );
|
||||
|
||||
lifetime = ( msg[0] << 24 ) | ( msg[1] << 16 ) |
|
||||
( msg[2] << 8 ) | ( msg[3] );
|
||||
lifetime = ( ((uint32_t) msg[0]) << 24 ) | ( msg[1] << 16 ) |
|
||||
( msg[2] << 8 ) | ( msg[3] );
|
||||
|
||||
ticket_len = ( msg[4] << 8 ) | ( msg[5] );
|
||||
|
||||
@@ -3392,10 +3506,10 @@ int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl )
|
||||
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
|
||||
ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING )
|
||||
{
|
||||
if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 )
|
||||
if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
|
||||
return( ret );
|
||||
}
|
||||
#endif
|
||||
#endif /* MBEDTLS_SSL_PROTO_DTLS */
|
||||
|
||||
/* Change state now, so that it is right in mbedtls_ssl_read_record(), used
|
||||
* by DTLS for dropping out-of-sequence ChangeCipherSpec records */
|
||||
|
||||
@@ -91,6 +91,13 @@ static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl,
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 3, ( "parse ServerName extension" ) );
|
||||
|
||||
if( len < 2 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
|
||||
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
|
||||
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
|
||||
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
|
||||
}
|
||||
servername_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) );
|
||||
if( servername_list_size + 2 != len )
|
||||
{
|
||||
@@ -101,7 +108,7 @@ static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl,
|
||||
}
|
||||
|
||||
p = buf + 2;
|
||||
while( servername_list_size > 0 )
|
||||
while( servername_list_size > 2 )
|
||||
{
|
||||
hostname_len = ( ( p[1] << 8 ) | p[2] );
|
||||
if( hostname_len + 3 > servername_list_size )
|
||||
@@ -205,6 +212,12 @@ static int ssl_parse_signature_algorithms_ext( mbedtls_ssl_context *ssl,
|
||||
mbedtls_md_type_t md_cur;
|
||||
mbedtls_pk_type_t sig_cur;
|
||||
|
||||
if ( len < 2 ) {
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
|
||||
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
|
||||
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
|
||||
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
|
||||
}
|
||||
sig_alg_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) );
|
||||
if( sig_alg_list_size + 2 != len ||
|
||||
sig_alg_list_size % 2 != 0 )
|
||||
@@ -273,6 +286,12 @@ static int ssl_parse_supported_elliptic_curves( mbedtls_ssl_context *ssl,
|
||||
const unsigned char *p;
|
||||
const mbedtls_ecp_curve_info *curve_info, **curves;
|
||||
|
||||
if ( len < 2 ) {
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
|
||||
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
|
||||
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
|
||||
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
|
||||
}
|
||||
list_size = ( ( buf[0] << 8 ) | ( buf[1] ) );
|
||||
if( list_size + 2 != len ||
|
||||
list_size % 2 != 0 )
|
||||
@@ -332,14 +351,14 @@ static int ssl_parse_supported_point_formats( mbedtls_ssl_context *ssl,
|
||||
size_t list_size;
|
||||
const unsigned char *p;
|
||||
|
||||
list_size = buf[0];
|
||||
if( list_size + 1 != len )
|
||||
if( len == 0 || (size_t)( buf[0] + 1 ) != len )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
|
||||
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
|
||||
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
|
||||
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
|
||||
}
|
||||
list_size = buf[0];
|
||||
|
||||
p = buf + 1;
|
||||
while( list_size > 0 )
|
||||
@@ -709,7 +728,7 @@ static int ssl_pick_cert( mbedtls_ssl_context *ssl,
|
||||
MBEDTLS_SSL_DEBUG_CRT( 3, "candidate certificate chain, certificate",
|
||||
cur->cert );
|
||||
|
||||
if( ! mbedtls_pk_can_do( cur->key, pk_alg ) )
|
||||
if( ! mbedtls_pk_can_do( &cur->cert->pk, pk_alg ) )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: key type" ) );
|
||||
continue;
|
||||
@@ -733,7 +752,7 @@ static int ssl_pick_cert( mbedtls_ssl_context *ssl,
|
||||
|
||||
#if defined(MBEDTLS_ECDSA_C)
|
||||
if( pk_alg == MBEDTLS_PK_ECDSA &&
|
||||
ssl_check_key_curve( cur->key, ssl->handshake->curves ) != 0 )
|
||||
ssl_check_key_curve( &cur->cert->pk, ssl->handshake->curves ) != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: elliptic curve" ) );
|
||||
continue;
|
||||
@@ -1275,7 +1294,7 @@ read_record_header:
|
||||
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
|
||||
}
|
||||
|
||||
memcpy( ssl->out_ctr + 2, ssl->in_ctr + 2, 6 );
|
||||
memcpy( ssl->cur_out_ctr + 2, ssl->in_ctr + 2, 6 );
|
||||
|
||||
#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
|
||||
if( mbedtls_ssl_dtls_replay_check( ssl ) != 0 )
|
||||
@@ -1303,7 +1322,7 @@ read_record_header:
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if( msg_len > MBEDTLS_SSL_MAX_CONTENT_LEN )
|
||||
if( msg_len > MBEDTLS_SSL_IN_CONTENT_LEN )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
|
||||
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
|
||||
@@ -1656,10 +1675,16 @@ read_record_header:
|
||||
|
||||
while( ext_len != 0 )
|
||||
{
|
||||
unsigned int ext_id = ( ( ext[0] << 8 )
|
||||
| ( ext[1] ) );
|
||||
unsigned int ext_size = ( ( ext[2] << 8 )
|
||||
| ( ext[3] ) );
|
||||
unsigned int ext_id;
|
||||
unsigned int ext_size;
|
||||
if ( ext_len < 4 ) {
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
|
||||
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
|
||||
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
|
||||
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
|
||||
}
|
||||
ext_id = ( ( ext[0] << 8 ) | ( ext[1] ) );
|
||||
ext_size = ( ( ext[2] << 8 ) | ( ext[3] ) );
|
||||
|
||||
if( ext_size + 4 > ext_len )
|
||||
{
|
||||
@@ -2235,7 +2260,7 @@ static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl,
|
||||
{
|
||||
int ret;
|
||||
unsigned char *p = buf;
|
||||
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
|
||||
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
|
||||
size_t kkpp_len;
|
||||
|
||||
*olen = 0;
|
||||
@@ -2342,7 +2367,7 @@ static int ssl_write_hello_verify_request( mbedtls_ssl_context *ssl )
|
||||
cookie_len_byte = p++;
|
||||
|
||||
if( ( ret = ssl->conf->f_cookie_write( ssl->conf->p_cookie,
|
||||
&p, ssl->out_buf + MBEDTLS_SSL_BUFFER_LEN,
|
||||
&p, ssl->out_buf + MBEDTLS_SSL_OUT_BUFFER_LEN,
|
||||
ssl->cli_id, ssl->cli_id_len ) ) != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "f_cookie_write", ret );
|
||||
@@ -2359,12 +2384,21 @@ static int ssl_write_hello_verify_request( mbedtls_ssl_context *ssl )
|
||||
|
||||
ssl->state = MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT;
|
||||
|
||||
if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
|
||||
if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
||||
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
|
||||
( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret );
|
||||
return( ret );
|
||||
}
|
||||
#endif /* MBEDTLS_SSL_PROTO_DTLS */
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write hello verify request" ) );
|
||||
|
||||
return( 0 );
|
||||
@@ -2564,8 +2598,12 @@ static int ssl_write_server_hello( mbedtls_ssl_context *ssl )
|
||||
|
||||
#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
|
||||
defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
|
||||
ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen );
|
||||
ext_len += olen;
|
||||
if ( mbedtls_ssl_ciphersuite_uses_ec(
|
||||
mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite ) ) )
|
||||
{
|
||||
ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen );
|
||||
ext_len += olen;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
|
||||
@@ -2595,7 +2633,7 @@ static int ssl_write_server_hello( mbedtls_ssl_context *ssl )
|
||||
ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
|
||||
ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_HELLO;
|
||||
|
||||
ret = mbedtls_ssl_write_record( ssl );
|
||||
ret = mbedtls_ssl_write_handshake_msg( ssl );
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello" ) );
|
||||
|
||||
@@ -2638,7 +2676,7 @@ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl )
|
||||
size_t dn_size, total_dn_size; /* excluding length bytes */
|
||||
size_t ct_len, sa_len; /* including length bytes */
|
||||
unsigned char *buf, *p;
|
||||
const unsigned char * const end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
|
||||
const unsigned char * const end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
|
||||
const mbedtls_x509_crt *crt;
|
||||
int authmode;
|
||||
|
||||
@@ -2790,7 +2828,7 @@ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl )
|
||||
ssl->out_msg[4 + ct_len + sa_len] = (unsigned char)( total_dn_size >> 8 );
|
||||
ssl->out_msg[5 + ct_len + sa_len] = (unsigned char)( total_dn_size );
|
||||
|
||||
ret = mbedtls_ssl_write_record( ssl );
|
||||
ret = mbedtls_ssl_write_handshake_msg( ssl );
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate request" ) );
|
||||
|
||||
@@ -2828,54 +2866,56 @@ static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl )
|
||||
#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||
|
||||
MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
|
||||
|
||||
static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) && \
|
||||
defined(MBEDTLS_SSL_ASYNC_PRIVATE)
|
||||
static int ssl_resume_server_key_exchange( mbedtls_ssl_context *ssl,
|
||||
size_t *signature_len )
|
||||
{
|
||||
/* Append the signature to ssl->out_msg, leaving 2 bytes for the
|
||||
* signature length which will be added in ssl_write_server_key_exchange
|
||||
* after the call to ssl_prepare_server_key_exchange.
|
||||
* ssl_write_server_key_exchange also takes care of incrementing
|
||||
* ssl->out_msglen. */
|
||||
unsigned char *sig_start = ssl->out_msg + ssl->out_msglen + 2;
|
||||
size_t sig_max_len = ( ssl->out_buf + MBEDTLS_SSL_OUT_CONTENT_LEN
|
||||
- sig_start );
|
||||
int ret = ssl->conf->f_async_resume( ssl,
|
||||
sig_start, signature_len, sig_max_len );
|
||||
if( ret != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS )
|
||||
{
|
||||
ssl->handshake->async_in_progress = 0;
|
||||
mbedtls_ssl_set_async_operation_data( ssl, NULL );
|
||||
}
|
||||
MBEDTLS_SSL_DEBUG_RET( 2, "ssl_resume_server_key_exchange", ret );
|
||||
return( ret );
|
||||
}
|
||||
#endif /* defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) &&
|
||||
defined(MBEDTLS_SSL_ASYNC_PRIVATE) */
|
||||
|
||||
/* Prepare the ServerKeyExchange message, up to and including
|
||||
* calculating the signature if any, but excluding formatting the
|
||||
* signature and sending the message. */
|
||||
static int ssl_prepare_server_key_exchange( mbedtls_ssl_context *ssl,
|
||||
size_t *signature_len )
|
||||
{
|
||||
int ret;
|
||||
size_t n = 0;
|
||||
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
|
||||
ssl->transform_negotiate->ciphersuite_info;
|
||||
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED)
|
||||
unsigned char *p = ssl->out_msg + 4;
|
||||
size_t len;
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED)
|
||||
unsigned char *dig_signed = p;
|
||||
size_t dig_signed_len = 0;
|
||||
unsigned char *dig_signed = NULL;
|
||||
#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */
|
||||
#endif /* MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED */
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) );
|
||||
(void) ciphersuite_info; /* unused in some configurations */
|
||||
#if !defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED)
|
||||
(void) signature_len;
|
||||
#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */
|
||||
|
||||
ssl->out_msglen = 4; /* header (type:1, length:3) to be written later */
|
||||
|
||||
/*
|
||||
*
|
||||
* Part 1: Extract static ECDH parameters and abort
|
||||
* if ServerKeyExchange not needed.
|
||||
*
|
||||
*/
|
||||
|
||||
/* For suites involving ECDH, extract DH parameters
|
||||
* from certificate at this point. */
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED)
|
||||
if( mbedtls_ssl_ciphersuite_uses_ecdh( ciphersuite_info ) )
|
||||
{
|
||||
ssl_get_ecdh_params_from_cert( ssl );
|
||||
}
|
||||
#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED */
|
||||
|
||||
/* Key exchanges not involving ephemeral keys don't use
|
||||
* ServerKeyExchange, so end here. */
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED)
|
||||
if( mbedtls_ssl_ciphersuite_no_pfs( ciphersuite_info ) )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) );
|
||||
ssl->state++;
|
||||
return( 0 );
|
||||
}
|
||||
#endif /* MBEDTLS_KEY_EXCHANGE__NON_PFS__ENABLED */
|
||||
|
||||
/*
|
||||
*
|
||||
* Part 2: Provide key exchange parameters for chosen ciphersuite.
|
||||
* Part 1: Provide key exchange parameters for chosen ciphersuite.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -2885,18 +2925,21 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
|
||||
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
|
||||
{
|
||||
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
|
||||
int ret;
|
||||
size_t len = 0;
|
||||
|
||||
ret = mbedtls_ecjpake_write_round_two( &ssl->handshake->ecjpake_ctx,
|
||||
p, end - p, &len, ssl->conf->f_rng, ssl->conf->p_rng );
|
||||
ret = mbedtls_ecjpake_write_round_two(
|
||||
&ssl->handshake->ecjpake_ctx,
|
||||
ssl->out_msg + ssl->out_msglen,
|
||||
MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen, &len,
|
||||
ssl->conf->f_rng, ssl->conf->p_rng );
|
||||
if( ret != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_write_round_two", ret );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
p += len;
|
||||
n += len;
|
||||
ssl->out_msglen += len;
|
||||
}
|
||||
#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
|
||||
|
||||
@@ -2910,10 +2953,8 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
|
||||
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
|
||||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK )
|
||||
{
|
||||
*(p++) = 0x00;
|
||||
*(p++) = 0x00;
|
||||
|
||||
n += 2;
|
||||
ssl->out_msg[ssl->out_msglen++] = 0x00;
|
||||
ssl->out_msg[ssl->out_msglen++] = 0x00;
|
||||
}
|
||||
#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED ||
|
||||
MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
|
||||
@@ -2924,6 +2965,9 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED)
|
||||
if( mbedtls_ssl_ciphersuite_uses_dhe( ciphersuite_info ) )
|
||||
{
|
||||
int ret;
|
||||
size_t len = 0;
|
||||
|
||||
if( ssl->conf->dhm_P.p == NULL || ssl->conf->dhm_G.p == NULL )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "no DH parameters set" ) );
|
||||
@@ -2947,21 +2991,21 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
|
||||
return( ret );
|
||||
}
|
||||
|
||||
if( ( ret = mbedtls_dhm_make_params( &ssl->handshake->dhm_ctx,
|
||||
(int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ),
|
||||
p, &len, ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
|
||||
if( ( ret = mbedtls_dhm_make_params(
|
||||
&ssl->handshake->dhm_ctx,
|
||||
(int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ),
|
||||
ssl->out_msg + ssl->out_msglen, &len,
|
||||
ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_params", ret );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED)
|
||||
dig_signed = p;
|
||||
dig_signed_len = len;
|
||||
dig_signed = ssl->out_msg + ssl->out_msglen;
|
||||
#endif
|
||||
|
||||
p += len;
|
||||
n += len;
|
||||
ssl->out_msglen += len;
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X );
|
||||
MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P );
|
||||
@@ -2986,6 +3030,8 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
|
||||
*/
|
||||
const mbedtls_ecp_curve_info **curve = NULL;
|
||||
const mbedtls_ecp_group_id *gid;
|
||||
int ret;
|
||||
size_t len = 0;
|
||||
|
||||
/* Match our preference list against the offered curves */
|
||||
for( gid = ssl->conf->curve_list; *gid != MBEDTLS_ECP_DP_NONE; gid++ )
|
||||
@@ -3009,21 +3055,21 @@ curve_matching_done:
|
||||
return( ret );
|
||||
}
|
||||
|
||||
if( ( ret = mbedtls_ecdh_make_params( &ssl->handshake->ecdh_ctx, &len,
|
||||
p, MBEDTLS_SSL_MAX_CONTENT_LEN - n,
|
||||
ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
|
||||
if( ( ret = mbedtls_ecdh_make_params(
|
||||
&ssl->handshake->ecdh_ctx, &len,
|
||||
ssl->out_msg + ssl->out_msglen,
|
||||
MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen,
|
||||
ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_params", ret );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED)
|
||||
dig_signed = p;
|
||||
dig_signed_len = len;
|
||||
dig_signed = ssl->out_msg + ssl->out_msglen;
|
||||
#endif
|
||||
|
||||
p += len;
|
||||
n += len;
|
||||
ssl->out_msglen += len;
|
||||
|
||||
MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q ", &ssl->handshake->ecdh_ctx.Q );
|
||||
}
|
||||
@@ -3031,19 +3077,20 @@ curve_matching_done:
|
||||
|
||||
/*
|
||||
*
|
||||
* Part 3: For key exchanges involving the server signing the
|
||||
* Part 2: For key exchanges involving the server signing the
|
||||
* exchange parameters, compute and add the signature here.
|
||||
*
|
||||
*/
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED)
|
||||
if( mbedtls_ssl_ciphersuite_uses_server_signature( ciphersuite_info ) )
|
||||
{
|
||||
size_t signature_len = 0;
|
||||
unsigned int hashlen = 0;
|
||||
unsigned char hash[64];
|
||||
size_t dig_signed_len = ssl->out_msg + ssl->out_msglen - dig_signed;
|
||||
size_t hashlen = 0;
|
||||
unsigned char hash[MBEDTLS_MD_MAX_SIZE];
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* 3.1: Choose hash algorithm:
|
||||
* 2.1: Choose hash algorithm:
|
||||
* A: For TLS 1.2, obey signature-hash-algorithm extension
|
||||
* to choose appropriate hash.
|
||||
* B: For SSL3, TLS1.0, TLS1.1 and ECDHE_ECDSA, use SHA1
|
||||
@@ -3090,7 +3137,7 @@ curve_matching_done:
|
||||
MBEDTLS_SSL_DEBUG_MSG( 3, ( "pick hash algorithm %d for signing", md_alg ) );
|
||||
|
||||
/*
|
||||
* 3.2: Compute the hash to be signed
|
||||
* 2.2: Compute the hash to be signed
|
||||
*/
|
||||
#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
|
||||
defined(MBEDTLS_SSL_PROTO_TLS1_1)
|
||||
@@ -3110,9 +3157,7 @@ curve_matching_done:
|
||||
defined(MBEDTLS_SSL_PROTO_TLS1_2)
|
||||
if( md_alg != MBEDTLS_MD_NONE )
|
||||
{
|
||||
/* Info from md_alg will be used instead */
|
||||
hashlen = 0;
|
||||
ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash,
|
||||
ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash, &hashlen,
|
||||
dig_signed,
|
||||
dig_signed_len,
|
||||
md_alg );
|
||||
@@ -3127,18 +3172,11 @@ curve_matching_done:
|
||||
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
|
||||
}
|
||||
|
||||
MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen != 0 ? hashlen :
|
||||
(unsigned int) ( mbedtls_md_get_size( mbedtls_md_info_from_type( md_alg ) ) ) );
|
||||
MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen );
|
||||
|
||||
/*
|
||||
* 3.3: Compute and add the signature
|
||||
* 2.3: Compute and add the signature
|
||||
*/
|
||||
if( mbedtls_ssl_own_key( ssl ) == NULL )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key" ) );
|
||||
return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
|
||||
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
|
||||
{
|
||||
@@ -3158,46 +3196,162 @@ curve_matching_done:
|
||||
*
|
||||
*/
|
||||
|
||||
*(p++) = mbedtls_ssl_hash_from_md_alg( md_alg );
|
||||
*(p++) = mbedtls_ssl_sig_from_pk_alg( sig_alg );
|
||||
|
||||
n += 2;
|
||||
ssl->out_msg[ssl->out_msglen++] =
|
||||
mbedtls_ssl_hash_from_md_alg( md_alg );
|
||||
ssl->out_msg[ssl->out_msglen++] =
|
||||
mbedtls_ssl_sig_from_pk_alg( sig_alg );
|
||||
}
|
||||
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
|
||||
|
||||
if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ), md_alg, hash, hashlen,
|
||||
p + 2 , &signature_len, ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
|
||||
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
|
||||
if( ssl->conf->f_async_sign_start != NULL )
|
||||
{
|
||||
ret = ssl->conf->f_async_sign_start( ssl,
|
||||
mbedtls_ssl_own_cert( ssl ),
|
||||
md_alg, hash, hashlen );
|
||||
switch( ret )
|
||||
{
|
||||
case MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH:
|
||||
/* act as if f_async_sign was null */
|
||||
break;
|
||||
case 0:
|
||||
ssl->handshake->async_in_progress = 1;
|
||||
return( ssl_resume_server_key_exchange( ssl, signature_len ) );
|
||||
case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS:
|
||||
ssl->handshake->async_in_progress = 1;
|
||||
return( MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS );
|
||||
default:
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "f_async_sign_start", ret );
|
||||
return( ret );
|
||||
}
|
||||
}
|
||||
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
|
||||
|
||||
if( mbedtls_ssl_own_key( ssl ) == NULL )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key" ) );
|
||||
return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED );
|
||||
}
|
||||
|
||||
/* Append the signature to ssl->out_msg, leaving 2 bytes for the
|
||||
* signature length which will be added in ssl_write_server_key_exchange
|
||||
* after the call to ssl_prepare_server_key_exchange.
|
||||
* ssl_write_server_key_exchange also takes care of incrementing
|
||||
* ssl->out_msglen. */
|
||||
if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ),
|
||||
md_alg, hash, hashlen,
|
||||
ssl->out_msg + ssl->out_msglen + 2,
|
||||
signature_len,
|
||||
ssl->conf->f_rng,
|
||||
ssl->conf->p_rng ) ) != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
*(p++) = (unsigned char)( signature_len >> 8 );
|
||||
*(p++) = (unsigned char)( signature_len );
|
||||
n += 2;
|
||||
|
||||
MBEDTLS_SSL_DEBUG_BUF( 3, "my signature", p, signature_len );
|
||||
|
||||
n += signature_len;
|
||||
}
|
||||
#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */
|
||||
|
||||
/* Done with actual work; add header and send. */
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
ssl->out_msglen = 4 + n;
|
||||
/* Prepare the ServerKeyExchange message and send it. For ciphersuites
|
||||
* that do not include a ServerKeyExchange message, do nothing. Either
|
||||
* way, if successful, move on to the next step in the SSL state
|
||||
* machine. */
|
||||
static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
|
||||
{
|
||||
int ret;
|
||||
size_t signature_len = 0;
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED)
|
||||
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
|
||||
ssl->transform_negotiate->ciphersuite_info;
|
||||
#endif /* MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED */
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) );
|
||||
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED)
|
||||
/* Extract static ECDH parameters and abort if ServerKeyExchange
|
||||
* is not needed. */
|
||||
if( mbedtls_ssl_ciphersuite_no_pfs( ciphersuite_info ) )
|
||||
{
|
||||
/* For suites involving ECDH, extract DH parameters
|
||||
* from certificate at this point. */
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED)
|
||||
if( mbedtls_ssl_ciphersuite_uses_ecdh( ciphersuite_info ) )
|
||||
{
|
||||
ssl_get_ecdh_params_from_cert( ssl );
|
||||
}
|
||||
#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED */
|
||||
|
||||
/* Key exchanges not involving ephemeral keys don't use
|
||||
* ServerKeyExchange, so end here. */
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) );
|
||||
ssl->state++;
|
||||
return( 0 );
|
||||
}
|
||||
#endif /* MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED */
|
||||
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) && \
|
||||
defined(MBEDTLS_SSL_ASYNC_PRIVATE)
|
||||
/* If we have already prepared the message and there is an ongoing
|
||||
* signature operation, resume signing. */
|
||||
if( ssl->handshake->async_in_progress != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "resuming signature operation" ) );
|
||||
ret = ssl_resume_server_key_exchange( ssl, &signature_len );
|
||||
}
|
||||
else
|
||||
#endif /* defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) &&
|
||||
defined(MBEDTLS_SSL_ASYNC_PRIVATE) */
|
||||
{
|
||||
/* ServerKeyExchange is needed. Prepare the message. */
|
||||
ret = ssl_prepare_server_key_exchange( ssl, &signature_len );
|
||||
}
|
||||
|
||||
if( ret != 0 )
|
||||
{
|
||||
/* If we're starting to write a new message, set ssl->out_msglen
|
||||
* to 0. But if we're resuming after an asynchronous message,
|
||||
* out_msglen is the amount of data written so far and mst be
|
||||
* preserved. */
|
||||
if( ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS )
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server key exchange (pending)" ) );
|
||||
else
|
||||
ssl->out_msglen = 0;
|
||||
return( ret );
|
||||
}
|
||||
|
||||
/* If there is a signature, write its length.
|
||||
* ssl_prepare_server_key_exchange already wrote the signature
|
||||
* itself at its proper place in the output buffer. */
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED)
|
||||
if( signature_len != 0 )
|
||||
{
|
||||
ssl->out_msg[ssl->out_msglen++] = (unsigned char)( signature_len >> 8 );
|
||||
ssl->out_msg[ssl->out_msglen++] = (unsigned char)( signature_len );
|
||||
|
||||
MBEDTLS_SSL_DEBUG_BUF( 3, "my signature",
|
||||
ssl->out_msg + ssl->out_msglen,
|
||||
signature_len );
|
||||
|
||||
/* Skip over the already-written signature */
|
||||
ssl->out_msglen += signature_len;
|
||||
}
|
||||
#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */
|
||||
|
||||
/* Add header and send. */
|
||||
ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
|
||||
ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE;
|
||||
|
||||
ssl->state++;
|
||||
|
||||
if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
|
||||
if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server key exchange" ) );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
@@ -3218,12 +3372,21 @@ static int ssl_write_server_hello_done( mbedtls_ssl_context *ssl )
|
||||
mbedtls_ssl_send_flight_completed( ssl );
|
||||
#endif
|
||||
|
||||
if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
|
||||
if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
||||
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
|
||||
( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret );
|
||||
return( ret );
|
||||
}
|
||||
#endif /* MBEDTLS_SSL_PROTO_DTLS */
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello done" ) );
|
||||
|
||||
return( 0 );
|
||||
@@ -3272,33 +3435,59 @@ static int ssl_parse_client_dh_public( mbedtls_ssl_context *ssl, unsigned char *
|
||||
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \
|
||||
defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
|
||||
static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl,
|
||||
const unsigned char *p,
|
||||
const unsigned char *end,
|
||||
size_t pms_offset )
|
||||
|
||||
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
|
||||
static int ssl_resume_decrypt_pms( mbedtls_ssl_context *ssl,
|
||||
unsigned char *peer_pms,
|
||||
size_t *peer_pmslen,
|
||||
size_t peer_pmssize )
|
||||
{
|
||||
int ret = ssl->conf->f_async_resume( ssl,
|
||||
peer_pms, peer_pmslen, peer_pmssize );
|
||||
if( ret != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS )
|
||||
{
|
||||
ssl->handshake->async_in_progress = 0;
|
||||
mbedtls_ssl_set_async_operation_data( ssl, NULL );
|
||||
}
|
||||
MBEDTLS_SSL_DEBUG_RET( 2, "ssl_decrypt_encrypted_pms", ret );
|
||||
return( ret );
|
||||
}
|
||||
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
|
||||
|
||||
static int ssl_decrypt_encrypted_pms( mbedtls_ssl_context *ssl,
|
||||
const unsigned char *p,
|
||||
const unsigned char *end,
|
||||
unsigned char *peer_pms,
|
||||
size_t *peer_pmslen,
|
||||
size_t peer_pmssize )
|
||||
{
|
||||
int ret;
|
||||
size_t len = mbedtls_pk_get_len( mbedtls_ssl_own_key( ssl ) );
|
||||
unsigned char *pms = ssl->handshake->premaster + pms_offset;
|
||||
unsigned char ver[2];
|
||||
unsigned char fake_pms[48], peer_pms[48];
|
||||
unsigned char mask;
|
||||
size_t i, peer_pmslen;
|
||||
unsigned int diff;
|
||||
mbedtls_pk_context *private_key = mbedtls_ssl_own_key( ssl );
|
||||
mbedtls_pk_context *public_key = &mbedtls_ssl_own_cert( ssl )->pk;
|
||||
size_t len = mbedtls_pk_get_len( public_key );
|
||||
|
||||
if( ! mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_RSA ) )
|
||||
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
|
||||
/* If we have already started decoding the message and there is an ongoing
|
||||
* decryption operation, resume signing. */
|
||||
if( ssl->handshake->async_in_progress != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no RSA private key" ) );
|
||||
return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED );
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "resuming decryption operation" ) );
|
||||
return( ssl_resume_decrypt_pms( ssl,
|
||||
peer_pms, peer_pmslen, peer_pmssize ) );
|
||||
}
|
||||
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
|
||||
|
||||
/*
|
||||
* Decrypt the premaster using own private RSA key
|
||||
* Prepare to decrypt the premaster using own private RSA key
|
||||
*/
|
||||
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
|
||||
defined(MBEDTLS_SSL_PROTO_TLS1_2)
|
||||
if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 )
|
||||
{
|
||||
if ( p + 2 > end ) {
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
|
||||
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
|
||||
}
|
||||
if( *p++ != ( ( len >> 8 ) & 0xFF ) ||
|
||||
*p++ != ( ( len ) & 0xFF ) )
|
||||
{
|
||||
@@ -3314,30 +3503,120 @@ static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl,
|
||||
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
|
||||
}
|
||||
|
||||
/*
|
||||
* Decrypt the premaster secret
|
||||
*/
|
||||
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
|
||||
if( ssl->conf->f_async_decrypt_start != NULL )
|
||||
{
|
||||
ret = ssl->conf->f_async_decrypt_start( ssl,
|
||||
mbedtls_ssl_own_cert( ssl ),
|
||||
p, len );
|
||||
switch( ret )
|
||||
{
|
||||
case MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH:
|
||||
/* act as if f_async_decrypt_start was null */
|
||||
break;
|
||||
case 0:
|
||||
ssl->handshake->async_in_progress = 1;
|
||||
return( ssl_resume_decrypt_pms( ssl,
|
||||
peer_pms,
|
||||
peer_pmslen,
|
||||
peer_pmssize ) );
|
||||
case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS:
|
||||
ssl->handshake->async_in_progress = 1;
|
||||
return( MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS );
|
||||
default:
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "f_async_decrypt_start", ret );
|
||||
return( ret );
|
||||
}
|
||||
}
|
||||
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
|
||||
|
||||
if( ! mbedtls_pk_can_do( private_key, MBEDTLS_PK_RSA ) )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no RSA private key" ) );
|
||||
return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED );
|
||||
}
|
||||
|
||||
ret = mbedtls_pk_decrypt( private_key, p, len,
|
||||
peer_pms, peer_pmslen, peer_pmssize,
|
||||
ssl->conf->f_rng, ssl->conf->p_rng );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl,
|
||||
const unsigned char *p,
|
||||
const unsigned char *end,
|
||||
size_t pms_offset )
|
||||
{
|
||||
int ret;
|
||||
unsigned char *pms = ssl->handshake->premaster + pms_offset;
|
||||
unsigned char ver[2];
|
||||
unsigned char fake_pms[48], peer_pms[48];
|
||||
unsigned char mask;
|
||||
size_t i, peer_pmslen;
|
||||
unsigned int diff;
|
||||
|
||||
/* In case of a failure in decryption, the decryption may write less than
|
||||
* 2 bytes of output, but we always read the first two bytes. It doesn't
|
||||
* matter in the end because diff will be nonzero in that case due to
|
||||
* peer_pmslen being less than 48, and we only care whether diff is 0.
|
||||
* But do initialize peer_pms for robustness anyway. This also makes
|
||||
* memory analyzers happy (don't access uninitialized memory, even
|
||||
* if it's an unsigned char). */
|
||||
peer_pms[0] = peer_pms[1] = ~0;
|
||||
|
||||
ret = ssl_decrypt_encrypted_pms( ssl, p, end,
|
||||
peer_pms,
|
||||
&peer_pmslen,
|
||||
sizeof( peer_pms ) );
|
||||
|
||||
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
|
||||
if ( ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS )
|
||||
return( ret );
|
||||
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
|
||||
|
||||
mbedtls_ssl_write_version( ssl->handshake->max_major_ver,
|
||||
ssl->handshake->max_minor_ver,
|
||||
ssl->conf->transport, ver );
|
||||
ssl->handshake->max_minor_ver,
|
||||
ssl->conf->transport, ver );
|
||||
|
||||
/* Avoid data-dependent branches while checking for invalid
|
||||
* padding, to protect against timing-based Bleichenbacher-type
|
||||
* attacks. */
|
||||
diff = (unsigned int) ret;
|
||||
diff |= peer_pmslen ^ 48;
|
||||
diff |= peer_pms[0] ^ ver[0];
|
||||
diff |= peer_pms[1] ^ ver[1];
|
||||
|
||||
/* mask = diff ? 0xff : 0x00 using bit operations to avoid branches */
|
||||
/* MSVC has a warning about unary minus on unsigned, but this is
|
||||
* well-defined and precisely what we want to do here */
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning( push )
|
||||
#pragma warning( disable : 4146 )
|
||||
#endif
|
||||
mask = - ( ( diff | - diff ) >> ( sizeof( unsigned int ) * 8 - 1 ) );
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning( pop )
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Protection against Bleichenbacher's attack: invalid PKCS#1 v1.5 padding
|
||||
* must not cause the connection to end immediately; instead, send a
|
||||
* bad_record_mac later in the handshake.
|
||||
* Also, avoid data-dependant branches here to protect against
|
||||
* timing-based variants.
|
||||
* To protect against timing-based variants of the attack, we must
|
||||
* not have any branch that depends on whether the decryption was
|
||||
* successful. In particular, always generate the fake premaster secret,
|
||||
* regardless of whether it will ultimately influence the output or not.
|
||||
*/
|
||||
ret = ssl->conf->f_rng( ssl->conf->p_rng, fake_pms, sizeof( fake_pms ) );
|
||||
if( ret != 0 )
|
||||
{
|
||||
/* It's ok to abort on an RNG failure, since this does not reveal
|
||||
* anything about the RSA decryption. */
|
||||
return( ret );
|
||||
|
||||
ret = mbedtls_pk_decrypt( mbedtls_ssl_own_key( ssl ), p, len,
|
||||
peer_pms, &peer_pmslen,
|
||||
sizeof( peer_pms ),
|
||||
ssl->conf->f_rng, ssl->conf->p_rng );
|
||||
|
||||
diff = (unsigned int) ret;
|
||||
diff |= peer_pmslen ^ 48;
|
||||
diff |= peer_pms[0] ^ ver[0];
|
||||
diff |= peer_pms[1] ^ ver[1];
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_SSL_DEBUG_ALL)
|
||||
if( diff != 0 )
|
||||
@@ -3352,18 +3631,8 @@ static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl,
|
||||
}
|
||||
ssl->handshake->pmslen = 48;
|
||||
|
||||
/* mask = diff ? 0xff : 0x00 using bit operations to avoid branches */
|
||||
/* MSVC has a warning about unary minus on unsigned, but this is
|
||||
* well-defined and precisely what we want to do here */
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning( push )
|
||||
#pragma warning( disable : 4146 )
|
||||
#endif
|
||||
mask = - ( ( diff | - diff ) >> ( sizeof( unsigned int ) * 8 - 1 ) );
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning( pop )
|
||||
#endif
|
||||
|
||||
/* Set pms to either the true or the fake PMS, without
|
||||
* data-dependent branches. */
|
||||
for( i = 0; i < ssl->handshake->pmslen; i++ )
|
||||
pms[i] = ( mask & fake_pms[i] ) | ( (~mask) & peer_pms[i] );
|
||||
|
||||
@@ -3445,7 +3714,21 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client key exchange" ) );
|
||||
|
||||
if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
|
||||
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) && \
|
||||
( defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \
|
||||
defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) )
|
||||
if( ( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ||
|
||||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) &&
|
||||
( ssl->handshake->async_in_progress != 0 ) )
|
||||
{
|
||||
/* We've already read a record and there is an asynchronous
|
||||
* operation in progress to decrypt it. So skip reading the
|
||||
* record. */
|
||||
MBEDTLS_SSL_DEBUG_MSG( 3, ( "will resume decryption of previously-read record" ) );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
|
||||
return( ret );
|
||||
@@ -3557,6 +3840,19 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
|
||||
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK )
|
||||
{
|
||||
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
|
||||
if ( ssl->handshake->async_in_progress != 0 )
|
||||
{
|
||||
/* There is an asynchronous operation in progress to
|
||||
* decrypt the encrypted premaster secret, so skip
|
||||
* directly to resuming this operation. */
|
||||
MBEDTLS_SSL_DEBUG_MSG( 3, ( "PSK identity already parsed" ) );
|
||||
/* Update p to skip the PSK identity. ssl_parse_encrypted_pms
|
||||
* won't actually use it, but maintain p anyway for robustness. */
|
||||
p += ssl->conf->psk_identity_len + 2;
|
||||
}
|
||||
else
|
||||
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
|
||||
if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret );
|
||||
@@ -3742,25 +4038,10 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
|
||||
}
|
||||
|
||||
/* Read the message without adding it to the checksum */
|
||||
do {
|
||||
|
||||
do ret = mbedtls_ssl_read_record_layer( ssl );
|
||||
while( ret == MBEDTLS_ERR_SSL_CONTINUE_PROCESSING );
|
||||
|
||||
if( ret != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record_layer" ), ret );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
ret = mbedtls_ssl_handle_message_type( ssl );
|
||||
|
||||
} while( MBEDTLS_ERR_SSL_NON_FATAL == ret ||
|
||||
MBEDTLS_ERR_SSL_CONTINUE_PROCESSING == ret );
|
||||
|
||||
ret = mbedtls_ssl_read_record( ssl, 0 /* no checksum update */ );
|
||||
if( 0 != ret )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_handle_message_type" ), ret );
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record" ), ret );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
@@ -3926,7 +4207,7 @@ static int ssl_write_new_session_ticket( mbedtls_ssl_context *ssl )
|
||||
if( ( ret = ssl->conf->f_ticket_write( ssl->conf->p_ticket,
|
||||
ssl->session_negotiate,
|
||||
ssl->out_msg + 10,
|
||||
ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN,
|
||||
ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN,
|
||||
&tlen, &lifetime ) ) != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_ticket_write", ret );
|
||||
@@ -3949,9 +4230,9 @@ static int ssl_write_new_session_ticket( mbedtls_ssl_context *ssl )
|
||||
*/
|
||||
ssl->handshake->new_session_ticket = 0;
|
||||
|
||||
if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 )
|
||||
if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
@@ -3980,10 +4261,10 @@ int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl )
|
||||
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
|
||||
ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING )
|
||||
{
|
||||
if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 )
|
||||
if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
|
||||
return( ret );
|
||||
}
|
||||
#endif
|
||||
#endif /* MBEDTLS_SSL_PROTO_DTLS */
|
||||
|
||||
switch( ssl->state )
|
||||
{
|
||||
|
||||
@@ -97,7 +97,7 @@ static int ssl_ticket_update_keys( mbedtls_ssl_ticket_context *ctx )
|
||||
uint32_t current_time = (uint32_t) mbedtls_time( NULL );
|
||||
uint32_t key_time = ctx->keys[ctx->active].generation_time;
|
||||
|
||||
if( current_time > key_time &&
|
||||
if( current_time >= key_time &&
|
||||
current_time - key_time < ctx->ticket_lifetime )
|
||||
{
|
||||
return( 0 );
|
||||
|
||||
2570
library/ssl_tls.c
2570
library/ssl_tls.c
File diff suppressed because it is too large
Load Diff
@@ -19,6 +19,14 @@
|
||||
* This file is part of mbed TLS (https://tls.mbed.org)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Ensure gmtime_r is available even with -std=c99; must be defined before
|
||||
* config.h, which pulls in glibc's features.h. Harmless on other platforms.
|
||||
*/
|
||||
#if !defined(_POSIX_C_SOURCE)
|
||||
#define _POSIX_C_SOURCE 200112L
|
||||
#endif
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
@@ -29,6 +37,36 @@
|
||||
|
||||
#include "mbedtls/threading.h"
|
||||
|
||||
#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT)
|
||||
|
||||
#if !defined(_WIN32) && (defined(unix) || \
|
||||
defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \
|
||||
defined(__MACH__)))
|
||||
#include <unistd.h>
|
||||
#endif /* !_WIN32 && (unix || __unix || __unix__ ||
|
||||
* (__APPLE__ && __MACH__)) */
|
||||
|
||||
#if !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \
|
||||
( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \
|
||||
_POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) )
|
||||
/*
|
||||
* This is a convenience shorthand macro to avoid checking the long
|
||||
* preprocessor conditions above. Ideally, we could expose this macro in
|
||||
* platform_util.h and simply use it in platform_util.c, threading.c and
|
||||
* threading.h. However, this macro is not part of the Mbed TLS public API, so
|
||||
* we keep it private by only defining it in this file
|
||||
*/
|
||||
|
||||
#if ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) )
|
||||
#define THREADING_USE_GMTIME
|
||||
#endif /* ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) */
|
||||
|
||||
#endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \
|
||||
( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \
|
||||
_POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) ) */
|
||||
|
||||
#endif /* MBEDTLS_HAVE_TIME_DATE && !MBEDTLS_PLATFORM_GMTIME_R_ALT */
|
||||
|
||||
#if defined(MBEDTLS_THREADING_PTHREAD)
|
||||
static void threading_mutex_init_pthread( mbedtls_threading_mutex_t *mutex )
|
||||
{
|
||||
@@ -114,7 +152,7 @@ void mbedtls_threading_set_alt( void (*mutex_init)( mbedtls_threading_mutex_t *
|
||||
#if defined(MBEDTLS_FS_IO)
|
||||
mbedtls_mutex_init( &mbedtls_threading_readdir_mutex );
|
||||
#endif
|
||||
#if defined(MBEDTLS_HAVE_TIME_DATE)
|
||||
#if defined(THREADING_USE_GMTIME)
|
||||
mbedtls_mutex_init( &mbedtls_threading_gmtime_mutex );
|
||||
#endif
|
||||
}
|
||||
@@ -127,7 +165,7 @@ void mbedtls_threading_free_alt( void )
|
||||
#if defined(MBEDTLS_FS_IO)
|
||||
mbedtls_mutex_free( &mbedtls_threading_readdir_mutex );
|
||||
#endif
|
||||
#if defined(MBEDTLS_HAVE_TIME_DATE)
|
||||
#if defined(THREADING_USE_GMTIME)
|
||||
mbedtls_mutex_free( &mbedtls_threading_gmtime_mutex );
|
||||
#endif
|
||||
}
|
||||
@@ -142,7 +180,7 @@ void mbedtls_threading_free_alt( void )
|
||||
#if defined(MBEDTLS_FS_IO)
|
||||
mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex MUTEX_INIT;
|
||||
#endif
|
||||
#if defined(MBEDTLS_HAVE_TIME_DATE)
|
||||
#if defined(THREADING_USE_GMTIME)
|
||||
mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex MUTEX_INIT;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -39,7 +39,8 @@
|
||||
#if !defined(MBEDTLS_TIMING_ALT)
|
||||
|
||||
#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \
|
||||
!defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__)
|
||||
!defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \
|
||||
!defined(__HAIKU__)
|
||||
#error "This module only works on Unix and Windows, see MBEDTLS_TIMING_C in config.h"
|
||||
#endif
|
||||
|
||||
|
||||
@@ -39,6 +39,9 @@ static const char *features[] = {
|
||||
#if defined(MBEDTLS_NO_UDBL_DIVISION)
|
||||
"MBEDTLS_NO_UDBL_DIVISION",
|
||||
#endif /* MBEDTLS_NO_UDBL_DIVISION */
|
||||
#if defined(MBEDTLS_NO_64BIT_MULTIPLICATION)
|
||||
"MBEDTLS_NO_64BIT_MULTIPLICATION",
|
||||
#endif /* MBEDTLS_NO_64BIT_MULTIPLICATION */
|
||||
#if defined(MBEDTLS_HAVE_SSE2)
|
||||
"MBEDTLS_HAVE_SSE2",
|
||||
#endif /* MBEDTLS_HAVE_SSE2 */
|
||||
@@ -90,6 +93,9 @@ static const char *features[] = {
|
||||
#if defined(MBEDTLS_ARC4_ALT)
|
||||
"MBEDTLS_ARC4_ALT",
|
||||
#endif /* MBEDTLS_ARC4_ALT */
|
||||
#if defined(MBEDTLS_ARIA_ALT)
|
||||
"MBEDTLS_ARIA_ALT",
|
||||
#endif /* MBEDTLS_ARIA_ALT */
|
||||
#if defined(MBEDTLS_BLOWFISH_ALT)
|
||||
"MBEDTLS_BLOWFISH_ALT",
|
||||
#endif /* MBEDTLS_BLOWFISH_ALT */
|
||||
@@ -99,6 +105,12 @@ static const char *features[] = {
|
||||
#if defined(MBEDTLS_CCM_ALT)
|
||||
"MBEDTLS_CCM_ALT",
|
||||
#endif /* MBEDTLS_CCM_ALT */
|
||||
#if defined(MBEDTLS_CHACHA20_ALT)
|
||||
"MBEDTLS_CHACHA20_ALT",
|
||||
#endif /* MBEDTLS_CHACHA20_ALT */
|
||||
#if defined(MBEDTLS_CHACHAPOLY_ALT)
|
||||
"MBEDTLS_CHACHAPOLY_ALT",
|
||||
#endif /* MBEDTLS_CHACHAPOLY_ALT */
|
||||
#if defined(MBEDTLS_CMAC_ALT)
|
||||
"MBEDTLS_CMAC_ALT",
|
||||
#endif /* MBEDTLS_CMAC_ALT */
|
||||
@@ -114,6 +126,9 @@ static const char *features[] = {
|
||||
#if defined(MBEDTLS_GCM_ALT)
|
||||
"MBEDTLS_GCM_ALT",
|
||||
#endif /* MBEDTLS_GCM_ALT */
|
||||
#if defined(MBEDTLS_NIST_KW_ALT)
|
||||
"MBEDTLS_NIST_KW_ALT",
|
||||
#endif /* MBEDTLS_NIST_KW_ALT */
|
||||
#if defined(MBEDTLS_MD2_ALT)
|
||||
"MBEDTLS_MD2_ALT",
|
||||
#endif /* MBEDTLS_MD2_ALT */
|
||||
@@ -123,6 +138,9 @@ static const char *features[] = {
|
||||
#if defined(MBEDTLS_MD5_ALT)
|
||||
"MBEDTLS_MD5_ALT",
|
||||
#endif /* MBEDTLS_MD5_ALT */
|
||||
#if defined(MBEDTLS_POLY1305_ALT)
|
||||
"MBEDTLS_POLY1305_ALT",
|
||||
#endif /* MBEDTLS_POLY1305_ALT */
|
||||
#if defined(MBEDTLS_RIPEMD160_ALT)
|
||||
"MBEDTLS_RIPEMD160_ALT",
|
||||
#endif /* MBEDTLS_RIPEMD160_ALT */
|
||||
@@ -252,6 +270,12 @@ static const char *features[] = {
|
||||
#if defined(MBEDTLS_CIPHER_MODE_CTR)
|
||||
"MBEDTLS_CIPHER_MODE_CTR",
|
||||
#endif /* MBEDTLS_CIPHER_MODE_CTR */
|
||||
#if defined(MBEDTLS_CIPHER_MODE_OFB)
|
||||
"MBEDTLS_CIPHER_MODE_OFB",
|
||||
#endif /* MBEDTLS_CIPHER_MODE_OFB */
|
||||
#if defined(MBEDTLS_CIPHER_MODE_XTS)
|
||||
"MBEDTLS_CIPHER_MODE_XTS",
|
||||
#endif /* MBEDTLS_CIPHER_MODE_XTS */
|
||||
#if defined(MBEDTLS_CIPHER_NULL_CIPHER)
|
||||
"MBEDTLS_CIPHER_NULL_CIPHER",
|
||||
#endif /* MBEDTLS_CIPHER_NULL_CIPHER */
|
||||
@@ -315,6 +339,9 @@ static const char *features[] = {
|
||||
#if defined(MBEDTLS_ECP_NIST_OPTIM)
|
||||
"MBEDTLS_ECP_NIST_OPTIM",
|
||||
#endif /* MBEDTLS_ECP_NIST_OPTIM */
|
||||
#if defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
"MBEDTLS_ECP_RESTARTABLE",
|
||||
#endif /* MBEDTLS_ECP_RESTARTABLE */
|
||||
#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
|
||||
"MBEDTLS_ECDSA_DETERMINISTIC",
|
||||
#endif /* MBEDTLS_ECDSA_DETERMINISTIC */
|
||||
@@ -402,6 +429,9 @@ static const char *features[] = {
|
||||
#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES)
|
||||
"MBEDTLS_SSL_ALL_ALERT_MESSAGES",
|
||||
#endif /* MBEDTLS_SSL_ALL_ALERT_MESSAGES */
|
||||
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
|
||||
"MBEDTLS_SSL_ASYNC_PRIVATE",
|
||||
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
|
||||
#if defined(MBEDTLS_SSL_DEBUG_ALL)
|
||||
"MBEDTLS_SSL_DEBUG_ALL",
|
||||
#endif /* MBEDTLS_SSL_DEBUG_ALL */
|
||||
@@ -531,12 +561,21 @@ static const char *features[] = {
|
||||
#if defined(MBEDTLS_CAMELLIA_C)
|
||||
"MBEDTLS_CAMELLIA_C",
|
||||
#endif /* MBEDTLS_CAMELLIA_C */
|
||||
#if defined(MBEDTLS_ARIA_C)
|
||||
"MBEDTLS_ARIA_C",
|
||||
#endif /* MBEDTLS_ARIA_C */
|
||||
#if defined(MBEDTLS_CCM_C)
|
||||
"MBEDTLS_CCM_C",
|
||||
#endif /* MBEDTLS_CCM_C */
|
||||
#if defined(MBEDTLS_CERTS_C)
|
||||
"MBEDTLS_CERTS_C",
|
||||
#endif /* MBEDTLS_CERTS_C */
|
||||
#if defined(MBEDTLS_CHACHA20_C)
|
||||
"MBEDTLS_CHACHA20_C",
|
||||
#endif /* MBEDTLS_CHACHA20_C */
|
||||
#if defined(MBEDTLS_CHACHAPOLY_C)
|
||||
"MBEDTLS_CHACHAPOLY_C",
|
||||
#endif /* MBEDTLS_CHACHAPOLY_C */
|
||||
#if defined(MBEDTLS_CIPHER_C)
|
||||
"MBEDTLS_CIPHER_C",
|
||||
#endif /* MBEDTLS_CIPHER_C */
|
||||
@@ -579,9 +618,15 @@ static const char *features[] = {
|
||||
#if defined(MBEDTLS_HAVEGE_C)
|
||||
"MBEDTLS_HAVEGE_C",
|
||||
#endif /* MBEDTLS_HAVEGE_C */
|
||||
#if defined(MBEDTLS_HKDF_C)
|
||||
"MBEDTLS_HKDF_C",
|
||||
#endif /* MBEDTLS_HKDF_C */
|
||||
#if defined(MBEDTLS_HMAC_DRBG_C)
|
||||
"MBEDTLS_HMAC_DRBG_C",
|
||||
#endif /* MBEDTLS_HMAC_DRBG_C */
|
||||
#if defined(MBEDTLS_NIST_KW_C)
|
||||
"MBEDTLS_NIST_KW_C",
|
||||
#endif /* MBEDTLS_NIST_KW_C */
|
||||
#if defined(MBEDTLS_MD_C)
|
||||
"MBEDTLS_MD_C",
|
||||
#endif /* MBEDTLS_MD_C */
|
||||
@@ -633,6 +678,9 @@ static const char *features[] = {
|
||||
#if defined(MBEDTLS_PLATFORM_C)
|
||||
"MBEDTLS_PLATFORM_C",
|
||||
#endif /* MBEDTLS_PLATFORM_C */
|
||||
#if defined(MBEDTLS_POLY1305_C)
|
||||
"MBEDTLS_POLY1305_C",
|
||||
#endif /* MBEDTLS_POLY1305_C */
|
||||
#if defined(MBEDTLS_RIPEMD160_C)
|
||||
"MBEDTLS_RIPEMD160_C",
|
||||
#endif /* MBEDTLS_RIPEMD160_C */
|
||||
|
||||
@@ -59,26 +59,14 @@
|
||||
#define mbedtls_snprintf snprintf
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(MBEDTLS_HAVE_TIME)
|
||||
#include "mbedtls/platform_time.h"
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
|
||||
#include <windows.h>
|
||||
#else
|
||||
#if defined(MBEDTLS_HAVE_TIME_DATE)
|
||||
#include "mbedtls/platform_util.h"
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_FS_IO)
|
||||
#include <stdio.h>
|
||||
#if !defined(_WIN32)
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define CHECK(code) if( ( ret = code ) != 0 ){ return( ret ); }
|
||||
#define CHECK_RANGE(min, max, val) if( val < min || val > max ){ return( ret ); }
|
||||
|
||||
@@ -903,36 +891,14 @@ int mbedtls_x509_key_size_helper( char *buf, size_t buf_size, const char *name )
|
||||
* Set the time structure to the current time.
|
||||
* Return 0 on success, non-zero on failure.
|
||||
*/
|
||||
#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
|
||||
static int x509_get_current_time( mbedtls_x509_time *now )
|
||||
{
|
||||
SYSTEMTIME st;
|
||||
|
||||
GetSystemTime( &st );
|
||||
|
||||
now->year = st.wYear;
|
||||
now->mon = st.wMonth;
|
||||
now->day = st.wDay;
|
||||
now->hour = st.wHour;
|
||||
now->min = st.wMinute;
|
||||
now->sec = st.wSecond;
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
#else
|
||||
static int x509_get_current_time( mbedtls_x509_time *now )
|
||||
{
|
||||
struct tm *lt;
|
||||
struct tm *lt, tm_buf;
|
||||
mbedtls_time_t tt;
|
||||
int ret = 0;
|
||||
|
||||
#if defined(MBEDTLS_THREADING_C)
|
||||
if( mbedtls_mutex_lock( &mbedtls_threading_gmtime_mutex ) != 0 )
|
||||
return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
|
||||
#endif
|
||||
|
||||
tt = mbedtls_time( NULL );
|
||||
lt = gmtime( &tt );
|
||||
lt = mbedtls_platform_gmtime_r( &tt, &tm_buf );
|
||||
|
||||
if( lt == NULL )
|
||||
ret = -1;
|
||||
@@ -946,14 +912,8 @@ static int x509_get_current_time( mbedtls_x509_time *now )
|
||||
now->sec = lt->tm_sec;
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_THREADING_C)
|
||||
if( mbedtls_mutex_unlock( &mbedtls_threading_gmtime_mutex ) != 0 )
|
||||
return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
|
||||
#endif
|
||||
|
||||
return( ret );
|
||||
}
|
||||
#endif /* _WIN32 && !EFIX64 && !EFI32 */
|
||||
|
||||
/*
|
||||
* Return 0 if before <= after, 1 otherwise
|
||||
|
||||
@@ -163,6 +163,9 @@ const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb =
|
||||
static int x509_profile_check_md_alg( const mbedtls_x509_crt_profile *profile,
|
||||
mbedtls_md_type_t md_alg )
|
||||
{
|
||||
if( md_alg == MBEDTLS_MD_NONE )
|
||||
return( -1 );
|
||||
|
||||
if( ( profile->allowed_mds & MBEDTLS_X509_ID_FLAG( md_alg ) ) != 0 )
|
||||
return( 0 );
|
||||
|
||||
@@ -176,6 +179,9 @@ static int x509_profile_check_md_alg( const mbedtls_x509_crt_profile *profile,
|
||||
static int x509_profile_check_pk_alg( const mbedtls_x509_crt_profile *profile,
|
||||
mbedtls_pk_type_t pk_alg )
|
||||
{
|
||||
if( pk_alg == MBEDTLS_PK_NONE )
|
||||
return( -1 );
|
||||
|
||||
if( ( profile->allowed_pks & MBEDTLS_X509_ID_FLAG( pk_alg ) ) != 0 )
|
||||
return( 0 );
|
||||
|
||||
@@ -208,6 +214,9 @@ static int x509_profile_check_key( const mbedtls_x509_crt_profile *profile,
|
||||
{
|
||||
const mbedtls_ecp_group_id gid = mbedtls_pk_ec( *pk )->grp.id;
|
||||
|
||||
if( gid == MBEDTLS_ECP_DP_NONE )
|
||||
return( -1 );
|
||||
|
||||
if( ( profile->allowed_curves & MBEDTLS_X509_ID_FLAG( gid ) ) != 0 )
|
||||
return( 0 );
|
||||
|
||||
@@ -218,6 +227,153 @@ static int x509_profile_check_key( const mbedtls_x509_crt_profile *profile,
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Like memcmp, but case-insensitive and always returns -1 if different
|
||||
*/
|
||||
static int x509_memcasecmp( const void *s1, const void *s2, size_t len )
|
||||
{
|
||||
size_t i;
|
||||
unsigned char diff;
|
||||
const unsigned char *n1 = s1, *n2 = s2;
|
||||
|
||||
for( i = 0; i < len; i++ )
|
||||
{
|
||||
diff = n1[i] ^ n2[i];
|
||||
|
||||
if( diff == 0 )
|
||||
continue;
|
||||
|
||||
if( diff == 32 &&
|
||||
( ( n1[i] >= 'a' && n1[i] <= 'z' ) ||
|
||||
( n1[i] >= 'A' && n1[i] <= 'Z' ) ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Return 0 if name matches wildcard, -1 otherwise
|
||||
*/
|
||||
static int x509_check_wildcard( const char *cn, const mbedtls_x509_buf *name )
|
||||
{
|
||||
size_t i;
|
||||
size_t cn_idx = 0, cn_len = strlen( cn );
|
||||
|
||||
/* We can't have a match if there is no wildcard to match */
|
||||
if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' )
|
||||
return( -1 );
|
||||
|
||||
for( i = 0; i < cn_len; ++i )
|
||||
{
|
||||
if( cn[i] == '.' )
|
||||
{
|
||||
cn_idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( cn_idx == 0 )
|
||||
return( -1 );
|
||||
|
||||
if( cn_len - cn_idx == name->len - 1 &&
|
||||
x509_memcasecmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 )
|
||||
{
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare two X.509 strings, case-insensitive, and allowing for some encoding
|
||||
* variations (but not all).
|
||||
*
|
||||
* Return 0 if equal, -1 otherwise.
|
||||
*/
|
||||
static int x509_string_cmp( const mbedtls_x509_buf *a, const mbedtls_x509_buf *b )
|
||||
{
|
||||
if( a->tag == b->tag &&
|
||||
a->len == b->len &&
|
||||
memcmp( a->p, b->p, b->len ) == 0 )
|
||||
{
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
if( ( a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) &&
|
||||
( b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) &&
|
||||
a->len == b->len &&
|
||||
x509_memcasecmp( a->p, b->p, b->len ) == 0 )
|
||||
{
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare two X.509 Names (aka rdnSequence).
|
||||
*
|
||||
* See RFC 5280 section 7.1, though we don't implement the whole algorithm:
|
||||
* we sometimes return unequal when the full algorithm would return equal,
|
||||
* but never the other way. (In particular, we don't do Unicode normalisation
|
||||
* or space folding.)
|
||||
*
|
||||
* Return 0 if equal, -1 otherwise.
|
||||
*/
|
||||
static int x509_name_cmp( const mbedtls_x509_name *a, const mbedtls_x509_name *b )
|
||||
{
|
||||
/* Avoid recursion, it might not be optimised by the compiler */
|
||||
while( a != NULL || b != NULL )
|
||||
{
|
||||
if( a == NULL || b == NULL )
|
||||
return( -1 );
|
||||
|
||||
/* type */
|
||||
if( a->oid.tag != b->oid.tag ||
|
||||
a->oid.len != b->oid.len ||
|
||||
memcmp( a->oid.p, b->oid.p, b->oid.len ) != 0 )
|
||||
{
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* value */
|
||||
if( x509_string_cmp( &a->val, &b->val ) != 0 )
|
||||
return( -1 );
|
||||
|
||||
/* structure of the list of sets */
|
||||
if( a->next_merged != b->next_merged )
|
||||
return( -1 );
|
||||
|
||||
a = a->next;
|
||||
b = b->next;
|
||||
}
|
||||
|
||||
/* a == NULL == b */
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset (init or clear) a verify_chain
|
||||
*/
|
||||
static void x509_crt_verify_chain_reset(
|
||||
mbedtls_x509_crt_verify_chain *ver_chain )
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for( i = 0; i < MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE; i++ )
|
||||
{
|
||||
ver_chain->items[i].crt = NULL;
|
||||
ver_chain->items[i].flags = -1;
|
||||
}
|
||||
|
||||
ver_chain->len = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Version ::= INTEGER { v1(0), v2(1), v3(2) }
|
||||
*/
|
||||
@@ -570,18 +726,14 @@ static int x509_get_crt_ext( unsigned char **p,
|
||||
end_ext_data = *p + len;
|
||||
|
||||
/* Get extension ID */
|
||||
extn_oid.tag = **p;
|
||||
|
||||
if( ( ret = mbedtls_asn1_get_tag( p, end, &extn_oid.len, MBEDTLS_ASN1_OID ) ) != 0 )
|
||||
if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &extn_oid.len,
|
||||
MBEDTLS_ASN1_OID ) ) != 0 )
|
||||
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
|
||||
|
||||
extn_oid.tag = MBEDTLS_ASN1_OID;
|
||||
extn_oid.p = *p;
|
||||
*p += extn_oid.len;
|
||||
|
||||
if( ( end - *p ) < 1 )
|
||||
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
|
||||
MBEDTLS_ERR_ASN1_OUT_OF_DATA );
|
||||
|
||||
/* Get optional critical */
|
||||
if( ( ret = mbedtls_asn1_get_bool( p, end_ext_data, &is_critical ) ) != 0 &&
|
||||
( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) )
|
||||
@@ -1662,9 +1814,7 @@ static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca,
|
||||
while( crl_list != NULL )
|
||||
{
|
||||
if( crl_list->version == 0 ||
|
||||
crl_list->issuer_raw.len != ca->subject_raw.len ||
|
||||
memcmp( crl_list->issuer_raw.p, ca->subject_raw.p,
|
||||
crl_list->issuer_raw.len ) != 0 )
|
||||
x509_name_cmp( &crl_list->issuer, &ca->subject ) != 0 )
|
||||
{
|
||||
crl_list = crl_list->next;
|
||||
continue;
|
||||
@@ -1674,7 +1824,8 @@ static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca,
|
||||
* Check if the CA is configured to sign CRLs
|
||||
*/
|
||||
#if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
|
||||
if( mbedtls_x509_crt_check_key_usage( ca, MBEDTLS_X509_KU_CRL_SIGN ) != 0 )
|
||||
if( mbedtls_x509_crt_check_key_usage( ca,
|
||||
MBEDTLS_X509_KU_CRL_SIGN ) != 0 )
|
||||
{
|
||||
flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;
|
||||
break;
|
||||
@@ -1734,141 +1885,12 @@ static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca,
|
||||
}
|
||||
#endif /* MBEDTLS_X509_CRL_PARSE_C */
|
||||
|
||||
/*
|
||||
* Like memcmp, but case-insensitive and always returns -1 if different
|
||||
*/
|
||||
static int x509_memcasecmp( const void *s1, const void *s2, size_t len )
|
||||
{
|
||||
size_t i;
|
||||
unsigned char diff;
|
||||
const unsigned char *n1 = s1, *n2 = s2;
|
||||
|
||||
for( i = 0; i < len; i++ )
|
||||
{
|
||||
diff = n1[i] ^ n2[i];
|
||||
|
||||
if( diff == 0 )
|
||||
continue;
|
||||
|
||||
if( diff == 32 &&
|
||||
( ( n1[i] >= 'a' && n1[i] <= 'z' ) ||
|
||||
( n1[i] >= 'A' && n1[i] <= 'Z' ) ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Return 0 if name matches wildcard, -1 otherwise
|
||||
*/
|
||||
static int x509_check_wildcard( const char *cn, const mbedtls_x509_buf *name )
|
||||
{
|
||||
size_t i;
|
||||
size_t cn_idx = 0, cn_len = strlen( cn );
|
||||
|
||||
/* We can't have a match if there is no wildcard to match */
|
||||
if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' )
|
||||
return( -1 );
|
||||
|
||||
for( i = 0; i < cn_len; ++i )
|
||||
{
|
||||
if( cn[i] == '.' )
|
||||
{
|
||||
cn_idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( cn_idx == 0 )
|
||||
return( -1 );
|
||||
|
||||
if( cn_len - cn_idx == name->len - 1 &&
|
||||
x509_memcasecmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 )
|
||||
{
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare two X.509 strings, case-insensitive, and allowing for some encoding
|
||||
* variations (but not all).
|
||||
*
|
||||
* Return 0 if equal, -1 otherwise.
|
||||
*/
|
||||
static int x509_string_cmp( const mbedtls_x509_buf *a, const mbedtls_x509_buf *b )
|
||||
{
|
||||
if( a->tag == b->tag &&
|
||||
a->len == b->len &&
|
||||
memcmp( a->p, b->p, b->len ) == 0 )
|
||||
{
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
if( ( a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) &&
|
||||
( b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) &&
|
||||
a->len == b->len &&
|
||||
x509_memcasecmp( a->p, b->p, b->len ) == 0 )
|
||||
{
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare two X.509 Names (aka rdnSequence).
|
||||
*
|
||||
* See RFC 5280 section 7.1, though we don't implement the whole algorithm:
|
||||
* we sometimes return unequal when the full algorithm would return equal,
|
||||
* but never the other way. (In particular, we don't do Unicode normalisation
|
||||
* or space folding.)
|
||||
*
|
||||
* Return 0 if equal, -1 otherwise.
|
||||
*/
|
||||
static int x509_name_cmp( const mbedtls_x509_name *a, const mbedtls_x509_name *b )
|
||||
{
|
||||
/* Avoid recursion, it might not be optimised by the compiler */
|
||||
while( a != NULL || b != NULL )
|
||||
{
|
||||
if( a == NULL || b == NULL )
|
||||
return( -1 );
|
||||
|
||||
/* type */
|
||||
if( a->oid.tag != b->oid.tag ||
|
||||
a->oid.len != b->oid.len ||
|
||||
memcmp( a->oid.p, b->oid.p, b->oid.len ) != 0 )
|
||||
{
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* value */
|
||||
if( x509_string_cmp( &a->val, &b->val ) != 0 )
|
||||
return( -1 );
|
||||
|
||||
/* structure of the list of sets */
|
||||
if( a->next_merged != b->next_merged )
|
||||
return( -1 );
|
||||
|
||||
a = a->next;
|
||||
b = b->next;
|
||||
}
|
||||
|
||||
/* a == NULL == b */
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Check the signature of a certificate by its parent
|
||||
*/
|
||||
static int x509_crt_check_signature( const mbedtls_x509_crt *child,
|
||||
mbedtls_x509_crt *parent )
|
||||
mbedtls_x509_crt *parent,
|
||||
mbedtls_x509_crt_restart_ctx *rs_ctx )
|
||||
{
|
||||
const mbedtls_md_info_t *md_info;
|
||||
unsigned char hash[MBEDTLS_MD_MAX_SIZE];
|
||||
@@ -1880,14 +1902,24 @@ static int x509_crt_check_signature( const mbedtls_x509_crt *child,
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk,
|
||||
child->sig_md, hash, mbedtls_md_get_size( md_info ),
|
||||
child->sig.p, child->sig.len ) != 0 )
|
||||
{
|
||||
/* Skip expensive computation on obvious mismatch */
|
||||
if( ! mbedtls_pk_can_do( &parent->pk, child->sig_pk ) )
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
if( rs_ctx != NULL && child->sig_pk == MBEDTLS_PK_ECDSA )
|
||||
{
|
||||
return( mbedtls_pk_verify_restartable( &parent->pk,
|
||||
child->sig_md, hash, mbedtls_md_get_size( md_info ),
|
||||
child->sig.p, child->sig.len, &rs_ctx->pk ) );
|
||||
}
|
||||
#else
|
||||
(void) rs_ctx;
|
||||
#endif
|
||||
|
||||
return( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk,
|
||||
child->sig_md, hash, mbedtls_md_get_size( md_info ),
|
||||
child->sig.p, child->sig.len ) );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1934,6 +1966,7 @@ static int x509_crt_check_parent( const mbedtls_x509_crt *child,
|
||||
* 1. subject name matches child's issuer
|
||||
* 2. if necessary, the CA bit is set and key usage allows signing certs
|
||||
* 3. for trusted roots, the signature is correct
|
||||
* (for intermediates, the signature is checked and the result reported)
|
||||
* 4. pathlen constraints are satisfied
|
||||
*
|
||||
* If there's a suitable candidate which is also time-valid, return the first
|
||||
@@ -1956,23 +1989,54 @@ static int x509_crt_check_parent( const mbedtls_x509_crt *child,
|
||||
* Arguments:
|
||||
* - [in] child: certificate for which we're looking for a parent
|
||||
* - [in] candidates: chained list of potential parents
|
||||
* - [out] r_parent: parent found (or NULL)
|
||||
* - [out] r_signature_is_good: 1 if child signature by parent is valid, or 0
|
||||
* - [in] top: 1 if candidates consists of trusted roots, ie we're at the top
|
||||
* of the chain, 0 otherwise
|
||||
* - [in] path_cnt: number of intermediates seen so far
|
||||
* - [in] self_cnt: number of self-signed intermediates seen so far
|
||||
* (will never be greater than path_cnt)
|
||||
* - [in-out] rs_ctx: context for restarting operations
|
||||
*
|
||||
* Return value:
|
||||
* - the first suitable parent found (see above regarding time-validity)
|
||||
* - NULL if no suitable parent was found
|
||||
* - 0 on success
|
||||
* - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise
|
||||
*/
|
||||
static mbedtls_x509_crt *x509_crt_find_parent_in( mbedtls_x509_crt *child,
|
||||
mbedtls_x509_crt *candidates,
|
||||
int top,
|
||||
size_t path_cnt,
|
||||
size_t self_cnt )
|
||||
static int x509_crt_find_parent_in(
|
||||
mbedtls_x509_crt *child,
|
||||
mbedtls_x509_crt *candidates,
|
||||
mbedtls_x509_crt **r_parent,
|
||||
int *r_signature_is_good,
|
||||
int top,
|
||||
unsigned path_cnt,
|
||||
unsigned self_cnt,
|
||||
mbedtls_x509_crt_restart_ctx *rs_ctx )
|
||||
{
|
||||
mbedtls_x509_crt *parent, *badtime_parent = NULL;
|
||||
int ret;
|
||||
mbedtls_x509_crt *parent, *fallback_parent;
|
||||
int signature_is_good, fallback_signature_is_good;
|
||||
|
||||
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
/* did we have something in progress? */
|
||||
if( rs_ctx != NULL && rs_ctx->parent != NULL )
|
||||
{
|
||||
/* restore saved state */
|
||||
parent = rs_ctx->parent;
|
||||
fallback_parent = rs_ctx->fallback_parent;
|
||||
fallback_signature_is_good = rs_ctx->fallback_signature_is_good;
|
||||
|
||||
/* clear saved state */
|
||||
rs_ctx->parent = NULL;
|
||||
rs_ctx->fallback_parent = NULL;
|
||||
rs_ctx->fallback_signature_is_good = 0;
|
||||
|
||||
/* resume where we left */
|
||||
goto check_signature;
|
||||
}
|
||||
#endif
|
||||
|
||||
fallback_parent = NULL;
|
||||
fallback_signature_is_good = 0;
|
||||
|
||||
for( parent = candidates; parent != NULL; parent = parent->next )
|
||||
{
|
||||
@@ -1988,17 +2052,38 @@ static mbedtls_x509_crt *x509_crt_find_parent_in( mbedtls_x509_crt *child,
|
||||
}
|
||||
|
||||
/* Signature */
|
||||
if( top && x509_crt_check_signature( child, parent ) != 0 )
|
||||
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
check_signature:
|
||||
#endif
|
||||
ret = x509_crt_check_signature( child, parent, rs_ctx );
|
||||
|
||||
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
|
||||
{
|
||||
continue;
|
||||
/* save state */
|
||||
rs_ctx->parent = parent;
|
||||
rs_ctx->fallback_parent = fallback_parent;
|
||||
rs_ctx->fallback_signature_is_good = fallback_signature_is_good;
|
||||
|
||||
return( ret );
|
||||
}
|
||||
#else
|
||||
(void) ret;
|
||||
#endif
|
||||
|
||||
signature_is_good = ret == 0;
|
||||
if( top && ! signature_is_good )
|
||||
continue;
|
||||
|
||||
/* optional time check */
|
||||
if( mbedtls_x509_time_is_past( &parent->valid_to ) ||
|
||||
mbedtls_x509_time_is_future( &parent->valid_from ) )
|
||||
{
|
||||
if( badtime_parent == NULL )
|
||||
badtime_parent = parent;
|
||||
if( fallback_parent == NULL )
|
||||
{
|
||||
fallback_parent = parent;
|
||||
fallback_signature_is_good = signature_is_good;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
@@ -2006,10 +2091,18 @@ static mbedtls_x509_crt *x509_crt_find_parent_in( mbedtls_x509_crt *child,
|
||||
break;
|
||||
}
|
||||
|
||||
if( parent == NULL )
|
||||
parent = badtime_parent;
|
||||
if( parent != NULL )
|
||||
{
|
||||
*r_parent = parent;
|
||||
*r_signature_is_good = signature_is_good;
|
||||
}
|
||||
else
|
||||
{
|
||||
*r_parent = fallback_parent;
|
||||
*r_signature_is_good = fallback_signature_is_good;
|
||||
}
|
||||
|
||||
return( parent );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2021,34 +2114,78 @@ static mbedtls_x509_crt *x509_crt_find_parent_in( mbedtls_x509_crt *child,
|
||||
* Arguments:
|
||||
* - [in] child: certificate for which we're looking for a parent, followed
|
||||
* by a chain of possible intermediates
|
||||
* - [in] trust_ca: locally trusted CAs
|
||||
* - [out] 1 if parent was found in trust_ca, 0 if found in provided chain
|
||||
* - [in] path_cnt: number of intermediates seen so far
|
||||
* - [in] self_cnt: number of self-signed intermediates seen so far
|
||||
* - [in] trust_ca: list of locally trusted certificates
|
||||
* - [out] parent: parent found (or NULL)
|
||||
* - [out] parent_is_trusted: 1 if returned `parent` is trusted, or 0
|
||||
* - [out] signature_is_good: 1 if child signature by parent is valid, or 0
|
||||
* - [in] path_cnt: number of links in the chain so far (EE -> ... -> child)
|
||||
* - [in] self_cnt: number of self-signed certs in the chain so far
|
||||
* (will always be no greater than path_cnt)
|
||||
* - [in-out] rs_ctx: context for restarting operations
|
||||
*
|
||||
* Return value:
|
||||
* - the first suitable parent found (see find_parent_in() for "suitable")
|
||||
* - NULL if no suitable parent was found
|
||||
* - 0 on success
|
||||
* - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise
|
||||
*/
|
||||
static mbedtls_x509_crt *x509_crt_find_parent( mbedtls_x509_crt *child,
|
||||
mbedtls_x509_crt *trust_ca,
|
||||
int *parent_is_trusted,
|
||||
size_t path_cnt,
|
||||
size_t self_cnt )
|
||||
static int x509_crt_find_parent(
|
||||
mbedtls_x509_crt *child,
|
||||
mbedtls_x509_crt *trust_ca,
|
||||
mbedtls_x509_crt **parent,
|
||||
int *parent_is_trusted,
|
||||
int *signature_is_good,
|
||||
unsigned path_cnt,
|
||||
unsigned self_cnt,
|
||||
mbedtls_x509_crt_restart_ctx *rs_ctx )
|
||||
{
|
||||
mbedtls_x509_crt *parent;
|
||||
int ret;
|
||||
mbedtls_x509_crt *search_list;
|
||||
|
||||
/* Look for a parent in trusted CAs */
|
||||
*parent_is_trusted = 1;
|
||||
parent = x509_crt_find_parent_in( child, trust_ca, 1, path_cnt, self_cnt );
|
||||
|
||||
if( parent != NULL )
|
||||
return( parent );
|
||||
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
/* restore then clear saved state if we have some stored */
|
||||
if( rs_ctx != NULL && rs_ctx->parent_is_trusted != -1 )
|
||||
{
|
||||
*parent_is_trusted = rs_ctx->parent_is_trusted;
|
||||
rs_ctx->parent_is_trusted = -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Look for a parent upwards the chain */
|
||||
*parent_is_trusted = 0;
|
||||
return( x509_crt_find_parent_in( child, child->next, 0, path_cnt, self_cnt ) );
|
||||
while( 1 ) {
|
||||
search_list = *parent_is_trusted ? trust_ca : child->next;
|
||||
|
||||
ret = x509_crt_find_parent_in( child, search_list,
|
||||
parent, signature_is_good,
|
||||
*parent_is_trusted,
|
||||
path_cnt, self_cnt, rs_ctx );
|
||||
|
||||
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
|
||||
{
|
||||
/* save state */
|
||||
rs_ctx->parent_is_trusted = *parent_is_trusted;
|
||||
return( ret );
|
||||
}
|
||||
#else
|
||||
(void) ret;
|
||||
#endif
|
||||
|
||||
/* stop here if found or already in second iteration */
|
||||
if( *parent != NULL || *parent_is_trusted == 0 )
|
||||
break;
|
||||
|
||||
/* prepare second iteration */
|
||||
*parent_is_trusted = 0;
|
||||
}
|
||||
|
||||
/* extra precaution against mistakes in the caller */
|
||||
if( parent == NULL )
|
||||
{
|
||||
*parent_is_trusted = 0;
|
||||
*signature_is_good = 0;
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2097,11 +2234,24 @@ static int x509_crt_check_ee_locally_trusted(
|
||||
* - EE, Ci1, ..., Ciq cannot be continued with a trusted root
|
||||
* -> return that chain with NOT_TRUSTED set on Ciq
|
||||
*
|
||||
* Tests for (aspects of) this function should include at least:
|
||||
* - trusted EE
|
||||
* - EE -> trusted root
|
||||
* - EE -> intermedate CA -> trusted root
|
||||
* - if relevant: EE untrusted
|
||||
* - if relevant: EE -> intermediate, untrusted
|
||||
* with the aspect under test checked at each relevant level (EE, int, root).
|
||||
* For some aspects longer chains are required, but usually length 2 is
|
||||
* enough (but length 1 is not in general).
|
||||
*
|
||||
* Arguments:
|
||||
* - [in] crt: the cert list EE, C1, ..., Cn
|
||||
* - [in] trust_ca: the trusted list R1, ..., Rp
|
||||
* - [in] ca_crl, profile: as in verify_with_profile()
|
||||
* - [out] ver_chain, chain_len: the built and verified chain
|
||||
* - [out] ver_chain: the built and verified chain
|
||||
* Only valid when return value is 0, may contain garbage otherwise!
|
||||
* Restart note: need not be the same when calling again to resume.
|
||||
* - [in-out] rs_ctx: context for restarting operations
|
||||
*
|
||||
* Return value:
|
||||
* - non-zero if the chain could not be fully built and examined
|
||||
@@ -2113,24 +2263,50 @@ static int x509_crt_verify_chain(
|
||||
mbedtls_x509_crt *trust_ca,
|
||||
mbedtls_x509_crl *ca_crl,
|
||||
const mbedtls_x509_crt_profile *profile,
|
||||
x509_crt_verify_chain_item ver_chain[X509_MAX_VERIFY_CHAIN_SIZE],
|
||||
size_t *chain_len )
|
||||
mbedtls_x509_crt_verify_chain *ver_chain,
|
||||
mbedtls_x509_crt_restart_ctx *rs_ctx )
|
||||
{
|
||||
/* Don't initialize any of those variables here, so that the compiler can
|
||||
* catch potential issues with jumping ahead when restarting */
|
||||
int ret;
|
||||
uint32_t *flags;
|
||||
mbedtls_x509_crt_verify_chain_item *cur;
|
||||
mbedtls_x509_crt *child;
|
||||
mbedtls_x509_crt *parent;
|
||||
int parent_is_trusted = 0;
|
||||
int child_is_trusted = 0;
|
||||
size_t self_cnt = 0;
|
||||
int parent_is_trusted;
|
||||
int child_is_trusted;
|
||||
int signature_is_good;
|
||||
unsigned self_cnt;
|
||||
|
||||
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
/* resume if we had an operation in progress */
|
||||
if( rs_ctx != NULL && rs_ctx->in_progress == x509_crt_rs_find_parent )
|
||||
{
|
||||
/* restore saved state */
|
||||
*ver_chain = rs_ctx->ver_chain; /* struct copy */
|
||||
self_cnt = rs_ctx->self_cnt;
|
||||
|
||||
/* restore derived state */
|
||||
cur = &ver_chain->items[ver_chain->len - 1];
|
||||
child = cur->crt;
|
||||
flags = &cur->flags;
|
||||
|
||||
goto find_parent;
|
||||
}
|
||||
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
|
||||
|
||||
child = crt;
|
||||
*chain_len = 0;
|
||||
self_cnt = 0;
|
||||
parent_is_trusted = 0;
|
||||
child_is_trusted = 0;
|
||||
|
||||
while( 1 ) {
|
||||
/* Add certificate to the verification chain */
|
||||
ver_chain[*chain_len].crt = child;
|
||||
flags = &ver_chain[*chain_len].flags;
|
||||
++*chain_len;
|
||||
cur = &ver_chain->items[ver_chain->len];
|
||||
cur->crt = child;
|
||||
cur->flags = 0;
|
||||
ver_chain->len++;
|
||||
flags = &cur->flags;
|
||||
|
||||
/* Check time-validity (all certificates) */
|
||||
if( mbedtls_x509_time_is_past( &child->valid_to ) )
|
||||
@@ -2151,15 +2327,33 @@ static int x509_crt_verify_chain(
|
||||
*flags |= MBEDTLS_X509_BADCERT_BAD_PK;
|
||||
|
||||
/* Special case: EE certs that are locally trusted */
|
||||
if( *chain_len == 1 &&
|
||||
if( ver_chain->len == 1 &&
|
||||
x509_crt_check_ee_locally_trusted( child, trust_ca ) == 0 )
|
||||
{
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
find_parent:
|
||||
#endif
|
||||
/* Look for a parent in trusted CAs or up the chain */
|
||||
parent = x509_crt_find_parent( child, trust_ca, &parent_is_trusted,
|
||||
*chain_len - 1, self_cnt );
|
||||
ret = x509_crt_find_parent( child, trust_ca, &parent,
|
||||
&parent_is_trusted, &signature_is_good,
|
||||
ver_chain->len - 1, self_cnt, rs_ctx );
|
||||
|
||||
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
|
||||
{
|
||||
/* save state */
|
||||
rs_ctx->in_progress = x509_crt_rs_find_parent;
|
||||
rs_ctx->self_cnt = self_cnt;
|
||||
rs_ctx->ver_chain = *ver_chain; /* struct copy */
|
||||
|
||||
return( ret );
|
||||
}
|
||||
#else
|
||||
(void) ret;
|
||||
#endif
|
||||
|
||||
/* No parent? We're done here */
|
||||
if( parent == NULL )
|
||||
@@ -2171,7 +2365,7 @@ static int x509_crt_verify_chain(
|
||||
/* Count intermediate self-issued (not necessarily self-signed) certs.
|
||||
* These can occur with some strategies for key rollover, see [SIRO],
|
||||
* and should be excluded from max_pathlen checks. */
|
||||
if( *chain_len != 1 &&
|
||||
if( ver_chain->len != 1 &&
|
||||
x509_name_cmp( &child->issuer, &child->subject ) == 0 )
|
||||
{
|
||||
self_cnt++;
|
||||
@@ -2180,14 +2374,14 @@ static int x509_crt_verify_chain(
|
||||
/* path_cnt is 0 for the first intermediate CA,
|
||||
* and if parent is trusted it's not an intermediate CA */
|
||||
if( ! parent_is_trusted &&
|
||||
*chain_len > MBEDTLS_X509_MAX_INTERMEDIATE_CA )
|
||||
ver_chain->len > MBEDTLS_X509_MAX_INTERMEDIATE_CA )
|
||||
{
|
||||
/* return immediately to avoid overflow the chain array */
|
||||
return( MBEDTLS_ERR_X509_FATAL_ERROR );
|
||||
}
|
||||
|
||||
/* if parent is trusted, the signature was checked by find_parent() */
|
||||
if( ! parent_is_trusted && x509_crt_check_signature( child, parent ) != 0 )
|
||||
/* signature was checked while searching parent */
|
||||
if( ! signature_is_good )
|
||||
*flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED;
|
||||
|
||||
/* check size of signing key */
|
||||
@@ -2205,6 +2399,7 @@ static int x509_crt_verify_chain(
|
||||
child = parent;
|
||||
parent = NULL;
|
||||
child_is_trusted = parent_is_trusted;
|
||||
signature_is_good = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2273,21 +2468,22 @@ static void x509_crt_verify_name( const mbedtls_x509_crt *crt,
|
||||
*/
|
||||
static int x509_crt_merge_flags_with_cb(
|
||||
uint32_t *flags,
|
||||
x509_crt_verify_chain_item ver_chain[X509_MAX_VERIFY_CHAIN_SIZE],
|
||||
size_t chain_len,
|
||||
const mbedtls_x509_crt_verify_chain *ver_chain,
|
||||
int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
|
||||
void *p_vrfy )
|
||||
{
|
||||
int ret;
|
||||
size_t i;
|
||||
unsigned i;
|
||||
uint32_t cur_flags;
|
||||
const mbedtls_x509_crt_verify_chain_item *cur;
|
||||
|
||||
for( i = chain_len; i != 0; --i )
|
||||
for( i = ver_chain->len; i != 0; --i )
|
||||
{
|
||||
cur_flags = ver_chain[i-1].flags;
|
||||
cur = &ver_chain->items[i-1];
|
||||
cur_flags = cur->flags;
|
||||
|
||||
if( NULL != f_vrfy )
|
||||
if( ( ret = f_vrfy( p_vrfy, ver_chain[i-1].crt, (int) i-1, &cur_flags ) ) != 0 )
|
||||
if( ( ret = f_vrfy( p_vrfy, cur->crt, (int) i-1, &cur_flags ) ) != 0 )
|
||||
return( ret );
|
||||
|
||||
*flags |= cur_flags;
|
||||
@@ -2297,7 +2493,7 @@ static int x509_crt_merge_flags_with_cb(
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify the certificate validity
|
||||
* Verify the certificate validity (default profile, not restartable)
|
||||
*/
|
||||
int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt,
|
||||
mbedtls_x509_crt *trust_ca,
|
||||
@@ -2306,19 +2502,13 @@ int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt,
|
||||
int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
|
||||
void *p_vrfy )
|
||||
{
|
||||
return( mbedtls_x509_crt_verify_with_profile( crt, trust_ca, ca_crl,
|
||||
&mbedtls_x509_crt_profile_default, cn, flags, f_vrfy, p_vrfy ) );
|
||||
return( mbedtls_x509_crt_verify_restartable( crt, trust_ca, ca_crl,
|
||||
&mbedtls_x509_crt_profile_default, cn, flags,
|
||||
f_vrfy, p_vrfy, NULL ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify the certificate validity, with profile
|
||||
*
|
||||
* This function:
|
||||
* - checks the requested CN (if any)
|
||||
* - checks the type and size of the EE cert's key,
|
||||
* as that isn't done as part of chain building/verification currently
|
||||
* - builds and verifies the chain
|
||||
* - then calls the callback and merges the flags
|
||||
* Verify the certificate validity (user-chosen profile, not restartable)
|
||||
*/
|
||||
int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt,
|
||||
mbedtls_x509_crt *trust_ca,
|
||||
@@ -2327,16 +2517,38 @@ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt,
|
||||
const char *cn, uint32_t *flags,
|
||||
int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
|
||||
void *p_vrfy )
|
||||
{
|
||||
return( mbedtls_x509_crt_verify_restartable( crt, trust_ca, ca_crl,
|
||||
profile, cn, flags, f_vrfy, p_vrfy, NULL ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify the certificate validity, with profile, restartable version
|
||||
*
|
||||
* This function:
|
||||
* - checks the requested CN (if any)
|
||||
* - checks the type and size of the EE cert's key,
|
||||
* as that isn't done as part of chain building/verification currently
|
||||
* - builds and verifies the chain
|
||||
* - then calls the callback and merges the flags
|
||||
*/
|
||||
int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt,
|
||||
mbedtls_x509_crt *trust_ca,
|
||||
mbedtls_x509_crl *ca_crl,
|
||||
const mbedtls_x509_crt_profile *profile,
|
||||
const char *cn, uint32_t *flags,
|
||||
int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
|
||||
void *p_vrfy,
|
||||
mbedtls_x509_crt_restart_ctx *rs_ctx )
|
||||
{
|
||||
int ret;
|
||||
mbedtls_pk_type_t pk_type;
|
||||
x509_crt_verify_chain_item ver_chain[X509_MAX_VERIFY_CHAIN_SIZE];
|
||||
size_t chain_len;
|
||||
uint32_t *ee_flags = &ver_chain[0].flags;
|
||||
mbedtls_x509_crt_verify_chain ver_chain;
|
||||
uint32_t ee_flags;
|
||||
|
||||
*flags = 0;
|
||||
memset( ver_chain, 0, sizeof( ver_chain ) );
|
||||
chain_len = 0;
|
||||
ee_flags = 0;
|
||||
x509_crt_verify_chain_reset( &ver_chain );
|
||||
|
||||
if( profile == NULL )
|
||||
{
|
||||
@@ -2346,28 +2558,36 @@ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt,
|
||||
|
||||
/* check name if requested */
|
||||
if( cn != NULL )
|
||||
x509_crt_verify_name( crt, cn, ee_flags );
|
||||
x509_crt_verify_name( crt, cn, &ee_flags );
|
||||
|
||||
/* Check the type and size of the key */
|
||||
pk_type = mbedtls_pk_get_type( &crt->pk );
|
||||
|
||||
if( x509_profile_check_pk_alg( profile, pk_type ) != 0 )
|
||||
*ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK;
|
||||
ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK;
|
||||
|
||||
if( x509_profile_check_key( profile, &crt->pk ) != 0 )
|
||||
*ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
|
||||
ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
|
||||
|
||||
/* Check the chain */
|
||||
ret = x509_crt_verify_chain( crt, trust_ca, ca_crl, profile,
|
||||
ver_chain, &chain_len );
|
||||
&ver_chain, rs_ctx );
|
||||
|
||||
if( ret != 0 )
|
||||
goto exit;
|
||||
|
||||
/* Merge end-entity flags */
|
||||
ver_chain.items[0].flags |= ee_flags;
|
||||
|
||||
/* Build final flags, calling callback on the way if any */
|
||||
ret = x509_crt_merge_flags_with_cb( flags,
|
||||
ver_chain, chain_len, f_vrfy, p_vrfy );
|
||||
ret = x509_crt_merge_flags_with_cb( flags, &ver_chain, f_vrfy, p_vrfy );
|
||||
|
||||
exit:
|
||||
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
|
||||
mbedtls_x509_crt_restart_free( rs_ctx );
|
||||
#endif
|
||||
|
||||
/* prevent misuse of the vrfy callback - VERIFY_FAILED would be ignored by
|
||||
* the SSL module for authmode optional, but non-zero return from the
|
||||
* callback means a fatal error so it shouldn't be ignored */
|
||||
@@ -2478,4 +2698,36 @@ void mbedtls_x509_crt_free( mbedtls_x509_crt *crt )
|
||||
while( cert_cur != NULL );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
/*
|
||||
* Initialize a restart context
|
||||
*/
|
||||
void mbedtls_x509_crt_restart_init( mbedtls_x509_crt_restart_ctx *ctx )
|
||||
{
|
||||
mbedtls_pk_restart_init( &ctx->pk );
|
||||
|
||||
ctx->parent = NULL;
|
||||
ctx->fallback_parent = NULL;
|
||||
ctx->fallback_signature_is_good = 0;
|
||||
|
||||
ctx->parent_is_trusted = -1;
|
||||
|
||||
ctx->in_progress = x509_crt_rs_none;
|
||||
ctx->self_cnt = 0;
|
||||
x509_crt_verify_chain_reset( &ctx->ver_chain );
|
||||
}
|
||||
|
||||
/*
|
||||
* Free the components of a restart context
|
||||
*/
|
||||
void mbedtls_x509_crt_restart_free( mbedtls_x509_crt_restart_ctx *ctx )
|
||||
{
|
||||
if( ctx == NULL )
|
||||
return;
|
||||
|
||||
mbedtls_pk_restart_free( &ctx->pk );
|
||||
mbedtls_x509_crt_restart_init( ctx );
|
||||
}
|
||||
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
|
||||
|
||||
#endif /* MBEDTLS_X509_CRT_PARSE_C */
|
||||
|
||||
@@ -274,34 +274,25 @@ int mbedtls_x509_csr_parse( mbedtls_x509_csr *csr, const unsigned char *buf, siz
|
||||
return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
|
||||
|
||||
#if defined(MBEDTLS_PEM_PARSE_C)
|
||||
mbedtls_pem_init( &pem );
|
||||
|
||||
/* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
|
||||
if( buf[buflen - 1] != '\0' )
|
||||
ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
|
||||
else
|
||||
if( buf[buflen - 1] == '\0' )
|
||||
{
|
||||
mbedtls_pem_init( &pem );
|
||||
ret = mbedtls_pem_read_buffer( &pem,
|
||||
"-----BEGIN CERTIFICATE REQUEST-----",
|
||||
"-----END CERTIFICATE REQUEST-----",
|
||||
buf, NULL, 0, &use_len );
|
||||
|
||||
if( ret == 0 )
|
||||
{
|
||||
/*
|
||||
* Was PEM encoded, parse the result
|
||||
*/
|
||||
if( ( ret = mbedtls_x509_csr_parse_der( csr, pem.buf, pem.buflen ) ) != 0 )
|
||||
return( ret );
|
||||
if( ret == 0 )
|
||||
/*
|
||||
* Was PEM encoded, parse the result
|
||||
*/
|
||||
ret = mbedtls_x509_csr_parse_der( csr, pem.buf, pem.buflen );
|
||||
|
||||
mbedtls_pem_free( &pem );
|
||||
return( 0 );
|
||||
if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
|
||||
return( ret );
|
||||
}
|
||||
else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
|
||||
{
|
||||
mbedtls_pem_free( &pem );
|
||||
return( ret );
|
||||
}
|
||||
else
|
||||
#endif /* MBEDTLS_PEM_PARSE_C */
|
||||
return( mbedtls_x509_csr_parse_der( csr, buf, buflen ) );
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user