diff --git a/include/polarssl/pk.h b/include/polarssl/pk.h index ab21e50a5..6135bb013 100644 --- a/include/polarssl/pk.h +++ b/include/polarssl/pk.h @@ -82,6 +82,7 @@ typedef enum { POLARSSL_PK_ECKEY, POLARSSL_PK_ECKEY_DH, POLARSSL_PK_ECDSA, + POLARSSL_PK_RSA_ALT, } pk_type_t; /** @@ -168,6 +169,18 @@ typedef struct void * pk_ctx; /**< Underlying public key context */ } pk_context; +/** + * \brief Types for RSA-alt abstraction + */ +typedef int (*pk_rsa_alt_decrypt_func)( void *ctx, int mode, size_t *olen, + const unsigned char *input, unsigned char *output, + size_t output_max_len ); +typedef int (*pk_rsa_alt_sign_func)( void *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + int mode, int hash_id, unsigned int hashlen, + const unsigned char *hash, unsigned char *sig ); +typedef size_t (*pk_rsa_alt_key_len_func)( void *ctx ); + /** * \brief Return information associated with the given PK type * @@ -182,6 +195,11 @@ const pk_info_t *pk_info_from_type( pk_type_t pk_type ); */ void pk_init( pk_context *ctx ); +/** + * \brief Free a pk_context + */ +void pk_free( pk_context *ctx ); + /** * \brief Initialize a PK context with the information given * and allocates the type-specific PK subcontext. @@ -192,13 +210,30 @@ void pk_init( pk_context *ctx ); * \return 0 on success, * POLARSSL_ERR_PK_BAD_INPUT_DATA on invalid input, * POLARSSL_ERR_PK_MALLOC_FAILED on allocation failure. + * + * \note For contexts holding an RSA-alt key, use + * \c pk_init_ctx_rsa_alt() instead. */ int pk_init_ctx( pk_context *ctx, const pk_info_t *info ); /** - * \brief Free a pk_context + * \brief Initialiaze an RSA-alt context + * + * \param ctx Context to initialize. Must be empty (type NONE). + * \param key RSA key pointer + * \param decrypt_func Decryption function + * \param sign_func Signing function + * \param key_len_func Function returning key length + * + * \return 0 on success, or POLARSSL_ERR_PK_BAD_INPUT_DATA if the + * context wasn't already initialized as RSA_ALT. + * + * \note This function replaces \c pk_init_ctx() for RSA-alt. */ -void pk_free( pk_context *ctx ); +int pk_init_ctx_rsa_alt( pk_context *ctx, void * key, + pk_rsa_alt_decrypt_func decrypt_func, + pk_rsa_alt_sign_func sign_func, + pk_rsa_alt_key_len_func key_len_func ); /** * \brief Get the size in bits of the underlying key diff --git a/include/polarssl/pk_wrap.h b/include/polarssl/pk_wrap.h index a24fbd1d1..91a671e02 100644 --- a/include/polarssl/pk_wrap.h +++ b/include/polarssl/pk_wrap.h @@ -32,6 +32,15 @@ #include "pk.h" +/* Container for RSA-alt */ +typedef struct +{ + void *key; + pk_rsa_alt_decrypt_func decrypt_func; + pk_rsa_alt_sign_func sign_func; + pk_rsa_alt_key_len_func key_len_func; +} rsa_alt_context; + #if defined(POLARSSL_RSA_C) extern const pk_info_t rsa_info; #endif @@ -45,4 +54,6 @@ extern const pk_info_t eckeydh_info; extern const pk_info_t ecdsa_info; #endif +extern const pk_info_t rsa_alt_info; + #endif /* POLARSSL_PK_WRAP_H */ diff --git a/library/error.c b/library/error.c index 0ea3c297c..35a4af086 100644 --- a/library/error.c +++ b/library/error.c @@ -251,7 +251,7 @@ void polarssl_strerror( int ret, char *buf, size_t buflen ) if( use_ret == -(POLARSSL_ERR_PK_MALLOC_FAILED) ) snprintf( buf, buflen, "PK - Memory alloation failed" ); if( use_ret == -(POLARSSL_ERR_PK_TYPE_MISMATCH) ) - snprintf( buf, buflen, "PK - Type mismatch, eg attempt to use a RSA key as EC, or to modify key type" ); + snprintf( buf, buflen, "PK - Type mismatch, eg attempt to encrypt with an ECDSA key" ); if( use_ret == -(POLARSSL_ERR_PK_BAD_INPUT_DATA) ) snprintf( buf, buflen, "PK - Bad input parameters to function" ); #endif /* POLARSSL_PK_C */ diff --git a/library/pk.c b/library/pk.c index 6e6057462..e0a252f2b 100644 --- a/library/pk.c +++ b/library/pk.c @@ -84,6 +84,7 @@ const pk_info_t * pk_info_from_type( pk_type_t pk_type ) case POLARSSL_PK_ECDSA: return &ecdsa_info; #endif + /* POLARSSL_PK_RSA_ALT ommited on purpose */ default: return NULL; } @@ -105,6 +106,35 @@ int pk_init_ctx( pk_context *ctx, const pk_info_t *info ) return( 0 ); } +/* + * Initialize an RSA-alt context + */ +int pk_init_ctx_rsa_alt( pk_context *ctx, void * key, + pk_rsa_alt_decrypt_func decrypt_func, + pk_rsa_alt_sign_func sign_func, + pk_rsa_alt_key_len_func key_len_func ) +{ + rsa_alt_context *rsa_alt; + const pk_info_t *info = &rsa_alt_info; + + if( ctx == NULL || ctx->pk_info != NULL ) + return( POLARSSL_ERR_PK_BAD_INPUT_DATA ); + + if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL ) + return( POLARSSL_ERR_PK_MALLOC_FAILED ); + + ctx->pk_info = info; + + rsa_alt = (rsa_alt_context *) ctx->pk_ctx; + + rsa_alt->key = key; + rsa_alt->decrypt_func = decrypt_func; + rsa_alt->sign_func = sign_func; + rsa_alt->key_len_func = key_len_func; + + return( 0 ); +} + /* * Tell if a PK can do the operations of the given type */ diff --git a/library/pk_wrap.c b/library/pk_wrap.c index 2c55ce08f..9f650b631 100644 --- a/library/pk_wrap.c +++ b/library/pk_wrap.c @@ -53,7 +53,7 @@ static int rsa_can_do( pk_type_t type ) return( type == POLARSSL_PK_RSA ); } -static size_t rsa_get_size( const void * ctx ) +static size_t rsa_get_size( const void *ctx ) { return( 8 * ((rsa_context *) ctx)->len ); } @@ -340,3 +340,73 @@ const pk_info_t ecdsa_info = { eckey_debug, /* Compatible key structures */ }; #endif /* POLARSSL_ECDSA_C */ + +/* + * Support for alternative RSA-private implementations + */ + +static size_t rsa_alt_get_size( const void *ctx ) +{ + rsa_alt_context *rsa_alt = (rsa_alt_context *) ctx; + + return( rsa_alt->key_len_func( rsa_alt->key ) ); +} + +static int rsa_alt_sign_wrap( void *ctx, 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 ) +{ + rsa_alt_context *rsa_alt = (rsa_alt_context *) ctx; + + *sig_len = rsa_alt->key_len_func( rsa_alt->key ); + + return( rsa_alt->sign_func( rsa_alt->key, f_rng, p_rng, RSA_PRIVATE, + md_alg, hash_len, hash, sig ) ); +} + +static int rsa_alt_decrypt_wrap( void *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + rsa_alt_context *rsa_alt = (rsa_alt_context *) ctx; + + ((void) f_rng); + ((void) p_rng); + + if( ilen != rsa_alt->key_len_func( rsa_alt->key ) ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + return( rsa_alt->decrypt_func( rsa_alt->key, + RSA_PRIVATE, olen, input, output, osize ) ); +} + +static void *rsa_alt_alloc_wrap( void ) +{ + void *ctx = polarssl_malloc( sizeof( rsa_alt_context ) ); + + if( ctx != NULL ) + memset( ctx, 0, sizeof( rsa_alt_context ) ); + + return ctx; +} + +static void rsa_alt_free_wrap( void *ctx ) +{ + polarssl_free( ctx ); +} + +const pk_info_t rsa_alt_info = { + POLARSSL_PK_RSA_ALT, + "RSA-alt", + rsa_alt_get_size, + rsa_can_do, + NULL, + rsa_alt_sign_wrap, + rsa_alt_decrypt_wrap, + NULL, + rsa_alt_alloc_wrap, + rsa_alt_free_wrap, + NULL, +};