- Merged changesets 1399 up to and including 1415 into 1.2 branch

diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index 9995859..640cf82 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -57,7 +57,7 @@
 else(NOT USE_SHARED_POLARSSL_LIBRARY)
 
 add_library(polarssl SHARED ${src})
-set_target_properties(polarssl PROPERTIES VERSION 1.2.0 SOVERSION 2)
+set_target_properties(polarssl PROPERTIES VERSION 1.2.1 SOVERSION 2)
 
 endif(NOT USE_SHARED_POLARSSL_LIBRARY)
 
diff --git a/library/Makefile b/library/Makefile
index 7983f7b..603f5d1 100644
--- a/library/Makefile
+++ b/library/Makefile
@@ -18,7 +18,9 @@
 # CFLAGS += -D_BSD_EXTENSION
 
 # To compile as a shared library:
-# CFLAGS += -fPIC
+ifdef SHARED
+CFLAGS += -fPIC
+endif
 
 SONAME=libpolarssl.so.0
 
@@ -51,7 +53,11 @@
 
 .SILENT:
 
+ifndef SHARED
 all: static
+else
+all: shared
+endif
 
 static: libpolarssl.a
 
diff --git a/library/bignum.c b/library/bignum.c
index f2a49ec..23feb6a 100644
--- a/library/bignum.c
+++ b/library/bignum.c
@@ -1195,9 +1195,9 @@
     if( R != NULL )
     {
         mpi_shift_r( &X, k );
+        X.s = A->s;
         mpi_copy( R, &X );
 
-        R->s = A->s;
         if( mpi_cmp_int( R, 0 ) == 0 )
             R->s = 1;
     }
@@ -1212,10 +1212,6 @@
 
 /*
  * Division by int: A = Q * b + R
- *
- * Returns 0 if successful
- *         1 if memory allocation failed
- *         POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0
  */
 int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b )
 {
diff --git a/library/ctr_drbg.c b/library/ctr_drbg.c
index 1de7f05..8cf0371 100644
--- a/library/ctr_drbg.c
+++ b/library/ctr_drbg.c
@@ -194,7 +194,7 @@
         /*
          * Increase counter
          */
-        for( i = CTR_DRBG_BLOCKSIZE; i >= 0; i-- )
+        for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- )
             if( ++ctx->counter[i - 1] != 0 )
                 break;
 
diff --git a/library/error.c b/library/error.c
index a5eaaba..03abc32 100644
--- a/library/error.c
+++ b/library/error.c
@@ -1,7 +1,7 @@
 /*
  *  Error message information
  *
- *  Copyright (C) 2006-2010, Brainspark B.V.
+ *  Copyright (C) 2006-2012, Brainspark B.V.
  *
  *  This file is part of PolarSSL (http://www.polarssl.org)
  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
@@ -553,4 +553,4 @@
     snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", use_ret );
 }
 
-#endif /* POLARSSL_VERBOSE_ERROR */
+#endif /* POLARSSL_ERROR_C */
diff --git a/library/pkcs11.c b/library/pkcs11.c
index b71415a..b68d688 100644
--- a/library/pkcs11.c
+++ b/library/pkcs11.c
@@ -115,7 +115,7 @@
                        int mode, size_t *olen,
                        const unsigned char *input,
                        unsigned char *output,
-                       unsigned int output_max_len )
+                       size_t output_max_len )
 {
     size_t input_len, output_len;
 
diff --git a/library/rsa.c b/library/rsa.c
index 191bfe8..637c23a 100644
--- a/library/rsa.c
+++ b/library/rsa.c
@@ -794,6 +794,9 @@
             hlen = md_get_size( md_info );
             slen = hlen;
 
+            if( olen < hlen + slen + 2 )
+                return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
             memset( sig, 0, olen );
             memset( &md_ctx, 0, sizeof( md_context_t ) );
 
diff --git a/library/x509parse.c b/library/x509parse.c
index d7bfc05..e54e0b7 100644
--- a/library/x509parse.c
+++ b/library/x509parse.c
@@ -2984,8 +2984,6 @@
 
 /*
  * Wrapper for x509 hashes.
- *
- * \param out   Buffer to receive the hash (Should be at least 64 bytes)
  */
 static void x509_hash( const unsigned char *in, size_t len, int alg,
                        unsigned char *out )
@@ -3116,12 +3114,12 @@
 
 static int x509parse_verify_top(
                 x509_cert *child, x509_cert *trust_ca,
-                x509_crl *ca_crl, int *path_cnt, int *flags,
+                x509_crl *ca_crl, int path_cnt, int *flags,
                 int (*f_vrfy)(void *, x509_cert *, int, int *),
                 void *p_vrfy )
 {
     int hash_id, ret;
-    int ca_flags = 0;
+    int ca_flags = 0, check_path_cnt = path_cnt + 1;
     unsigned char hash[64];
 
     if( x509parse_time_expired( &child->valid_to ) )
@@ -3143,8 +3141,19 @@
             continue;
         }
 
+        /*
+         * Reduce path_len to check against if top of the chain is
+         * the same as the trusted CA
+         */
+        if( child->subject_raw.len == trust_ca->subject_raw.len &&
+            memcmp( child->subject_raw.p, trust_ca->subject_raw.p,
+                            child->issuer_raw.len ) == 0 ) 
+        {
+            check_path_cnt--;
+        }
+
         if( trust_ca->max_pathlen > 0 &&
-            trust_ca->max_pathlen < *path_cnt )
+            trust_ca->max_pathlen < check_path_cnt )
         {
             trust_ca = trust_ca->next;
             continue;
@@ -3168,7 +3177,13 @@
         break;
     }
 
-    if( trust_ca != NULL )
+    /*
+     * If top of chain is not the same as the trusted CA
+     */
+    if( trust_ca != NULL &&
+        ( child->subject_raw.len != trust_ca->subject_raw.len ||
+          memcmp( child->subject_raw.p, trust_ca->subject_raw.p,
+                            child->issuer_raw.len ) != 0 ) )
     {
         /* Check trusted CA's CRL for then chain's top crt */
         *flags |= x509parse_verifycrl( child, trust_ca, ca_crl );
@@ -3188,7 +3203,7 @@
 
         if( NULL != f_vrfy )
         {
-            if( ( ret = f_vrfy( p_vrfy, trust_ca, 0, &ca_flags ) ) != 0 )
+            if( ( ret = f_vrfy( p_vrfy, trust_ca, path_cnt + 1, &ca_flags ) ) != 0 )
                 return( ret );
         }
     }
@@ -3196,12 +3211,10 @@
     /* Call callback on top cert */
     if( NULL != f_vrfy )
     {
-        if( ( ret = f_vrfy(p_vrfy, child, 1, flags ) ) != 0 )
+        if( ( ret = f_vrfy(p_vrfy, child, path_cnt, flags ) ) != 0 )
             return( ret );
     }
 
-    *path_cnt = 2;
-
     *flags |= ca_flags;
 
     return( 0 );
@@ -3209,7 +3222,7 @@
 
 static int x509parse_verify_child(
                 x509_cert *child, x509_cert *parent, x509_cert *trust_ca,
-                x509_crl *ca_crl, int *path_cnt, int *flags,
+                x509_crl *ca_crl, int path_cnt, int *flags,
                 int (*f_vrfy)(void *, x509_cert *, int, int *),
                 void *p_vrfy )
 {
@@ -3248,28 +3261,26 @@
         break;
     }
 
-    (*path_cnt)++;
     if( grandparent != NULL )
     {
         /*
          * Part of the chain
          */
-        ret = x509parse_verify_child( parent, grandparent, trust_ca, ca_crl, path_cnt, &parent_flags, f_vrfy, p_vrfy );
+        ret = x509parse_verify_child( parent, grandparent, trust_ca, ca_crl, path_cnt + 1, &parent_flags, f_vrfy, p_vrfy );
         if( ret != 0 )
             return( ret );
     } 
     else
     {
-        ret = x509parse_verify_top( parent, trust_ca, ca_crl, path_cnt, &parent_flags, f_vrfy, p_vrfy );
+        ret = x509parse_verify_top( parent, trust_ca, ca_crl, path_cnt + 1, &parent_flags, f_vrfy, p_vrfy );
         if( ret != 0 )
             return( ret );
     }
 
     /* child is verified to be a child of the parent, call verify callback */
     if( NULL != f_vrfy )
-        if( ( ret = f_vrfy( p_vrfy, child, *path_cnt, flags ) ) != 0 )
+        if( ( ret = f_vrfy( p_vrfy, child, path_cnt, flags ) ) != 0 )
             return( ret );
-    (*path_cnt)++;
 
     *flags |= parent_flags;
 
@@ -3288,7 +3299,7 @@
 {
     size_t cn_len;
     int ret;
-    int pathlen = 1;
+    int pathlen = 0;
     x509_cert *parent;
     x509_name *name;
     x509_sequence *cur = NULL;
@@ -3370,13 +3381,13 @@
         /*
          * Part of the chain
          */
-        ret = x509parse_verify_child( crt, parent, trust_ca, ca_crl, &pathlen, flags, f_vrfy, p_vrfy );
+        ret = x509parse_verify_child( crt, parent, trust_ca, ca_crl, pathlen, flags, f_vrfy, p_vrfy );
         if( ret != 0 )
             return( ret );
     } 
     else
     {
-        ret = x509parse_verify_top( crt, trust_ca, ca_crl, &pathlen, flags, f_vrfy, p_vrfy );
+        ret = x509parse_verify_top( crt, trust_ca, ca_crl, pathlen, flags, f_vrfy, p_vrfy );
         if( ret != 0 )
             return( ret );
     }
diff --git a/library/x509write.c b/library/x509write.c
index 400ffa0..9f5a910 100644
--- a/library/x509write.c
+++ b/library/x509write.c
@@ -146,8 +146,6 @@
 
 /*
  * Wrapper for x509 hashes.
- *
- * \param out   Buffer to receive the hash (Should be at least 64 bytes)
  */
 static void x509_hash( const unsigned char *in, size_t len, int alg,
                        unsigned char *out )