Add RSA-alt to the PK layer
diff --git a/include/polarssl/pk.h b/include/polarssl/pk.h
index ab21e50..6135bb0 100644
--- a/include/polarssl/pk.h
+++ b/include/polarssl/pk.h
@@ -82,6 +82,7 @@
     POLARSSL_PK_ECKEY,
     POLARSSL_PK_ECKEY_DH,
     POLARSSL_PK_ECDSA,
+    POLARSSL_PK_RSA_ALT,
 } pk_type_t;
 
 /**
@@ -169,6 +170,18 @@
 } 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
  *
  * \param type      PK type to search for.
@@ -183,6 +196,11 @@
 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 @@
  * \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 a24fbd1..91a671e 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 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 0ea3c29..35a4af0 100644
--- a/library/error.c
+++ b/library/error.c
@@ -251,7 +251,7 @@
         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 6e60574..e0a252f 100644
--- a/library/pk.c
+++ b/library/pk.c
@@ -84,6 +84,7 @@
         case POLARSSL_PK_ECDSA:
             return &ecdsa_info;
 #endif
+        /* POLARSSL_PK_RSA_ALT ommited on purpose */
         default:
             return NULL;
     }
@@ -106,6 +107,35 @@
 }
 
 /*
+ * 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
  */
 int pk_can_do( pk_context *ctx, pk_type_t type )
diff --git a/library/pk_wrap.c b/library/pk_wrap.c
index 2c55ce0..9f650b6 100644
--- a/library/pk_wrap.c
+++ b/library/pk_wrap.c
@@ -53,7 +53,7 @@
     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 @@
     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,
+};