@ -47,6 +47,22 @@
# include <stdio.h>
# endif
# elif defined(USE_CRYPTO_MBEDTLS)
# include <mbedtls/md5.h>
# include <mbedtls/entropy.h>
# include <mbedtls/ctr_drbg.h>
# include <mbedtls/version.h>
# define CIPHER_UNSUPPORTED "unsupported"
# include <time.h>
# ifdef _WIN32
# include <windows.h>
# include <wincrypt.h>
# else
# include <stdio.h>
# endif
# endif
# include <sodium.h>
@ -119,6 +135,30 @@ static const char * supported_ciphers_polarssl[CIPHER_NUM] =
} ;
# endif
# ifdef USE_CRYPTO_MBEDTLS
/ / FIXME : check it
static const char * supported_ciphers_mbedtls [ CIPHER_NUM ] =
{
" table " ,
" ARC4-128 " ,
" ARC4-128 " ,
" AES-128-CFB128 " ,
" AES-192-CFB128 " ,
" AES-256-CFB128 " ,
" BLOWFISH-CFB64 " ,
" CAMELLIA-128-CFB128 " ,
" CAMELLIA-192-CFB128 " ,
" CAMELLIA-256-CFB128 " ,
CIPHER_UNSUPPORTED ,
CIPHER_UNSUPPORTED ,
CIPHER_UNSUPPORTED ,
CIPHER_UNSUPPORTED ,
CIPHER_UNSUPPORTED ,
" salsa20 " ,
" chacha20 "
} ;
# endif
# ifdef USE_CRYPTO_APPLECC
static const CCAlgorithm supported_ciphers_applecc [ CIPHER_NUM ] =
{
@ -261,6 +301,13 @@ unsigned char *enc_md5(const unsigned char *d, size_t n, unsigned char *md)
}
md5 ( d , n , md ) ;
return md ;
# elif defined(USE_CRYPTO_MBEDTLS)
static unsigned char m [ 16 ] ;
if ( md = = NULL ) {
md = m ;
}
mbedtls_md5 ( d , n , md ) ;
return md ;
# endif
}
@ -295,7 +342,8 @@ int cipher_iv_size(const cipher_kt_t *cipher)
{
# if defined(USE_CRYPTO_OPENSSL)
return EVP_CIPHER_iv_length ( cipher ) ;
# elif defined(USE_CRYPTO_POLARSSL)
# elif defined(USE_CRYPTO_POLARSSL) || defined(USE_CRYPTO_MBEDTLS)
/ / FIXME : check data structure of cipher
if ( cipher = = NULL ) {
return 0 ;
}
@ -317,6 +365,21 @@ int cipher_key_size(const cipher_kt_t *cipher)
return 128 / 8 ;
}
return cipher - > key_length / 8 ;
# elif defined(USE_CRYPTO_MBEDTLS)
/ / FIXME : ditto , cipher data structure
/*
* Semi - API changes ( technically public , morally private )
* Renamed a few headers to include _internal in the name . Those headers are
not supposed to be included by users .
* Changed md_info_t into an opaque structure ( use md_get_xxx ( ) accessors ) .
* Changed pk_info_t into an opaque structure .
* Changed cipher_base_t into an opaque structure .
*/
if ( cipher = = NULL ) {
return 0 ;
}
/* From Version 1.2.7 released 2013-04-13 Default Blowfish keysize is now 128-bits */
return cipher - > key_bitlen / 8 ;
# endif
}
@ -416,6 +479,123 @@ int bytes_to_key(const cipher_kt_t *cipher, const digest_type_t *md,
md_free_ctx ( & c ) ;
memset ( md_buf , 0 , MAX_MD_SIZE ) ;
return rv ;
# elif defined(USE_CRYPTO_MBEDTLS)
/*
*
* Generic message digest context .
typedef struct {
Information about the associated message digest
const mbedtls_md_info_t * md_info ;
Digest - specific context
void * md_ctx ;
HMAC part of the context
void * hmac_ctx ;
} mbedtls_md_context_t ; / / mbedtls 2.0 .0
typedef struct {
Information about the associated message digest
const md_info_t * md_info ;
Digest - specific context
void * md_ctx ;
} md_context_t ; / / polarssl 1.3
*/
/ / NOTE : different struct body , initialize new param hmac 0 to disable HMAC
mbedtls_md_context_t c ;
unsigned char md_buf [ MAX_MD_SIZE ] ;
int niv ;
int nkey ;
int addmd ;
unsigned int mds ;
unsigned int i ;
int rv ;
nkey = cipher_key_size ( cipher ) ;
niv = cipher_iv_size ( cipher ) ;
rv = nkey ;
if ( pass = = NULL ) {
return nkey ;
}
memset ( & c , 0 , sizeof ( mbedtls_md_context_t ) ) ;
/ / FIXME : md_init_ctx superseded by mbedtls_md_setup ( ) in 2.0 .0
/ / new param hmac 0 to save some meory ( maybe a typo ? memory ? ) is HMAC will not be use ,
/ / non - zero is HMAC is going to be used with this context .
if ( mbedtls_md_setup ( & c , md , 0 ) ) {
return 0 ;
}
addmd = 0 ;
mds = mbedtls_md_get_size ( md ) ;
for ( ; ; ) {
int error ;
do {
error = 1 ;
if ( mbedtls_md_starts ( & c ) ) {
break ;
}
if ( addmd ) {
if ( mbedtls_md_update ( & c , & ( md_buf [ 0 ] ) , mds ) ) {
break ;
}
} else {
addmd = 1 ;
}
if ( mbedtls_md_update ( & c , pass , datal ) ) {
break ;
}
if ( mbedtls_md_finish ( & c , & ( md_buf [ 0 ] ) ) ) {
break ;
}
error = 0 ;
} while ( 0 ) ;
if ( error ) {
mbedtls_md_free ( & c ) ; / / md_free_ctx deprecated , Use mbedtls_md_free ( ) instead
memset ( md_buf , 0 , MAX_MD_SIZE ) ;
return 0 ;
}
i = 0 ;
if ( nkey ) {
for ( ; ; ) {
if ( nkey = = 0 ) {
break ;
}
if ( i = = mds ) {
break ;
}
if ( key ! = NULL ) {
* ( key + + ) = md_buf [ i ] ;
}
nkey - - ;
i + + ;
}
}
if ( niv & & ( i ! = mds ) ) {
for ( ; ; ) {
if ( niv = = 0 ) {
break ;
}
if ( i = = mds ) {
break ;
}
if ( iv ! = NULL ) {
* ( iv + + ) = md_buf [ i ] ;
}
niv - - ;
i + + ;
}
}
if ( ( nkey = = 0 ) & & ( niv = = 0 ) ) {
break ;
}
}
mbedtls_md_free ( & c ) ; / / NOTE : md_free_ctx deprecated , Use mbedtls_md_free ( ) instead
memset ( md_buf , 0 , MAX_MD_SIZE ) ;
return rv ;
# endif
}
@ -482,6 +662,66 @@ int rand_bytes(uint8_t *output, int len)
len - = blen ;
}
return 1 ;
# elif defined(USE_CRYPTO_MBEDTLS)
static mbedtls_entropy_context ec = { } ;
/ / FIXME : ctr_drbg_context changed , [ if defined ( MBEDTLS_THREADING_C ) mbedtls_threading_mutex_t mutex ; ]
static mbedtls_ctr_drbg_context cd_ctx = { } ;
static unsigned char rand_initialised = 0 ;
const size_t blen = min ( len , MBEDTLS_CTR_DRBG_MAX_REQUEST ) ;
if ( ! rand_initialised ) {
# ifdef _WIN32
HCRYPTPROV hProvider ;
union {
unsigned __int64 seed ;
BYTE buffer [ 8 ] ;
} rand_buffer ;
hProvider = 0 ;
if ( CryptAcquireContext ( & hProvider , 0 , 0 , PROV_RSA_FULL , \
CRYPT_VERIFYCONTEXT | CRYPT_SILENT ) ) {
CryptGenRandom ( hProvider , 8 , rand_buffer . buffer ) ;
CryptReleaseContext ( hProvider , 0 ) ;
} else {
rand_buffer . seed = ( unsigned __int64 ) clock ( ) ;
}
# else
FILE * urand ;
union {
uint64_t seed ;
uint8_t buffer [ 8 ] ;
} rand_buffer ;
urand = fopen ( " /dev/urandom " , " r " ) ;
if ( urand ) {
int read = fread ( & rand_buffer . seed , sizeof ( rand_buffer . seed ) , 1 ,
urand ) ;
fclose ( urand ) ;
if ( read < = 0 ) {
rand_buffer . seed = ( uint64_t ) clock ( ) ;
}
} else {
rand_buffer . seed = ( uint64_t ) clock ( ) ;
}
# endif
mbedtls_entropy_init ( & ec ) ;
/ / FIXME : ctr_drbg_init changed , seems we should initialize it before calling mbedtls_ctr_drbg_seed ( )
mbedtls_ctr_drbg_init ( & cd_ctx ) ;
if ( mbedtls_ctr_drbg_seed ( & cd_ctx , mbedtls_entropy_func , & ec ,
( const unsigned char * ) rand_buffer . buffer , 8 ) ! = 0 ) {
mbedtls_entropy_free ( & ec ) ;
FATAL ( " mbed TLS: Failed to initialize random generator " ) ;
}
rand_initialised = 1 ;
}
while ( len > 0 ) {
if ( mbedtls_ctr_drbg_random ( & cd_ctx , output , blen ) ! = 0 ) {
return 0 ;
}
output + = blen ;
len - = blen ;
}
return 1 ;
# endif
}
@ -511,6 +751,14 @@ const cipher_kt_t *get_cipher_type(int method)
return NULL ;
}
return cipher_info_from_string ( polarname ) ;
# elif defined(USE_CRYPTO_MBEDTLS)
const char * mbedtlsname = supported_ciphers_mbedtls [ method ] ;
if ( strcmp ( mbedtlsname , CIPHER_UNSUPPORTED ) = = 0 ) {
LOGE ( " Cipher %s currently is not supported by mbed TLS library " ,
ciphername ) ;
return NULL ;
}
return mbedtls_cipher_info_from_string ( mbedtlsname ) ;
# endif
}
@ -525,6 +773,8 @@ const digest_type_t *get_digest_type(const char *digest)
return EVP_get_digestbyname ( digest ) ;
# elif defined(USE_CRYPTO_POLARSSL)
return md_info_from_string ( digest ) ;
# elif defined(USE_CRYPTO_MBEDTLS)
return mbedtls_md_info_from_string ( digest ) ;
# endif
}
@ -588,6 +838,19 @@ void cipher_context_init(cipher_ctx_t *ctx, int method, int enc)
if ( cipher_init_ctx ( evp , cipher ) ! = 0 ) {
FATAL ( " Cannot initialize PolarSSL cipher context " ) ;
}
# elif defined(USE_CRYPTO_MBEDTLS)
/ / FIXME : mbedtls_cipher_setup future change
/ / NOTE : Currently also clears structure . In future versions you will be required to call
/ / mbedtls_cipher_init ( ) on the structure first .
/ / void mbedtls_cipher_init ( mbedtls_cipher_context_t * ctx ) ;
if ( cipher = = NULL ) {
LOGE ( " Cipher %s not found in mbed TLS library " , ciphername ) ;
FATAL ( " Cannot initialize mbed TLS cipher " ) ;
}
mbedtls_cipher_init ( evp ) ;
if ( mbedtls_cipher_setup ( evp , cipher ) ! = 0 ) {
FATAL ( " Cannot initialize mbed TLS cipher context " ) ;
}
# endif
}
@ -664,6 +927,7 @@ void cipher_context_set_iv(cipher_ctx_t *ctx, uint8_t *iv, size_t iv_len,
FATAL ( " Cannot set key and IV " ) ;
}
# elif defined(USE_CRYPTO_POLARSSL)
/ / FIXME : PolarSSL 1.3 .11 : cipher_free_ctx deprecated , Use cipher_free ( ) instead .
if ( cipher_setkey ( evp , true_key , enc_key_len * 8 , enc ) ! = 0 ) {
cipher_free_ctx ( evp ) ;
FATAL ( " Cannot set PolarSSL cipher key " ) ;
@ -683,6 +947,21 @@ void cipher_context_set_iv(cipher_ctx_t *ctx, uint8_t *iv, size_t iv_len,
FATAL ( " Cannot set PolarSSL cipher IV " ) ;
}
# endif
# elif defined(USE_CRYPTO_MBEDTLS)
/ / FIXME : cipher_free_ctx deprecated , Use cipher_free ( ) instead in PolarSSL 1.3 .11
if ( mbedtls_cipher_setkey ( evp , true_key , enc_key_len * 8 , enc ) ! = 0 ) {
mbedtls_cipher_free ( evp ) ;
FATAL ( " Cannot set mbed TLS cipher key " ) ;
}
if ( mbedtls_cipher_set_iv ( evp , iv , iv_len ) ! = 0 ) {
mbedtls_cipher_free ( evp ) ;
FATAL ( " Cannot set mbed TLS cipher IV " ) ;
}
if ( mbedtls_cipher_reset ( evp ) ! = 0 ) {
mbedtls_cipher_free ( evp ) ;
FATAL ( " Cannot finalize mbed TLS cipher context " ) ;
}
# endif
# ifdef DEBUG
@ -711,7 +990,11 @@ void cipher_context_release(cipher_ctx_t *ctx)
# if defined(USE_CRYPTO_OPENSSL)
EVP_CIPHER_CTX_cleanup ( evp ) ;
# elif defined(USE_CRYPTO_POLARSSL)
/ / NOTE : cipher_free_ctx deprecated in PolarSSL 1.3 .11
cipher_free_ctx ( evp ) ;
# elif defined(USE_CRYPTO_MBEDTLS)
/ / NOTE : cipher_free_ctx deprecated
mbedtls_cipher_free ( evp ) ;
# endif
}
@ -734,6 +1017,9 @@ static int cipher_context_update(cipher_ctx_t *ctx, uint8_t *output, int *olen,
# elif defined(USE_CRYPTO_POLARSSL)
return ! cipher_update ( evp , ( const uint8_t * ) input , ( size_t ) ilen ,
( uint8_t * ) output , ( size_t * ) olen ) ;
# elif defined(USE_CRYPTO_MBEDTLS)
return ! mbedtls_cipher_update ( evp , ( const uint8_t * ) input , ( size_t ) ilen ,
( uint8_t * ) output , ( size_t * ) olen ) ;
# endif
}
@ -1073,6 +1359,12 @@ void enc_key_init(int method, const char *pass)
cipher - > base = NULL ;
cipher - > key_length = supported_ciphers_key_size [ method ] * 8 ;
cipher - > iv_size = supported_ciphers_iv_size [ method ] ;
# endif
# if defined(USE_CRYPTO_MBEDTLS)
/ / FIXME : key_length changed to key_bitlen in mbed TLS 2.0 .0
cipher - > base = NULL ;
cipher - > key_bitlen = supported_ciphers_key_size [ method ] * 8 ;
cipher - > iv_size = supported_ciphers_iv_size [ method ] ;
# endif
} else {
cipher = ( cipher_kt_t * ) get_cipher_type ( method ) ;
@ -1088,6 +1380,16 @@ void enc_key_init(int method, const char *pass)
cipher = ( cipher_kt_t * ) & cipher_info ;
break ;
}
# endif
# if defined(USE_CRYPTO_MBEDTLS) && defined(USE_CRYPTO_APPLECC)
/ / FIXME : key_length changed to key_bitlen in mbed TLS 2.0 .0
if ( supported_ciphers_applecc [ method ] ! = kCCAlgorithmInvalid ) {
cipher_info . base = NULL ;
cipher_info . key_bitlen = supported_ciphers_key_size [ method ] * 8 ;
cipher_info . iv_size = supported_ciphers_iv_size [ method ] ;
cipher = ( cipher_kt_t * ) & cipher_info ;
break ;
}
# endif
LOGE ( " Cipher %s not found in crypto library " ,
supported_ciphers [ method ] ) ;