Merge verification of the keyUsage extension in X.509 certificates
diff --git a/ChangeLog b/ChangeLog
index 36532ba..23e59dc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -6,9 +6,12 @@
Features
* Support for the ALPN SSL extension
+ * Add option 'use_dev_random' to gen_key application
Changes
* x509_crt_info() now prints information about parsed extensions as well
+ * pk_verify() now returns a specific error code when the signature is valid
+ but shorter than the supplied length.
Security
* Avoid potential timing leak in ecdsa_sign() by blinding modular division.
diff --git a/include/polarssl/ecdsa.h b/include/polarssl/ecdsa.h
index b5e363e..4f06328 100644
--- a/include/polarssl/ecdsa.h
+++ b/include/polarssl/ecdsa.h
@@ -175,7 +175,9 @@
* \param slen Size of sig
*
* \return 0 if successful,
- * POLARSSL_ERR_ECP_BAD_INPUT_DATA if signature is invalid
+ * POLARSSL_ERR_ECP_BAD_INPUT_DATA if signature is invalid,
+ * POLARSSL_ERR_ECP_SIG_LEN_MISTMATCH if the signature is
+ * valid but its actual length is less than siglen,
* or a POLARSSL_ERR_ECP or POLARSSL_ERR_MPI error code
*/
int ecdsa_read_signature( ecdsa_context *ctx,
diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h
index 3942891..93fbe3d 100644
--- a/include/polarssl/ecp.h
+++ b/include/polarssl/ecp.h
@@ -39,6 +39,7 @@
#define POLARSSL_ERR_ECP_MALLOC_FAILED -0x4D80 /**< Memory allocation failed. */
#define POLARSSL_ERR_ECP_RANDOM_FAILED -0x4D00 /**< Generation of random value, such as (ephemeral) key, failed. */
#define POLARSSL_ERR_ECP_INVALID_KEY -0x4C80 /**< Invalid private or public key. */
+#define POLARSSL_ERR_ECP_SIG_LEN_MISMATCH -0x4C00 /**< Signature is valid but shorter than the user-supplied length. */
#ifdef __cplusplus
extern "C" {
@@ -122,7 +123,7 @@
* prime. (Use odd in ecp_mul() and prime in ecdsa_sign() for blinding.)
*
* In the case of Montgomery curves, we don't store A but (A + 2) / 4 which is
- * the quantity actualy used in the formulas. Also, nbits is not the size of N
+ * the quantity actually used in the formulas. Also, nbits is not the size of N
* but the required size for private keys.
*
* If modp is NULL, reduction modulo P is done using a generic algorithm.
@@ -542,7 +543,7 @@
*
* \note If f_rng is not NULL, it is used to randomize intermediate
* results in order to prevent potential timing attacks
- * targetting these results. It is recommended to always
+ * targeting these results. It is recommended to always
* provide a non-NULL f_rng (the overhead is negligible).
*/
int ecp_mul( ecp_group *grp, ecp_point *R,
diff --git a/include/polarssl/error.h b/include/polarssl/error.h
index 23c0ed7..d27b0e5 100644
--- a/include/polarssl/error.h
+++ b/include/polarssl/error.h
@@ -83,11 +83,11 @@
* PEM 1 9
* PKCS#12 1 4 (Started from top)
* X509 2 18
- * PK 2 13 (Started from top)
+ * PK 2 14 (Started from top, plus 0x2000)
* DHM 3 9
* PKCS5 3 4 (Started from top)
* RSA 4 9
- * ECP 4 7 (Started from top)
+ * ECP 4 8 (Started from top)
* MD 5 4
* CIPHER 6 6
* SSL 6 9 (Started from top)
diff --git a/include/polarssl/oid.h b/include/polarssl/oid.h
index 0c471c5..ade4683 100644
--- a/include/polarssl/oid.h
+++ b/include/polarssl/oid.h
@@ -326,7 +326,7 @@
#define OID_ANSI_X9_62_PRIME_FIELD OID_ANSI_X9_62_FIELD_TYPE "\x01"
/*
- * ECDSA signature identifers, from RFC 5480
+ * ECDSA signature identifiers, from RFC 5480
*/
#define OID_ANSI_X9_62_SIG OID_ANSI_X9_62 "\x04" /* signatures(4) */
#define OID_ANSI_X9_62_SIG_SHA2 OID_ANSI_X9_62_SIG "\x03" /* ecdsa-with-SHA2(3) */
diff --git a/include/polarssl/pk.h b/include/polarssl/pk.h
index b764d55..cebe057 100644
--- a/include/polarssl/pk.h
+++ b/include/polarssl/pk.h
@@ -57,6 +57,7 @@
#define POLARSSL_ERR_PK_INVALID_ALG -0x2A80 /**< The algorithm tag or value is invalid. */
#define POLARSSL_ERR_PK_UNKNOWN_NAMED_CURVE -0x2A00 /**< Elliptic curve is unsupported (only NIST curves are supported). */
#define POLARSSL_ERR_PK_FEATURE_UNAVAILABLE -0x2980 /**< Unavailable feature, e.g. RSA disabled for RSA key. */
+#define POLARSSL_ERR_PK_SIG_LEN_MISMATCH -0x2000 /**< The signature is valid but its length is less than expected. */
#if defined(POLARSSL_RSA_C)
@@ -288,6 +289,8 @@
* \param sig_len Signature length
*
* \return 0 on success (signature is valid),
+ * POLARSSL_ERR_PK_SIG_LEN_MISMATCH if the signature is
+ * valid but its actual length is less than sig_len,
* or a specific error code.
*
* \note If hash_len is 0, then the length associated with md_alg
diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h
index 82cdb53..cb32805 100644
--- a/include/polarssl/ssl.h
+++ b/include/polarssl/ssl.h
@@ -137,7 +137,7 @@
#define POLARSSL_ERR_SSL_BAD_HS_NEW_SESSION_TICKET -0x6E00 /**< Processing of the NewSessionTicket handshake message failed. */
#define POLARSSL_ERR_SSL_SESSION_TICKET_EXPIRED -0x6D80 /**< Session ticket has expired. */
#define POLARSSL_ERR_SSL_PK_TYPE_MISMATCH -0x6D00 /**< Public key type mismatch (eg, asked for RSA key exchange and presented EC key) */
-#define POLARSSL_ERR_SSL_UNKNOWN_IDENTITY -0x6C80 /**< Unkown identity received (eg, PSK identity) */
+#define POLARSSL_ERR_SSL_UNKNOWN_IDENTITY -0x6C80 /**< Unknown identity received (eg, PSK identity) */
#define POLARSSL_ERR_SSL_INTERNAL_ERROR -0x6C00 /**< Internal error (eg, unexpected failure in lower-level module) */
#define POLARSSL_ERR_SSL_COUNTER_WRAPPING -0x6B80 /**< A counter would wrap (eg, too many messages exchanged). */
diff --git a/include/polarssl/x509.h b/include/polarssl/x509.h
index 003154b..f2b8a0c 100644
--- a/include/polarssl/x509.h
+++ b/include/polarssl/x509.h
@@ -230,7 +230,7 @@
* \param size Maximum size of buffer
* \param oid Buffer containing the OID
*
- * \return Length of the string written (exluding final NULL) or
+ * \return Length of the string written (excluding final NULL) or
* POLARSSL_ERR_OID_BUF_TO_SMALL in case of error
*/
int x509_oid_get_numeric_string( char *buf, size_t size, x509_buf *oid );
diff --git a/library/ecdsa.c b/library/ecdsa.c
index c9ab62f..6e45f2f 100644
--- a/library/ecdsa.c
+++ b/library/ecdsa.c
@@ -422,11 +422,14 @@
( ret = asn1_get_mpi( &p, end, &ctx->s ) ) != 0 )
return( POLARSSL_ERR_ECP_BAD_INPUT_DATA + ret );
- if( p != end )
- return( POLARSSL_ERR_ECP_BAD_INPUT_DATA +
- POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
+ if( ( ret = ecdsa_verify( &ctx->grp, hash, hlen,
+ &ctx->Q, &ctx->r, &ctx->s ) ) != 0 )
+ return( ret );
- return( ecdsa_verify( &ctx->grp, hash, hlen, &ctx->Q, &ctx->r, &ctx->s ) );
+ if( p != end )
+ return( POLARSSL_ERR_ECP_SIG_LEN_MISMATCH );
+
+ return( 0 );
}
/*
diff --git a/library/entropy.c b/library/entropy.c
index 9828926..d62fecf 100644
--- a/library/entropy.c
+++ b/library/entropy.c
@@ -211,21 +211,21 @@
*/
int entropy_gather( entropy_context *ctx )
{
- int ret;
+ int ret;
#if defined(POLARSSL_THREADING_C)
- if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 )
- return( ret );
+ if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 )
+ return( ret );
#endif
- ret = entropy_gather_internal( ctx );
+ ret = entropy_gather_internal( ctx );
#if defined(POLARSSL_THREADING_C)
- if( polarssl_mutex_unlock( &ctx->mutex ) != 0 )
- return( POLARSSL_ERR_THREADING_MUTEX_ERROR );
+ if( polarssl_mutex_unlock( &ctx->mutex ) != 0 )
+ return( POLARSSL_ERR_THREADING_MUTEX_ERROR );
#endif
- return ( ret );
+ return( ret );
}
int entropy_func( void *data, unsigned char *output, size_t len )
diff --git a/library/error.c b/library/error.c
index 2ca755c..b2e8346 100644
--- a/library/error.c
+++ b/library/error.c
@@ -245,6 +245,8 @@
snprintf( buf, buflen, "ECP - Generation of random value, such as (ephemeral) key, failed" );
if( use_ret == -(POLARSSL_ERR_ECP_INVALID_KEY) )
snprintf( buf, buflen, "ECP - Invalid private or public key" );
+ if( use_ret == -(POLARSSL_ERR_ECP_SIG_LEN_MISMATCH) )
+ snprintf( buf, buflen, "ECP - Signature is valid but shorter than the user-supplied length" );
#endif /* POLARSSL_ECP_C */
#if defined(POLARSSL_MD_C)
@@ -306,6 +308,8 @@
snprintf( buf, buflen, "PK - Elliptic curve is unsupported (only NIST curves are supported)" );
if( use_ret == -(POLARSSL_ERR_PK_FEATURE_UNAVAILABLE) )
snprintf( buf, buflen, "PK - Unavailable feature, e.g. RSA disabled for RSA key" );
+ if( use_ret == -(POLARSSL_ERR_PK_SIG_LEN_MISMATCH) )
+ snprintf( buf, buflen, "PK - The signature is valid but its length is less than expected" );
#endif /* POLARSSL_PK_C */
#if defined(POLARSSL_PKCS12_C)
@@ -430,7 +434,7 @@
if( use_ret == -(POLARSSL_ERR_SSL_PK_TYPE_MISMATCH) )
snprintf( buf, buflen, "SSL - Public key type mismatch (eg, asked for RSA key exchange and presented EC key)" );
if( use_ret == -(POLARSSL_ERR_SSL_UNKNOWN_IDENTITY) )
- snprintf( buf, buflen, "SSL - Unkown identity received (eg, PSK identity)" );
+ snprintf( buf, buflen, "SSL - Unknown identity received (eg, PSK identity)" );
if( use_ret == -(POLARSSL_ERR_SSL_INTERNAL_ERROR) )
snprintf( buf, buflen, "SSL - Internal error (eg, unexpected failure in lower-level module)" );
if( use_ret == -(POLARSSL_ERR_SSL_COUNTER_WRAPPING) )
diff --git a/library/pk.c b/library/pk.c
index cfde265..25c9d85 100644
--- a/library/pk.c
+++ b/library/pk.c
@@ -86,7 +86,7 @@
case POLARSSL_PK_ECDSA:
return &ecdsa_info;
#endif
- /* POLARSSL_PK_RSA_ALT ommited on purpose */
+ /* POLARSSL_PK_RSA_ALT omitted on purpose */
default:
return NULL;
}
diff --git a/library/pk_wrap.c b/library/pk_wrap.c
index 96695d4..2a4da03 100644
--- a/library/pk_wrap.c
+++ b/library/pk_wrap.c
@@ -64,11 +64,20 @@
const unsigned char *hash, size_t hash_len,
const unsigned char *sig, size_t sig_len )
{
- if( sig_len != ((rsa_context *) ctx)->len )
+ int ret;
+
+ if( sig_len < ((rsa_context *) ctx)->len )
return( POLARSSL_ERR_RSA_VERIFY_FAILED );
- return( rsa_pkcs1_verify( (rsa_context *) ctx, NULL, NULL,
- RSA_PUBLIC, md_alg, (unsigned int) hash_len, hash, sig ) );
+ if( ( ret = rsa_pkcs1_verify( (rsa_context *) ctx, NULL, NULL,
+ RSA_PUBLIC, md_alg,
+ (unsigned int) hash_len, hash, sig ) ) != 0 )
+ return( ret );
+
+ if( sig_len > ((rsa_context *) ctx)->len )
+ return( POLARSSL_ERR_PK_SIG_LEN_MISMATCH );
+
+ return( 0 );
}
static int rsa_sign_wrap( void *ctx, md_type_t md_alg,
@@ -259,7 +268,7 @@
};
/*
- * EC key resticted to ECDH
+ * EC key restricted to ECDH
*/
static int eckeydh_can_do( pk_type_t type )
{
@@ -292,10 +301,16 @@
const unsigned char *hash, size_t hash_len,
const unsigned char *sig, size_t sig_len )
{
+ int ret;
((void) md_alg);
- return( ecdsa_read_signature( (ecdsa_context *) ctx,
- hash, hash_len, sig, sig_len ) );
+ ret = ecdsa_read_signature( (ecdsa_context *) ctx,
+ hash, hash_len, sig, sig_len );
+
+ if( ret == POLARSSL_ERR_ECP_SIG_LEN_MISMATCH )
+ return( POLARSSL_ERR_PK_SIG_LEN_MISMATCH );
+
+ return( ret );
}
static int ecdsa_sign_wrap( void *ctx, md_type_t md_alg,
diff --git a/programs/pkey/gen_key.c b/programs/pkey/gen_key.c
index 2a33257..9f060b7 100644
--- a/programs/pkey/gen_key.c
+++ b/programs/pkey/gen_key.c
@@ -29,6 +29,10 @@
#include <stdlib.h>
#include <stdio.h>
+#if !defined(_WIN32) && defined(POLARSSL_FS_IO)
+#include <unistd.h>
+#endif /* !_WIN32 && POLARSSL_FS_IO */
+
#include "polarssl/error.h"
#include "polarssl/pk.h"
#include "polarssl/ecdsa.h"
@@ -59,6 +63,7 @@
#define DFL_EC_CURVE ecp_curve_list()->grp_id
#define DFL_FILENAME "keyfile.key"
#define DFL_FORMAT FORMAT_PEM
+#define DFL_USE_DEV_RANDOM 0
/*
* global options
@@ -70,8 +75,48 @@
int ec_curve; /* curve identifier for EC keys */
const char *filename; /* filename of the key file */
int format; /* the output format to use */
+ int use_dev_random; /* use /dev/random as entropy source */
} opt;
+#if !defined(_WIN32) && defined(POLARSSL_FS_IO)
+
+#define DEV_RANDOM_THRESHOLD 32
+
+int dev_random_entropy_poll( void *data, unsigned char *output,
+ size_t len, size_t *olen )
+{
+ FILE *file;
+ size_t ret, left = len;
+ unsigned char *p = output;
+ ((void) data);
+
+ *olen = 0;
+
+ file = fopen( "/dev/random", "rb" );
+ if( file == NULL )
+ return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED );
+
+ while( left > 0 )
+ {
+ /* /dev/random can return much less than requested. If so, try again */
+ ret = fread( p, 1, left, file );
+ if( ret == 0 && ferror( file ) )
+ {
+ fclose( file );
+ return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED );
+ }
+
+ p += ret;
+ left -= ret;
+ sleep( 1 );
+ }
+ fclose( file );
+ *olen = len;
+
+ return( 0 );
+}
+#endif /* !_WIN32 && POLARSSL_FS_IO */
+
static int write_private_key( pk_context *key, const char *output_file )
{
int ret;
@@ -108,6 +153,13 @@
return( 0 );
}
+#if !defined(_WIN32) && defined(POLARSSL_FS_IO)
+#define USAGE_DEV_RANDOM \
+ " use_dev_random=0|1 default: 0\n"
+#else
+#define USAGE_DEV_RANDOM ""
+#endif /* !_WIN32 && POLARSSL_FS_IO */
+
#define USAGE \
"\n usage: gen_key param=<>...\n" \
"\n acceptable parameters:\n" \
@@ -116,6 +168,7 @@
" ec_curve=%%s see below\n" \
" filename=%%s default: keyfile.key\n" \
" format=pem|der default: pem\n" \
+ USAGE_DEV_RANDOM \
"\n"
int main( int argc, char *argv[] )
@@ -158,6 +211,7 @@
opt.ec_curve = DFL_EC_CURVE;
opt.filename = DFL_FILENAME;
opt.format = DFL_FORMAT;
+ opt.use_dev_random = DFL_USE_DEV_RANDOM;
for( i = 1; i < argc; i++ )
{
@@ -198,6 +252,12 @@
}
else if( strcmp( p, "filename" ) == 0 )
opt.filename = q;
+ else if( strcmp( p, "use_dev_random" ) == 0 )
+ {
+ opt.use_dev_random = atoi( q );
+ if( opt.use_dev_random < 0 || opt.use_dev_random > 1 )
+ goto usage;
+ }
else
goto usage;
}
@@ -206,6 +266,21 @@
fflush( stdout );
entropy_init( &entropy );
+#if !defined(_WIN32) && defined(POLARSSL_FS_IO)
+ if( opt.use_dev_random )
+ {
+ if( ( ret = entropy_add_source( &entropy, dev_random_entropy_poll,
+ NULL, DEV_RANDOM_THRESHOLD ) ) != 0 )
+ {
+ printf( " failed\n ! entropy_add_source returned -0x%04x\n", -ret );
+ goto exit;
+ }
+
+ printf("\n Using /dev/random, so can take a long time! " );
+ fflush( stdout );
+ }
+#endif /* !_WIN32 && POLARSSL_FS_IO */
+
if( ( ret = ctr_drbg_init( &ctr_drbg, entropy_func, &entropy,
(const unsigned char *) pers,
strlen( pers ) ) ) != 0 )