Add tests and fix bugs for RSA-alt contexts
diff --git a/ChangeLog b/ChangeLog
index 01c9c87..e4147bd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -22,6 +22,8 @@
    * oid_get_numeric_string() used to truncate the output without returning an
      error if the output buffer was just 1 byte too small.
    * dhm_parse_dhm() (hence dhm_parse_dhmfile()) did not set dhm->len.
+   * Calling pk_debug() on an RSA-alt key would segfault.
+   * pk_get_size() and pk_get_len() were off by a factor 8 for RSA-alt keys.
 
 = PolarSSL 1.3.5 released on 2014-03-26
 Features
diff --git a/include/polarssl/pk.h b/include/polarssl/pk.h
index 6f21dab..b764d55 100644
--- a/include/polarssl/pk.h
+++ b/include/polarssl/pk.h
@@ -234,7 +234,7 @@
  * \param key       RSA key pointer
  * \param decrypt_func  Decryption function
  * \param sign_func     Signing function
- * \param key_len_func  Function returning key length
+ * \param key_len_func  Function returning key length in bytes
  *
  * \return          0 on success, or POLARSSL_ERR_PK_BAD_INPUT_DATA if the
  *                  context wasn't already initialized as RSA_ALT.
diff --git a/library/pk.c b/library/pk.c
index 80eccc9..cfde265 100644
--- a/library/pk.c
+++ b/library/pk.c
@@ -258,6 +258,9 @@
     if( ctx == NULL || ctx->pk_info == NULL )
         return( POLARSSL_ERR_PK_BAD_INPUT_DATA );
 
+    if( ctx->pk_info->debug_func == NULL )
+        return( POLARSSL_ERR_PK_TYPE_MISMATCH );
+
     ctx->pk_info->debug_func( ctx->pk_ctx, items );
     return( 0 );
 }
diff --git a/library/pk_wrap.c b/library/pk_wrap.c
index 99535d6..96695d4 100644
--- a/library/pk_wrap.c
+++ b/library/pk_wrap.c
@@ -357,7 +357,7 @@
 {
     const rsa_alt_context *rsa_alt = (const rsa_alt_context *) ctx;
 
-    return( rsa_alt->key_len_func( rsa_alt->key ) );
+    return( 8 * rsa_alt->key_len_func( rsa_alt->key ) );
 }
 
 static int rsa_alt_sign_wrap( void *ctx, md_type_t md_alg,
diff --git a/tests/suites/test_suite_pk.data b/tests/suites/test_suite_pk.data
index e07495a..974748c 100644
--- a/tests/suites/test_suite_pk.data
+++ b/tests/suites/test_suite_pk.data
@@ -77,3 +77,7 @@
 ECDSA nocrypt
 depends_on:POLARSSL_ECDSA_C
 pk_ec_nocrypt:POLARSSL_PK_ECDSA
+
+RSA_ALT consistency
+depends_on:POLARSSL_RSA_C:POLARSSL_PKCS1_V15:POLARSSL_GENPRIME
+pk_rsa_alt:
diff --git a/tests/suites/test_suite_pk.function b/tests/suites/test_suite_pk.function
index 85cdb74..f82ed67 100644
--- a/tests/suites/test_suite_pk.function
+++ b/tests/suites/test_suite_pk.function
@@ -3,13 +3,16 @@
 
 static int rnd_std_rand( void *rng_state, unsigned char *output, size_t len );
 
+#define RSA_KEY_SIZE 512
+#define RSA_KEY_LEN   64
+
 static int pk_genkey( pk_context *pk )
 {
     ((void) pk);
 
 #if defined(POLARSSL_RSA_C) && defined(POLARSSL_GENPRIME)
     if( pk_get_type( pk ) == POLARSSL_PK_RSA )
-        return rsa_gen_key( pk_rsa( *pk ), rnd_std_rand, NULL, 512, 3 );
+        return rsa_gen_key( pk_rsa( *pk ), rnd_std_rand, NULL, RSA_KEY_SIZE, 3 );
 #endif
 #if defined(POLARSSL_ECP_C)
     if( pk_get_type( pk ) == POLARSSL_PK_ECKEY ||
@@ -27,6 +30,28 @@
 #endif
     return( -1 );
 }
+
+#if defined(POLARSSL_RSA_C)
+int rsa_decrypt_func( void *ctx, int mode, size_t *olen,
+                       const unsigned char *input, unsigned char *output,
+                       size_t output_max_len )
+{
+    return( rsa_pkcs1_decrypt( (rsa_context *) ctx, NULL, NULL, mode, olen,
+                               input, output, output_max_len ) );
+}
+int rsa_sign_func( void *ctx,
+                   int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+                   int mode, md_type_t md_alg, unsigned int hashlen,
+                   const unsigned char *hash, unsigned char *sig )
+{
+    return( rsa_pkcs1_sign( (rsa_context *) ctx, f_rng, p_rng, mode,
+                            md_alg, hashlen, hash, sig ) );
+}
+size_t rsa_key_len_func( void *ctx )
+{
+    return( ((const rsa_context *) ctx)->len );
+}
+#endif /* POLARSSL_RSA_C */
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
@@ -282,3 +307,77 @@
     pk_free( &pk );
 }
 /* END_CASE */
+
+/* BEGIN_CASE depends_on:POLARSSL_RSA_C */
+void pk_rsa_alt( )
+{
+    /*
+     * An rsa_alt context can only do private operations (decrypt, sign).
+     * Test it against the public operations (encrypt, verify) of a
+     * corresponding rsa context.
+     */
+    rsa_context raw;
+    pk_context rsa, alt;
+    pk_debug_item dbg_items[10];
+    unsigned char hash[50], sig[1000];
+    unsigned char msg[50], ciph[1000], test[1000];
+    size_t sig_len, ciph_len, test_len;
+    int ret = POLARSSL_ERR_PK_TYPE_MISMATCH;
+
+    rsa_init( &raw, RSA_PKCS_V15, POLARSSL_MD_NONE );
+    pk_init( &rsa ); pk_init( &alt );
+
+    memset( hash, 0x2a, sizeof hash );
+    memset( sig, 0, sizeof sig );
+    memset( msg, 0x2a, sizeof msg );
+    memset( ciph, 0, sizeof ciph );
+    memset( test, 0, sizeof test );
+
+    /* Initiliaze PK RSA context with random key */
+    TEST_ASSERT( pk_init_ctx( &rsa,
+                              pk_info_from_type( POLARSSL_PK_RSA ) ) == 0 );
+    TEST_ASSERT( pk_genkey( &rsa ) == 0 );
+
+    /* Extract key to the raw rsa context */
+    TEST_ASSERT( rsa_copy( &raw, pk_rsa( rsa ) ) == 0 );
+
+    /* Initialize PK RSA_ALT context */
+    TEST_ASSERT( pk_init_ctx_rsa_alt( &alt, (void *) &raw,
+                 rsa_decrypt_func, rsa_sign_func, rsa_key_len_func ) == 0 );
+
+    /* Test administrative functions */
+    TEST_ASSERT( pk_can_do( &alt, POLARSSL_PK_RSA ) );
+    TEST_ASSERT( pk_get_size( &alt ) == RSA_KEY_SIZE );
+    TEST_ASSERT( pk_get_len( &alt ) == RSA_KEY_LEN );
+    TEST_ASSERT( pk_get_type( &alt ) == POLARSSL_PK_RSA_ALT );
+    TEST_ASSERT( strcmp( pk_get_name( &alt ), "RSA-alt" ) == 0 );
+
+    /* Test signature */
+    TEST_ASSERT( pk_sign( &alt, POLARSSL_MD_NONE, hash, sizeof hash,
+                          sig, &sig_len, rnd_std_rand, NULL ) == 0 );
+    TEST_ASSERT( sig_len == RSA_KEY_LEN );
+    TEST_ASSERT( pk_verify( &rsa, POLARSSL_MD_NONE,
+                            hash, sizeof hash, sig, sig_len ) == 0 );
+
+    /* Test decrypt */
+    TEST_ASSERT( pk_encrypt( &rsa, msg, sizeof msg,
+                             ciph, &ciph_len, sizeof ciph,
+                             rnd_std_rand, NULL ) == 0 );
+    TEST_ASSERT( pk_decrypt( &alt, ciph, ciph_len,
+                             test, &test_len, sizeof test,
+                             rnd_std_rand, NULL ) == 0 );
+    TEST_ASSERT( test_len == sizeof msg );
+    TEST_ASSERT( memcmp( test, msg, test_len ) == 0 );
+
+    /* Test forbidden operations */
+    TEST_ASSERT( pk_encrypt( &alt, msg, sizeof msg,
+                             ciph, &ciph_len, sizeof ciph,
+                             rnd_std_rand, NULL ) == ret );
+    TEST_ASSERT( pk_verify( &alt, POLARSSL_MD_NONE,
+                            hash, sizeof hash, sig, sig_len ) == ret );
+    TEST_ASSERT( pk_debug( &alt, dbg_items ) == ret );
+
+    rsa_free( &raw );
+    pk_free( &rsa ); pk_free( &alt );
+}
+/* END_CASE */