From 53019ae6f73e499b8250c771ffe5330cedc53f88 Mon Sep 17 00:00:00 2001
From: Paul Bakker
Date: Fri, 25 Mar 2011 13:58:48 +0000
Subject: [PATCH] - RSASSA-PSS verification now properly handles salt lengths
other than hlen
---
library/rsa.c | 24 ++++++----
library/x509parse.c | 112 +++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 125 insertions(+), 11 deletions(-)
diff --git a/library/rsa.c b/library/rsa.c
index ec44d84e9..0a6c490f0 100644
--- a/library/rsa.c
+++ b/library/rsa.c
@@ -580,7 +580,7 @@ int rsa_pkcs1_sign( rsa_context *ctx,
unsigned char salt[POLARSSL_MD_MAX_SIZE];
const md_info_t *md_info;
md_context_t md_ctx;
- int i, hlen, msb, offset = 0;
+ int i, slen, hlen, msb, offset = 0;
#else
(void) f_rng;
(void) p_rng;
@@ -733,6 +733,8 @@ int rsa_pkcs1_sign( rsa_context *ctx,
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
hlen = md_get_size( md_info );
+ slen = hlen;
+
memset( sig, 0, olen );
memset( &md_ctx, 0, sizeof( md_context_t ) );
@@ -740,9 +742,9 @@ int rsa_pkcs1_sign( rsa_context *ctx,
msb = mpi_msb( &ctx->N ) - 1;
- // Generate salt of length hlen
+ // Generate salt of length slen
//
- for( i = 0; i < hlen; ++i )
+ for( i = 0; i < slen; ++i )
salt[i] = (unsigned char) f_rng( p_rng );
// Note: EMSA-PSS encoding is over the length of N - 1 bits
@@ -750,15 +752,15 @@ int rsa_pkcs1_sign( rsa_context *ctx,
msb = mpi_msb( &ctx->N ) - 1;
p += olen - hlen * 2 - 2;
*p++ = 0x01;
- memcpy( p, salt, hlen );
- p += hlen;
+ memcpy( p, salt, slen );
+ p += slen;
// Generate H = Hash( M' )
//
md_starts( &md_ctx );
md_update( &md_ctx, p, 8 );
md_update( &md_ctx, hash, hashlen );
- md_update( &md_ctx, salt, hlen );
+ md_update( &md_ctx, salt, slen );
md_finish( &md_ctx, p );
// Compensate for boundary condition when applying mask
@@ -805,7 +807,7 @@ int rsa_pkcs1_verify( rsa_context *ctx,
unsigned char zeros[8];
const md_info_t *md_info;
md_context_t md_ctx;
- int hlen, msb;
+ int slen, hlen, msb;
#endif
siglen = ctx->len;
@@ -935,6 +937,8 @@ int rsa_pkcs1_verify( rsa_context *ctx,
return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
hlen = md_get_size( md_info );
+ slen = siglen - hlen - 1;
+
memset( &md_ctx, 0, sizeof( md_context_t ) );
memset( zeros, 0, 8 );
@@ -967,15 +971,17 @@ int rsa_pkcs1_verify( rsa_context *ctx,
if( *p++ != 0x01 )
return( POLARSSL_ERR_RSA_INVALID_PADDING );
+ slen -= p - buf;
+
// Generate H = Hash( M' )
//
md_starts( &md_ctx );
md_update( &md_ctx, zeros, 8 );
md_update( &md_ctx, hash, hashlen );
- md_update( &md_ctx, p, hlen );
+ md_update( &md_ctx, p, slen );
md_finish( &md_ctx, p );
- if( memcmp( p, p + hlen, hlen ) == 0 )
+ if( memcmp( p, p + slen, hlen ) == 0 )
return( 0 );
else
return( POLARSSL_ERR_RSA_VERIFY_FAILED );
diff --git a/library/x509parse.c b/library/x509parse.c
index e33074345..df671eff5 100644
--- a/library/x509parse.c
+++ b/library/x509parse.c
@@ -1827,8 +1827,6 @@ int x509parse_key( rsa_context *rsa, const unsigned char *key, int keylen,
#endif
end = p + keylen;
- memset( rsa, 0, sizeof( rsa_context ) );
-
/*
* RSAPrivateKey ::= SEQUENCE {
* version Version,
@@ -1941,6 +1939,116 @@ int x509parse_keyfile( rsa_context *rsa, const char *path, const char *pwd )
return( ret );
}
+/*
+ * Parse a public RSA key
+ */
+int x509parse_public_key( rsa_context *rsa, const unsigned char *key, int keylen )
+{
+ int ret, len;
+ unsigned char *p, *end;
+ x509_buf alg_oid;
+#if defined(POLARSSL_PEM_C)
+ pem_context pem;
+
+ pem_init( &pem );
+ ret = pem_read_buffer( &pem,
+ "-----BEGIN PUBLIC KEY-----",
+ "-----END PUBLIC KEY-----",
+ key, NULL, 0, &len );
+
+ if( ret == 0 )
+ {
+ /*
+ * Was PEM encoded
+ */
+ keylen = pem.buflen;
+ }
+ else if( ret != POLARSSL_ERR_PEM_NO_HEADER_PRESENT )
+ {
+ pem_free( &pem );
+ return( ret );
+ }
+
+ p = ( ret == 0 ) ? pem.buf : (unsigned char *) key;
+#else
+ p = (unsigned char *) key;
+#endif
+ end = p + keylen;
+
+ /*
+ * PublicKeyInfo ::= SEQUENCE {
+ * algorithm AlgorithmIdentifier,
+ * PublicKey BIT STRING
+ * }
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL
+ * }
+ *
+ * RSAPublicKey ::= SEQUENCE {
+ * modulus INTEGER, -- n
+ * publicExponent INTEGER -- e
+ * }
+ */
+
+ if( ( ret = asn1_get_tag( &p, end, &len,
+ ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
+ {
+#if defined(POLARSSL_PEM_C)
+ pem_free( &pem );
+#endif
+ rsa_free( rsa );
+ return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT | ret );
+ }
+
+ if( ( ret = x509_get_pubkey( &p, end, &alg_oid, &rsa->N, &rsa->E ) ) != 0 )
+ {
+#if defined(POLARSSL_PEM_C)
+ pem_free( &pem );
+#endif
+ rsa_free( rsa );
+ return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret );
+ }
+
+ if( ( ret = rsa_check_pubkey( rsa ) ) != 0 )
+ {
+#if defined(POLARSSL_PEM_C)
+ pem_free( &pem );
+#endif
+ rsa_free( rsa );
+ return( ret );
+ }
+
+ rsa->len = mpi_size( &rsa->N );
+
+#if defined(POLARSSL_PEM_C)
+ pem_free( &pem );
+#endif
+
+ return( 0 );
+}
+
+/*
+ * Load and parse a public RSA key
+ */
+int x509parse_public_keyfile( rsa_context *rsa, const char *path )
+{
+ int ret;
+ size_t n;
+ unsigned char *buf;
+
+ if ( load_file( path, &buf, &n ) )
+ return( 1 );
+
+ ret = x509parse_public_key( rsa, buf, (int) n );
+
+ memset( buf, 0, n + 1 );
+ free( buf );
+
+ return( ret );
+}
+
/*
* Parse DHM parameters
*/