Add mbedtls_rsa_validate_crt

This commit adds the function mbedtls_rsa_validate_crt for validating a set of CRT parameters. The function
mbedtls_rsa_check_crt is simplified accordingly.
diff --git a/library/rsa.c b/library/rsa.c
index d0cc9e0..bd72aee 100644
--- a/library/rsa.c
+++ b/library/rsa.c
@@ -305,6 +305,92 @@
 }
 
 /*
+ * Check that RSA CRT parameters are in accordance with core parameters.
+ */
+
+int mbedtls_rsa_validate_crt( const mbedtls_mpi *P,  const mbedtls_mpi *Q,
+                              const mbedtls_mpi *D,  const mbedtls_mpi *DP,
+                              const mbedtls_mpi *DQ, const mbedtls_mpi *QP )
+{
+    int ret = 0;
+
+    mbedtls_mpi K, L;
+    mbedtls_mpi_init( &K );
+    mbedtls_mpi_init( &L );
+
+    /* Check that DP - P == 0 mod P - 1 */
+    if( DP != NULL )
+    {
+        if( P == NULL )
+        {
+            ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+            goto cleanup;
+        }
+
+        MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) );
+        MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &L, DP, D ) );
+        MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &L, &L, &K ) );
+
+        if( mbedtls_mpi_cmp_int( &L, 0 ) != 0 )
+        {
+            return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
+        }
+    }
+
+    /* Check that DQ - Q == 0 mod Q - 1 */
+    if( DQ != NULL )
+    {
+        if( Q == NULL )
+        {
+            ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+            goto cleanup;
+        }
+
+        MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, Q, 1 ) );
+        MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &L, DQ, D ) );
+        MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &L, &L, &K ) );
+
+        if( mbedtls_mpi_cmp_int( &L, 0 ) != 0 )
+        {
+            return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
+        }
+    }
+
+    /* Check that QP * P - 1 == 0 mod P */
+    if( QP != NULL )
+    {
+        if( P == NULL || Q == NULL )
+        {
+            ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+            goto cleanup;
+        }
+
+        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, QP, Q ) );
+        MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) );
+        MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, P ) );
+        if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 )
+        {
+            return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
+        }
+    }
+
+cleanup:
+
+    /* Wrap MPI error codes by RSA check failure error code */
+    if( ret != 0 &&
+        ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED &&
+        ret != MBEDTLS_ERR_RSA_BAD_INPUT_DATA )
+    {
+        ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
+    }
+
+    mbedtls_mpi_free( &K );
+    mbedtls_mpi_free( &L );
+
+    return( ret );
+}
+
+/*
  * Check that core RSA parameters are sane.
  */
 
@@ -621,8 +707,8 @@
  * in order to be able to validate DER encoded RSA keys,
  * which always contain CRT parameters.
  */
-int mbedtls_rsa_check_crt( mbedtls_rsa_context *ctx, mbedtls_mpi *DP,
-                           mbedtls_mpi *DQ, mbedtls_mpi *QP )
+int mbedtls_rsa_check_crt( const mbedtls_rsa_context *ctx,
+                           mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP )
 {
     int ret = 0;
 
@@ -648,61 +734,11 @@
         return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
     }
 #else /* MBEDTLS_RSA_NO_CRT */
-
-    /*
-     * Check that DP, DQ and QP are in accordance with core parameters.
-     * (1) Check that DP - P     == 0 mod P - 1
-     * (2) Check that DQ - Q     == 0 mod Q - 1
-     * (3) Check that QP * P - 1 == 0 mod P
-
-     * Alternative implementation also not using DP, DQ and QP
-     * should be able to reuse this codepath.
-     */
-
-    /* Check (1) */
-    if( DP != NULL )
+    if( ( ret = mbedtls_rsa_validate_crt( &ctx->P, &ctx->Q, &ctx->D,
+                                          DP, DQ, QP ) ) != 0 )
     {
-        /* Temporarily replace P by P-1 and compute DP - D mod P-1 */
-        MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &ctx->P, &ctx->P, 1 ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( DP, DP, &ctx->D ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( DP, DP, &ctx->P ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &ctx->P, &ctx->P, 1 ) );
-
-        if( mbedtls_mpi_cmp_int( DP, 0 ) != 0 )
-        {
-            return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
-        }
+        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
     }
-
-    /* Check (1) */
-    if( DQ != NULL )
-    {
-        /* Temporarily replace Q by Q-1 and compute DQ - D mod Q-1 */
-        MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &ctx->Q, &ctx->Q, 1 ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( DQ, DQ, &ctx->D ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( DQ, DQ, &ctx->Q ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &ctx->Q, &ctx->Q, 1 ) );
-
-        if( mbedtls_mpi_cmp_int( DQ, 0 ) != 0 )
-        {
-            return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
-        }
-    }
-
-    /* Check (3) */
-    if( QP != NULL )
-    {
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( QP, QP, &ctx->Q ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( QP, QP, 1 ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( QP, QP, &ctx->P ) );
-        if( mbedtls_mpi_cmp_int( QP, 0 ) != 0 )
-        {
-            return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
-        }
-    }
-
-cleanup:
-
 #endif
 
     if( ret != 0 )