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 )