NativeCrypto: add tests for DSA and RSA keys

Change-Id: I75c924fe67e24948ba26640e99fcc1748671ddf5
diff --git a/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp b/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp
index c0abdf7..f9e7cc9 100644
--- a/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp
+++ b/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp
@@ -1202,9 +1202,14 @@
     EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
     JNI_TRACE("get_RSA_public_params(%p)", pkey);
 
+    if (pkey == NULL) {
+        jniThrowNullPointerException(env, "pkey == null");
+        return 0;
+    }
+
     Unique_RSA rsa(EVP_PKEY_get1_RSA(pkey));
     if (rsa.get() == NULL) {
-        jniThrowRuntimeException(env, "get_RSA_public_params failed");
+        throwExceptionIfNecessary(env, "get_RSA_public_params failed");
         return 0;
     }
 
@@ -1235,9 +1240,14 @@
     EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
     JNI_TRACE("get_RSA_public_params(%p)", pkey);
 
+    if (pkey == NULL) {
+        jniThrowNullPointerException(env, "pkey == null");
+        return 0;
+    }
+
     Unique_RSA rsa(EVP_PKEY_get1_RSA(pkey));
     if (rsa.get() == NULL) {
-        jniThrowRuntimeException(env, "get_RSA_public_params failed");
+        throwExceptionIfNecessary(env, "get_RSA_public_params failed");
         return 0;
     }
 
@@ -1337,6 +1347,7 @@
     if (dsa.get() == NULL) {
         JNI_TRACE("DSA_generate_key failed");
         jniThrowOutOfMemoryError(env, "Unable to allocate DSA key");
+        freeOpenSslErrorState();
         return 0;
     }
 
@@ -1374,12 +1385,13 @@
     if (pkey.get() == NULL) {
         JNI_TRACE("DSA_generate_key failed");
         jniThrowRuntimeException(env, "NativeCrypto_DSA_generate_key failed");
+        freeOpenSslErrorState();
         return 0;
     }
 
     if (EVP_PKEY_assign_DSA(pkey.get(), dsa.get()) != 1) {
         JNI_TRACE("DSA_generate_key failed");
-        jniThrowRuntimeException(env, "NativeCrypto_DSA_generate_key failed");
+        throwExceptionIfNecessary(env, "NativeCrypto_DSA_generate_key failed");
         return 0;
     }
 
@@ -1397,7 +1409,7 @@
 
     Unique_DSA dsa(EVP_PKEY_get1_DSA(pkey));
     if (dsa.get() == NULL) {
-        jniThrowRuntimeException(env, "get_DSA_params failed");
+        throwExceptionIfNecessary(env, "get_DSA_params failed");
         return 0;
     }
 
@@ -1470,7 +1482,7 @@
     JNI_TRACE("NativeCrypto_EVP_MD_CTX_copy(%p)", ctx);
 
     if (ctx == NULL) {
-        jniThrowNullPointerException(env, NULL);
+        jniThrowNullPointerException(env, "ctx == null");
         return 0;
     }
 
@@ -1485,6 +1497,7 @@
     if (result == 0) {
         EVP_MD_CTX_destroy(copy);
         jniThrowRuntimeException(env, "Unable to copy EVP_MD_CTX");
+        freeOpenSslErrorState();
         return 0;
     }
 
@@ -1501,7 +1514,7 @@
     JNI_TRACE("NativeCrypto_EVP_DigestFinal(%p, %p, %d)", ctx, hash, offset);
 
     if (ctx == NULL || hash == NULL) {
-        jniThrowNullPointerException(env, NULL);
+        jniThrowNullPointerException(env, "ctx == null || hash == null");
         return -1;
     }
 
diff --git a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/NativeCryptoTest.java b/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/NativeCryptoTest.java
index 8f52af6..b7dea79 100644
--- a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/NativeCryptoTest.java
+++ b/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/NativeCryptoTest.java
@@ -1764,6 +1764,210 @@
         }
     }
 
+    public void test_get_RSA_private_params() throws Exception {
+        try {
+            NativeCrypto.get_RSA_private_params(NULL);
+        } catch (NullPointerException expected) {
+        }
+
+        try {
+            NativeCrypto.get_RSA_private_params(NULL);
+        } catch (NullPointerException expected) {
+        }
+
+        // Test getting params for the wrong kind of key.
+        final byte[] seed = new byte[20];
+        int ctx = 0;
+        try {
+            ctx = NativeCrypto.DSA_generate_key(2048, seed, dsa2048_g, dsa2048_p, dsa2048_q);
+            assertTrue(ctx != NULL);
+            try {
+                NativeCrypto.get_RSA_private_params(ctx);
+                fail();
+            } catch (RuntimeException expected) {
+            }
+        } finally {
+            if (ctx != 0) {
+                NativeCrypto.EVP_PKEY_free(ctx);
+            }
+        }
+    }
+
+    public void test_get_RSA_public_params() throws Exception {
+        try {
+            NativeCrypto.get_RSA_public_params(NULL);
+        } catch (NullPointerException expected) {
+        }
+
+        try {
+            NativeCrypto.get_RSA_public_params(NULL);
+        } catch (NullPointerException expected) {
+        }
+
+        // Test getting params for the wrong kind of key.
+        final byte[] seed = new byte[20];
+        int ctx = 0;
+        try {
+            ctx = NativeCrypto.DSA_generate_key(2048, seed, dsa2048_g, dsa2048_p, dsa2048_q);
+            assertTrue(ctx != NULL);
+            try {
+                NativeCrypto.get_RSA_public_params(ctx);
+                fail();
+            } catch (RuntimeException expected) {
+            }
+        } finally {
+            if (ctx != 0) {
+                NativeCrypto.EVP_PKEY_free(ctx);
+            }
+        }
+    }
+
+    final byte[] dsa2048_p = {
+            (byte) 0xC3, (byte) 0x16, (byte) 0xD4, (byte) 0xBA, (byte) 0xDC, (byte) 0x0E,
+            (byte) 0xB8, (byte) 0xFC, (byte) 0x40, (byte) 0xDB, (byte) 0xB0, (byte) 0x76,
+            (byte) 0x47, (byte) 0xB8, (byte) 0x8D, (byte) 0xC1, (byte) 0xF1, (byte) 0xAB,
+            (byte) 0x9B, (byte) 0x80, (byte) 0x9D, (byte) 0xDC, (byte) 0x55, (byte) 0x33,
+            (byte) 0xEC, (byte) 0xB6, (byte) 0x09, (byte) 0x8F, (byte) 0xB7, (byte) 0xD9,
+            (byte) 0xA5, (byte) 0x7F, (byte) 0xC1, (byte) 0xE3, (byte) 0xAD, (byte) 0xE1,
+            (byte) 0x7A, (byte) 0x58, (byte) 0xF4, (byte) 0x2D, (byte) 0xB9, (byte) 0x61,
+            (byte) 0xCF, (byte) 0x5B, (byte) 0xCA, (byte) 0x41, (byte) 0x9F, (byte) 0x73,
+            (byte) 0x8D, (byte) 0x81, (byte) 0x62, (byte) 0xD2, (byte) 0x19, (byte) 0x7D,
+            (byte) 0x18, (byte) 0xDB, (byte) 0xB3, (byte) 0x04, (byte) 0xE7, (byte) 0xB2,
+            (byte) 0x28, (byte) 0x59, (byte) 0x14, (byte) 0x73, (byte) 0x43, (byte) 0xF1,
+            (byte) 0x45, (byte) 0xC7, (byte) 0x47, (byte) 0xCC, (byte) 0xD1, (byte) 0x12,
+            (byte) 0x8E, (byte) 0x19, (byte) 0x00, (byte) 0x2C, (byte) 0xD0, (byte) 0x86,
+            (byte) 0x54, (byte) 0x64, (byte) 0x2D, (byte) 0x42, (byte) 0x6C, (byte) 0x6B,
+            (byte) 0x5C, (byte) 0x2D, (byte) 0x4D, (byte) 0x97, (byte) 0x6A, (byte) 0x1D,
+            (byte) 0x89, (byte) 0xB1, (byte) 0x2C, (byte) 0xA0, (byte) 0x05, (byte) 0x2B,
+            (byte) 0x3C, (byte) 0xDB, (byte) 0x1F, (byte) 0x89, (byte) 0x03, (byte) 0x03,
+            (byte) 0x92, (byte) 0x63, (byte) 0xB6, (byte) 0x08, (byte) 0x32, (byte) 0x50,
+            (byte) 0xB2, (byte) 0x54, (byte) 0xA3, (byte) 0xFE, (byte) 0x6C, (byte) 0x35,
+            (byte) 0x17, (byte) 0x2F, (byte) 0x7F, (byte) 0x54, (byte) 0xA4, (byte) 0xAE,
+            (byte) 0x96, (byte) 0x1E, (byte) 0x31, (byte) 0x83, (byte) 0xF1, (byte) 0x3F,
+            (byte) 0x9E, (byte) 0xB9, (byte) 0x5D, (byte) 0xD3, (byte) 0xA9, (byte) 0xCB,
+            (byte) 0xE5, (byte) 0x2F, (byte) 0xBC, (byte) 0xA4, (byte) 0x1A, (byte) 0x31,
+            (byte) 0x41, (byte) 0x91, (byte) 0x2C, (byte) 0xA0, (byte) 0xF4, (byte) 0x83,
+            (byte) 0xAC, (byte) 0xD5, (byte) 0xBA, (byte) 0x3D, (byte) 0x19, (byte) 0xED,
+            (byte) 0xF1, (byte) 0x6C, (byte) 0xD9, (byte) 0x3F, (byte) 0x30, (byte) 0xDA,
+            (byte) 0x80, (byte) 0x06, (byte) 0x56, (byte) 0x3A, (byte) 0x8C, (byte) 0x74,
+            (byte) 0x63, (byte) 0xF2, (byte) 0xED, (byte) 0x1E, (byte) 0xE3, (byte) 0x86,
+            (byte) 0x95, (byte) 0x64, (byte) 0x2A, (byte) 0xC4, (byte) 0x5F, (byte) 0xB2,
+            (byte) 0x64, (byte) 0x40, (byte) 0x9D, (byte) 0xA6, (byte) 0xB8, (byte) 0xF5,
+            (byte) 0x84, (byte) 0x03, (byte) 0x2E, (byte) 0x4A, (byte) 0x7A, (byte) 0x1A,
+            (byte) 0xB0, (byte) 0x0E, (byte) 0xBA, (byte) 0xB1, (byte) 0xF5, (byte) 0xD2,
+            (byte) 0xE7, (byte) 0x65, (byte) 0xCE, (byte) 0xEE, (byte) 0x2C, (byte) 0x7C,
+            (byte) 0x68, (byte) 0x20, (byte) 0x50, (byte) 0x53, (byte) 0x0F, (byte) 0x60,
+            (byte) 0x92, (byte) 0x81, (byte) 0xC0, (byte) 0x2C, (byte) 0x2A, (byte) 0xEA,
+            (byte) 0xE9, (byte) 0xB3, (byte) 0x2A, (byte) 0x81, (byte) 0xDA, (byte) 0x0F,
+            (byte) 0xBB, (byte) 0xFA, (byte) 0x5B, (byte) 0x47, (byte) 0xDA, (byte) 0x57,
+            (byte) 0x4E, (byte) 0xFC, (byte) 0x05, (byte) 0x2C, (byte) 0x6A, (byte) 0x90,
+            (byte) 0xA0, (byte) 0x99, (byte) 0x88, (byte) 0x71, (byte) 0x8A, (byte) 0xCC,
+            (byte) 0xD2, (byte) 0x97, (byte) 0x11, (byte) 0xB1, (byte) 0xCE, (byte) 0xF7,
+            (byte) 0x47, (byte) 0x53, (byte) 0x53, (byte) 0x68, (byte) 0xE1, (byte) 0x2A,
+            (byte) 0x56, (byte) 0xD5, (byte) 0x3D, (byte) 0xDF, (byte) 0x08, (byte) 0x16,
+            (byte) 0x1F, (byte) 0xAA, (byte) 0x54, (byte) 0x15,
+    };
+
+    final byte[] dsa2048_q = {
+            (byte) 0xAA, (byte) 0xDD, (byte) 0xE2, (byte) 0xCE, (byte) 0x08, (byte) 0xC0,
+            (byte) 0x0E, (byte) 0x91, (byte) 0x8C, (byte) 0xD9, (byte) 0xBC, (byte) 0x1E,
+            (byte) 0x05, (byte) 0x70, (byte) 0x07, (byte) 0x3B, (byte) 0xB5, (byte) 0xA9,
+            (byte) 0xB5, (byte) 0x8B, (byte) 0x21, (byte) 0x68, (byte) 0xA2, (byte) 0x76,
+            (byte) 0x53, (byte) 0x1E, (byte) 0x68, (byte) 0x1B, (byte) 0x4F, (byte) 0x88,
+            (byte) 0x6D, (byte) 0xCF,
+    };
+
+    final byte[] dsa2048_g = {
+            (byte) 0x6B, (byte) 0x4D, (byte) 0x21, (byte) 0x92, (byte) 0x24, (byte) 0x76,
+            (byte) 0xE5, (byte) 0xA2, (byte) 0xCE, (byte) 0x02, (byte) 0x85, (byte) 0x32,
+            (byte) 0x73, (byte) 0x70, (byte) 0xFF, (byte) 0xB9, (byte) 0xD4, (byte) 0x51,
+            (byte) 0xBA, (byte) 0x22, (byte) 0x8B, (byte) 0x75, (byte) 0x29, (byte) 0xE3,
+            (byte) 0xF2, (byte) 0x2E, (byte) 0x20, (byte) 0xF5, (byte) 0x6A, (byte) 0xD9,
+            (byte) 0x75, (byte) 0xA0, (byte) 0xC0, (byte) 0x3B, (byte) 0x12, (byte) 0x2F,
+            (byte) 0x4F, (byte) 0x9A, (byte) 0xF8, (byte) 0x5D, (byte) 0x45, (byte) 0xC5,
+            (byte) 0x80, (byte) 0x6C, (byte) 0x9B, (byte) 0x56, (byte) 0xBE, (byte) 0x8E,
+            (byte) 0x40, (byte) 0xF9, (byte) 0x0A, (byte) 0xF0, (byte) 0x3D, (byte) 0xD7,
+            (byte) 0x7C, (byte) 0xDE, (byte) 0x22, (byte) 0x10, (byte) 0x24, (byte) 0xCC,
+            (byte) 0xAE, (byte) 0x8A, (byte) 0xC0, (byte) 0x05, (byte) 0xCD, (byte) 0xDC,
+            (byte) 0x10, (byte) 0x29, (byte) 0x4D, (byte) 0xFC, (byte) 0xEC, (byte) 0xEF,
+            (byte) 0x51, (byte) 0x4B, (byte) 0xF9, (byte) 0xCC, (byte) 0x99, (byte) 0x84,
+            (byte) 0x1B, (byte) 0x14, (byte) 0x68, (byte) 0xEC, (byte) 0xF0, (byte) 0x5E,
+            (byte) 0x07, (byte) 0x10, (byte) 0x09, (byte) 0xA9, (byte) 0x2C, (byte) 0x04,
+            (byte) 0xD0, (byte) 0x14, (byte) 0xBF, (byte) 0x88, (byte) 0x9E, (byte) 0xBB,
+            (byte) 0xE3, (byte) 0x3F, (byte) 0xDE, (byte) 0x92, (byte) 0xE1, (byte) 0x64,
+            (byte) 0x07, (byte) 0x28, (byte) 0xC1, (byte) 0xCA, (byte) 0x48, (byte) 0xC1,
+            (byte) 0x1D, (byte) 0x33, (byte) 0xE4, (byte) 0x35, (byte) 0xBE, (byte) 0xDF,
+            (byte) 0x5E, (byte) 0x50, (byte) 0xF9, (byte) 0xC2, (byte) 0x0E, (byte) 0x25,
+            (byte) 0x0D, (byte) 0x20, (byte) 0x8C, (byte) 0x01, (byte) 0x0A, (byte) 0x23,
+            (byte) 0xD4, (byte) 0x6E, (byte) 0x42, (byte) 0x47, (byte) 0xE1, (byte) 0x9E,
+            (byte) 0x36, (byte) 0x91, (byte) 0xC8, (byte) 0x65, (byte) 0x44, (byte) 0xE0,
+            (byte) 0x04, (byte) 0x86, (byte) 0x2F, (byte) 0xD4, (byte) 0x90, (byte) 0x16,
+            (byte) 0x09, (byte) 0x14, (byte) 0xB1, (byte) 0xC5, (byte) 0x7D, (byte) 0xB2,
+            (byte) 0x7C, (byte) 0x36, (byte) 0x0D, (byte) 0x9C, (byte) 0x1F, (byte) 0x83,
+            (byte) 0x57, (byte) 0x94, (byte) 0x26, (byte) 0x32, (byte) 0x9C, (byte) 0x86,
+            (byte) 0x8E, (byte) 0xE5, (byte) 0x80, (byte) 0x3A, (byte) 0xA9, (byte) 0xAF,
+            (byte) 0x4A, (byte) 0x95, (byte) 0x78, (byte) 0x8D, (byte) 0xE6, (byte) 0xC3,
+            (byte) 0x0C, (byte) 0x78, (byte) 0x83, (byte) 0x4B, (byte) 0xF5, (byte) 0x40,
+            (byte) 0x04, (byte) 0x20, (byte) 0x90, (byte) 0x5C, (byte) 0xA1, (byte) 0x19,
+            (byte) 0xEB, (byte) 0x95, (byte) 0x70, (byte) 0x2B, (byte) 0x94, (byte) 0xA3,
+            (byte) 0x43, (byte) 0xDD, (byte) 0xEB, (byte) 0xD4, (byte) 0x0C, (byte) 0xBC,
+            (byte) 0xBD, (byte) 0x58, (byte) 0x2D, (byte) 0x75, (byte) 0xB0, (byte) 0x8D,
+            (byte) 0x8B, (byte) 0x70, (byte) 0xB9, (byte) 0xE7, (byte) 0xA3, (byte) 0xCC,
+            (byte) 0x8C, (byte) 0xB4, (byte) 0xCD, (byte) 0xBB, (byte) 0x4B, (byte) 0xB1,
+            (byte) 0x15, (byte) 0x18, (byte) 0x79, (byte) 0xDF, (byte) 0x22, (byte) 0xA6,
+            (byte) 0x5C, (byte) 0x90, (byte) 0x7C, (byte) 0x1F, (byte) 0xEA, (byte) 0x1B,
+            (byte) 0xF2, (byte) 0x89, (byte) 0x87, (byte) 0xB2, (byte) 0xEC, (byte) 0x57,
+            (byte) 0xFF, (byte) 0xB2, (byte) 0xDA, (byte) 0xF5, (byte) 0xAD, (byte) 0x73,
+            (byte) 0xC0, (byte) 0xA0, (byte) 0x20, (byte) 0x8B, (byte) 0x78, (byte) 0xA1,
+            (byte) 0x5D, (byte) 0x04, (byte) 0x0A, (byte) 0x29, (byte) 0xE3, (byte) 0xD7,
+            (byte) 0x37, (byte) 0xF6, (byte) 0xA2, (byte) 0xCA,
+    };
+
+    public void test_DSA_generate_key() throws Exception {
+        final byte[] seed = new byte[20];
+
+        // Real key
+        {
+            int ctx = 0;
+            try {
+                ctx = NativeCrypto.DSA_generate_key(2048, seed, dsa2048_g, dsa2048_p, dsa2048_q);
+                assertTrue(ctx != NULL);
+            } finally {
+                if (ctx != 0) {
+                    NativeCrypto.EVP_PKEY_free(ctx);
+                }
+            }
+        }
+
+        // Real key with minimum bit size (should be 512 bits)
+        {
+            int ctx = 0;
+            try {
+                ctx = NativeCrypto.DSA_generate_key(0, null, null, null, null);
+                assertTrue(ctx != NULL);
+            } finally {
+                if (ctx != 0) {
+                    NativeCrypto.EVP_PKEY_free(ctx);
+                }
+            }
+        }
+
+        // Bad DSA params.
+        {
+            int ctx = 0;
+            try {
+                ctx = NativeCrypto.DSA_generate_key(0, null, new byte[] {}, new byte[] {},
+                        new byte[] {});
+                fail();
+            } catch (RuntimeException expected) {
+            } finally {
+                if (ctx != 0) {
+                    NativeCrypto.EVP_PKEY_free(ctx);
+                }
+            }
+        }
+    }
+
     /*
      * Test vector generation:
      * openssl rand -hex 16