Bug 992240 - RSA PopulatePrivateKey PKCS1 replace, r=rbarnes,rrelyea
authorFranziskus Kiefer <franziskuskiefer@gmail.com>
Wed, 28 Sep 2016 13:06:11 +0200
changeset 12638 df4ebf05c2af8b29e5bce5ec3aaaea50fef2a8ac
parent 12637 99cbef6af40bbc3040dbaba5b6ec57c2f35f0e7a
child 12639 233a44e96b228bfe98eb79c0586538df00de7cba
push id1598
push userfranziskuskiefer@gmail.com
push dateWed, 28 Sep 2016 11:48:09 +0000
reviewersrbarnes, rrelyea
bugs992240
Bug 992240 - RSA PopulatePrivateKey PKCS1 replace, r=rbarnes,rrelyea This patch was contributed by Filippo Valsarda
cmd/bltest/blapitest.c
cmd/bltest/pkcs1_vectors.h
lib/freebl/rsa.c
tests/cipher/cipher.txt
--- a/cmd/bltest/blapitest.c
+++ b/cmd/bltest/blapitest.c
@@ -16,16 +16,18 @@
 #include "basicutil.h"
 #include "plgetopt.h"
 #include "softoken.h"
 #include "nspr.h"
 #include "secport.h"
 #include "secoid.h"
 #include "nssutil.h"
 
+#include "pkcs1_vectors.h"
+
 #ifndef NSS_DISABLE_ECC
 #include "ecl-curve.h"
 SECStatus EC_DecodeParams(const SECItem *encodedParams,
                           ECParams **ecparams);
 SECStatus EC_CopyParams(PLArenaPool *arena, ECParams *dstParams,
                         const ECParams *srcParams);
 #endif
 
@@ -3405,28 +3407,74 @@ rsaPrivKeysAreEqual(RSAPrivateKey *src, 
         fprintf(stderr, "original key:\n");
         dump_rsakey(src);
         fprintf(stderr, "recreated key:\n");
         dump_rsakey(dest);
     }
     return areEqual;
 }
 
+static int
+doRSAPopulateTestKV()
+{
+    RSAPrivateKey tstKey = { 0 };
+    SECStatus rv;
+    int failed = 0;
+    int i;
+
+    tstKey.arena = NULL;
+
+    /* Test public exponent, private exponent, modulus cases from
+     * pkcs1v15sign-vectors.txt. Some are valid PKCS#1 keys but not valid RSA
+     * ones (de = 1 mod lcm(p − 1, q − 1))
+     */
+    for (i = 0; i < PR_ARRAY_SIZE(PKCS1_VECTORS); ++i) {
+        struct pkcs1_test_vector *v = &PKCS1_VECTORS[i];
+
+        rsaPrivKeyReset(&tstKey);
+        tstKey.privateExponent.data = v->d;
+        tstKey.privateExponent.len = v->d_len;
+        tstKey.publicExponent.data = v->e;
+        tstKey.publicExponent.len = v->e_len;
+        tstKey.modulus.data = v->n;
+        tstKey.modulus.len = v->n_len;
+
+        rv = RSA_PopulatePrivateKey(&tstKey);
+        if (rv != SECSuccess) {
+            fprintf(stderr, "RSA Populate failed: pkcs1v15sign-vector %d\n", i);
+            failed = 1;
+        } else if (memcmp(v->q, tstKey.prime1.data, v->q_len) ||
+                   tstKey.prime1.len != v->q_len) {
+            fprintf(stderr, "RSA Populate key mismatch: pkcs1v15sign-vector %d q\n", i);
+            failed = 1;
+        } else if (memcmp(v->p, tstKey.prime2.data, v->p_len) ||
+                   tstKey.prime1.len != v->p_len) {
+            fprintf(stderr, "RSA Populate key mismatch: pkcs1v15sign-vector %d p\n", i);
+            failed = 1;
+        } else {
+            fprintf(stderr, "RSA Populate success: pkcs1v15sign-vector %d p\n", i);
+        }
+    }
+
+    PORT_FreeArena(tstKey.arena, PR_TRUE);
+    return failed;
+}
+
 /*
  * Test the RSA populate command to see that it can really build
- * keys from it's components.
+ * keys from its components.
  */
 static int
 doRSAPopulateTest(unsigned int keySize, unsigned long exponent)
 {
     RSAPrivateKey *srcKey;
     RSAPrivateKey tstKey = { 0 };
     SECItem expitem = { 0, 0, 0 };
     SECStatus rv;
-    unsigned char pubExp[4];
+    unsigned char pubExp[32];
     int expLen = 0;
     int failed = 0;
     int i;
 
     for (i = 0; i < sizeof(unsigned long); i++) {
         int shift = (sizeof(unsigned long) - i - 1) * 8;
         if (expLen || (exponent && ((unsigned long)0xffL << shift))) {
             pubExp[expLen] = (unsigned char)((exponent >> shift) & 0xff);
@@ -3499,18 +3547,18 @@ doRSAPopulateTest(unsigned int keySize, 
     tstKey.publicExponent = srcKey->publicExponent;
     tstKey.prime2 = srcKey->prime2; /* use q in the prime2 position */
 
     rv = RSA_PopulatePrivateKey(&tstKey);
     if (rv != SECSuccess) {
         fprintf(stderr, "RSA Populate failed: pubExp privExp q\n");
         fprintf(stderr, " - not fatal\n");
         /* it's possible that we can't uniquely determine the original key
-     * from just the exponents and prime. Populate returns an error rather
-     * than return the wrong key. */
+         * from just the exponents and prime. Populate returns an error rather
+         * than return the wrong key. */
     } else if (!rsaPrivKeysAreEqual(&tstKey, srcKey)) {
         /* if we returned a key, it *must* be correct */
         fprintf(stderr, "RSA Populate key mismatch: pubExp privExp  q\n");
         rv = RSA_PrivateKeyCheck(&tstKey);
         failed = 1;
     }
 
     /* test the advanced case2, public exponent, private exponent, modulus */
@@ -3524,28 +3572,30 @@ doRSAPopulateTest(unsigned int keySize, 
     if (rv != SECSuccess) {
         fprintf(stderr, "RSA Populate failed: pubExp privExp mod\n");
         failed = 1;
     } else if (!rsaPrivKeysAreEqual(&tstKey, srcKey)) {
         fprintf(stderr, "RSA Populate key mismatch: pubExp privExp  mod\n");
         failed = 1;
     }
 
+    PORT_FreeArena(srcKey->arena, PR_TRUE);
     return failed ? -1 : 0;
 }
 
 /* bltest commands */
 enum {
     cmd_Decrypt = 0,
     cmd_Encrypt,
     cmd_FIPS,
     cmd_Hash,
     cmd_Nonce,
     cmd_Dump,
     cmd_RSAPopulate,
+    cmd_RSAPopulateKV,
     cmd_Sign,
     cmd_SelfTest,
     cmd_Verify
 };
 
 /* bltest options */
 enum {
     opt_B64 = 0,
@@ -3589,16 +3639,17 @@ static secuCommandFlag bltest_commands[]
     {
       { /* cmd_Decrypt */ 'D', PR_FALSE, 0, PR_FALSE },
       { /* cmd_Encrypt */ 'E', PR_FALSE, 0, PR_FALSE },
       { /* cmd_FIPS */ 'F', PR_FALSE, 0, PR_FALSE },
       { /* cmd_Hash */ 'H', PR_FALSE, 0, PR_FALSE },
       { /* cmd_Nonce */ 'N', PR_FALSE, 0, PR_FALSE },
       { /* cmd_Dump */ 'P', PR_FALSE, 0, PR_FALSE },
       { /* cmd_RSAPopulate */ 'R', PR_FALSE, 0, PR_FALSE },
+      { /* cmd_RSAPopulateKV */ 'K', PR_FALSE, 0, PR_FALSE },
       { /* cmd_Sign */ 'S', PR_FALSE, 0, PR_FALSE },
       { /* cmd_SelfTest */ 'T', PR_FALSE, 0, PR_FALSE },
       { /* cmd_Verify */ 'V', PR_FALSE, 0, PR_FALSE }
     };
 
 static secuCommandFlag bltest_options[] =
     {
       { /* opt_B64 */ 'a', PR_FALSE, 0, PR_FALSE },
@@ -3726,16 +3777,22 @@ main(int argc, char **argv)
 
     testdir = (bltest.options[opt_SelfTestDir].activated) ? strdup(bltest.options[opt_SelfTestDir].arg)
                                                           : ".";
 
     /*
      * Handle three simple cases first
      */
 
+    /* test the RSA_PopulatePrivateKey function with known vectors */
+    if (bltest.commands[cmd_RSAPopulateKV].activated) {
+        PORT_Free(cipherInfo);
+        return doRSAPopulateTestKV();
+    }
+
     /* test the RSA_PopulatePrivateKey function */
     if (bltest.commands[cmd_RSAPopulate].activated) {
         unsigned int keySize = 1024;
         unsigned long exponent = 65537;
         int rounds = 1;
         int ret = -1;
 
         if (bltest.options[opt_KeySize].activated) {
@@ -3753,16 +3810,17 @@ main(int argc, char **argv)
             ret = doRSAPopulateTest(keySize, exponent);
             if (ret != 0) {
                 break;
             }
         }
         if (ret != 0) {
             fprintf(stderr, "RSA Populate test round %d: FAILED\n", i);
         }
+        PORT_Free(cipherInfo);
         return ret;
     }
 
     /* Do BLAPI self-test */
     if (bltest.commands[cmd_SelfTest].activated) {
         PRBool encrypt = PR_TRUE, decrypt = PR_TRUE;
         /* user may specified a set of ciphers to test.  parse them. */
         bltestCipherMode modesToTest[NUMMODES];
new file mode 100644
--- /dev/null
+++ b/cmd/bltest/pkcs1_vectors.h
@@ -0,0 +1,789 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Vectors from pkcs1v15sign-vectors.txt */
+
+struct pkcs1_test_vector {
+    unsigned char *n;
+    unsigned long n_len;
+    unsigned char *e;
+    unsigned long e_len;
+    unsigned char *d;
+    unsigned long d_len;
+    unsigned char *p;
+    unsigned long p_len;
+    unsigned char *q;
+    unsigned long q_len;
+};
+
+struct pkcs1_test_vector PKCS1_VECTORS[15] = {
+    {
+        (unsigned char[]){
+            0xa5, 0x6e, 0x4a, 0x0e, 0x70, 0x10, 0x17, 0x58, 0x9a, 0x51,
+            0x87, 0xdc, 0x7e, 0xa8, 0x41, 0xd1, 0x56, 0xf2, 0xec, 0x0e,
+            0x36, 0xad, 0x52, 0xa4, 0x4d, 0xfe, 0xb1, 0xe6, 0x1f, 0x7a,
+            0xd9, 0x91, 0xd8, 0xc5, 0x10, 0x56, 0xff, 0xed, 0xb1, 0x62,
+            0xb4, 0xc0, 0xf2, 0x83, 0xa1, 0x2a, 0x88, 0xa3, 0x94, 0xdf,
+            0xf5, 0x26, 0xab, 0x72, 0x91, 0xcb, 0xb3, 0x07, 0xce, 0xab,
+            0xfc, 0xe0, 0xb1, 0xdf, 0xd5, 0xcd, 0x95, 0x08, 0x09, 0x6d,
+            0x5b, 0x2b, 0x8b, 0x6d, 0xf5, 0xd6, 0x71, 0xef, 0x63, 0x77,
+            0xc0, 0x92, 0x1c, 0xb2, 0x3c, 0x27, 0x0a, 0x70, 0xe2, 0x59,
+            0x8e, 0x6f, 0xf8, 0x9d, 0x19, 0xf1, 0x05, 0xac, 0xc2, 0xd3,
+            0xf0, 0xcb, 0x35, 0xf2, 0x92, 0x80, 0xe1, 0x38, 0x6b, 0x6f,
+            0x64, 0xc4, 0xef, 0x22, 0xe1, 0xe1, 0xf2, 0x0d, 0x0c, 0xe8,
+            0xcf, 0xfb, 0x22, 0x49, 0xbd, 0x9a, 0x21, 0x37 },
+        128,
+        (unsigned char[]){ 0x01, 0x00, 0x01 }, 3,
+        (unsigned char[]){
+            0x33, 0xa5, 0x04, 0x2a, 0x90, 0xb2, 0x7d, 0x4f, 0x54, 0x51,
+            0xca, 0x9b, 0xbb, 0xd0, 0xb4, 0x47, 0x71, 0xa1, 0x01, 0xaf,
+            0x88, 0x43, 0x40, 0xae, 0xf9, 0x88, 0x5f, 0x2a, 0x4b, 0xbe,
+            0x92, 0xe8, 0x94, 0xa7, 0x24, 0xac, 0x3c, 0x56, 0x8c, 0x8f,
+            0x97, 0x85, 0x3a, 0xd0, 0x7c, 0x02, 0x66, 0xc8, 0xc6, 0xa3,
+            0xca, 0x09, 0x29, 0xf1, 0xe8, 0xf1, 0x12, 0x31, 0x88, 0x44,
+            0x29, 0xfc, 0x4d, 0x9a, 0xe5, 0x5f, 0xee, 0x89, 0x6a, 0x10,
+            0xce, 0x70, 0x7c, 0x3e, 0xd7, 0xe7, 0x34, 0xe4, 0x47, 0x27,
+            0xa3, 0x95, 0x74, 0x50, 0x1a, 0x53, 0x26, 0x83, 0x10, 0x9c,
+            0x2a, 0xba, 0xca, 0xba, 0x28, 0x3c, 0x31, 0xb4, 0xbd, 0x2f,
+            0x53, 0xc3, 0xee, 0x37, 0xe3, 0x52, 0xce, 0xe3, 0x4f, 0x9e,
+            0x50, 0x3b, 0xd8, 0x0c, 0x06, 0x22, 0xad, 0x79, 0xc6, 0xdc,
+            0xee, 0x88, 0x35, 0x47, 0xc6, 0xa3, 0xb3, 0x25 },
+        128,
+        (unsigned char[]){
+            0xb6, 0x9d, 0xca, 0x1c, 0xf7, 0xd4, 0xd7, 0xec, 0x81, 0xe7,
+            0x5b, 0x90, 0xfc, 0xca, 0x87, 0x4a, 0xbc, 0xde, 0x12, 0x3f,
+            0xd2, 0x70, 0x01, 0x80, 0xaa, 0x90, 0x47, 0x9b, 0x6e, 0x48,
+            0xde, 0x8d, 0x67, 0xed, 0x24, 0xf9, 0xf1, 0x9d, 0x85, 0xba,
+            0x27, 0x58, 0x74, 0xf5, 0x42, 0xcd, 0x20, 0xdc, 0x72, 0x3e,
+            0x69, 0x63, 0x36, 0x4a, 0x1f, 0x94, 0x25, 0x45, 0x2b, 0x26,
+            0x9a, 0x67, 0x99, 0xfd },
+        64,
+        (unsigned char[]){
+            0xe7, 0xe8, 0x94, 0x27, 0x20, 0xa8, 0x77, 0x51, 0x72, 0x73,
+            0xa3, 0x56, 0x05, 0x3e, 0xa2, 0xa1, 0xbc, 0x0c, 0x94, 0xaa,
+            0x72, 0xd5, 0x5c, 0x6e, 0x86, 0x29, 0x6b, 0x2d, 0xfc, 0x96,
+            0x79, 0x48, 0xc0, 0xa7, 0x2c, 0xbc, 0xcc, 0xa7, 0xea, 0xcb,
+            0x35, 0x70, 0x6e, 0x09, 0xa1, 0xdf, 0x55, 0xa1, 0x53, 0x5b,
+            0xd9, 0xb3, 0xcc, 0x34, 0x16, 0x0b, 0x3b, 0x6d, 0xcd, 0x3e,
+            0xda, 0x8e, 0x64, 0x43 },
+        64,
+    },
+    {
+        (unsigned char[]){
+            0xa5, 0x6e, 0x4a, 0x0e, 0x70, 0x10, 0x17, 0x58, 0x9a, 0x51,
+            0x87, 0xdc, 0x7e, 0xa8, 0x41, 0xd1, 0x56, 0xf2, 0xec, 0x0e,
+            0x36, 0xad, 0x52, 0xa4, 0x4d, 0xfe, 0xb1, 0xe6, 0x1f, 0x7a,
+            0xd9, 0x91, 0xd8, 0xc5, 0x10, 0x56, 0xff, 0xed, 0xb1, 0x62,
+            0xb4, 0xc0, 0xf2, 0x83, 0xa1, 0x2a, 0x88, 0xa3, 0x94, 0xdf,
+            0xf5, 0x26, 0xab, 0x72, 0x91, 0xcb, 0xb3, 0x07, 0xce, 0xab,
+            0xfc, 0xe0, 0xb1, 0xdf, 0xd5, 0xcd, 0x95, 0x08, 0x09, 0x6d,
+            0x5b, 0x2b, 0x8b, 0x6d, 0xf5, 0xd6, 0x71, 0xef, 0x63, 0x77,
+            0xc0, 0x92, 0x1c, 0xb2, 0x3c, 0x27, 0x0a, 0x70, 0xe2, 0x59,
+            0x8e, 0x6f, 0xf8, 0x9d, 0x19, 0xf1, 0x05, 0xac, 0xc2, 0xd3,
+            0xf0, 0xcb, 0x35, 0xf2, 0x92, 0x80, 0xe1, 0x38, 0x6b, 0x6f,
+            0x64, 0xc4, 0xef, 0x22, 0xe1, 0xe1, 0xf2, 0x0d, 0x0c, 0xe8,
+            0xcf, 0xfb, 0x22, 0x49, 0xbd, 0x9a, 0x21, 0x37 },
+        128,
+        (unsigned char[]){ 0x01, 0x00, 0x01 }, 3,
+        (unsigned char[]){
+            0x33, 0xa5, 0x04, 0x2a, 0x90, 0xb2, 0x7d, 0x4f, 0x54, 0x51,
+            0xca, 0x9b, 0xbb, 0xd0, 0xb4, 0x47, 0x71, 0xa1, 0x01, 0xaf,
+            0x88, 0x43, 0x40, 0xae, 0xf9, 0x88, 0x5f, 0x2a, 0x4b, 0xbe,
+            0x92, 0xe8, 0x94, 0xa7, 0x24, 0xac, 0x3c, 0x56, 0x8c, 0x8f,
+            0x97, 0x85, 0x3a, 0xd0, 0x7c, 0x02, 0x66, 0xc8, 0xc6, 0xa3,
+            0xca, 0x09, 0x29, 0xf1, 0xe8, 0xf1, 0x12, 0x31, 0x88, 0x44,
+            0x29, 0xfc, 0x4d, 0x9a, 0xe5, 0x5f, 0xee, 0x89, 0x6a, 0x10,
+            0xce, 0x70, 0x7c, 0x3e, 0xd7, 0xe7, 0x34, 0xe4, 0x47, 0x27,
+            0xa3, 0x95, 0x74, 0x50, 0x1a, 0x53, 0x26, 0x83, 0x10, 0x9c,
+            0x2a, 0xba, 0xca, 0xba, 0x28, 0x3c, 0x31, 0xb4, 0xbd, 0x2f,
+            0x53, 0xc3, 0xee, 0x37, 0xe3, 0x52, 0xce, 0xe3, 0x4f, 0x9e,
+            0x50, 0x3b, 0xd8, 0x0c, 0x06, 0x22, 0xad, 0x79, 0xc6, 0xdc,
+            0xee, 0x88, 0x35, 0x47, 0xc6, 0xa3, 0xb3, 0x25 },
+        128,
+        (unsigned char[]){
+            0xb6, 0x9d, 0xca, 0x1c, 0xf7, 0xd4, 0xd7, 0xec, 0x81, 0xe7,
+            0x5b, 0x90, 0xfc, 0xca, 0x87, 0x4a, 0xbc, 0xde, 0x12, 0x3f,
+            0xd2, 0x70, 0x01, 0x80, 0xaa, 0x90, 0x47, 0x9b, 0x6e, 0x48,
+            0xde, 0x8d, 0x67, 0xed, 0x24, 0xf9, 0xf1, 0x9d, 0x85, 0xba,
+            0x27, 0x58, 0x74, 0xf5, 0x42, 0xcd, 0x20, 0xdc, 0x72, 0x3e,
+            0x69, 0x63, 0x36, 0x4a, 0x1f, 0x94, 0x25, 0x45, 0x2b, 0x26,
+            0x9a, 0x67, 0x99, 0xfd },
+        64,
+        (unsigned char[]){
+            0xe7, 0xe8, 0x94, 0x27, 0x20, 0xa8, 0x77, 0x51, 0x72, 0x73,
+            0xa3, 0x56, 0x05, 0x3e, 0xa2, 0xa1, 0xbc, 0x0c, 0x94, 0xaa,
+            0x72, 0xd5, 0x5c, 0x6e, 0x86, 0x29, 0x6b, 0x2d, 0xfc, 0x96,
+            0x79, 0x48, 0xc0, 0xa7, 0x2c, 0xbc, 0xcc, 0xa7, 0xea, 0xcb,
+            0x35, 0x70, 0x6e, 0x09, 0xa1, 0xdf, 0x55, 0xa1, 0x53, 0x5b,
+            0xd9, 0xb3, 0xcc, 0x34, 0x16, 0x0b, 0x3b, 0x6d, 0xcd, 0x3e,
+            0xda, 0x8e, 0x64, 0x43 },
+        64,
+    },
+    {
+        (unsigned char[]){
+            0xa5, 0x6e, 0x4a, 0x0e, 0x70, 0x10, 0x17, 0x58, 0x9a, 0x51,
+            0x87, 0xdc, 0x7e, 0xa8, 0x41, 0xd1, 0x56, 0xf2, 0xec, 0x0e,
+            0x36, 0xad, 0x52, 0xa4, 0x4d, 0xfe, 0xb1, 0xe6, 0x1f, 0x7a,
+            0xd9, 0x91, 0xd8, 0xc5, 0x10, 0x56, 0xff, 0xed, 0xb1, 0x62,
+            0xb4, 0xc0, 0xf2, 0x83, 0xa1, 0x2a, 0x88, 0xa3, 0x94, 0xdf,
+            0xf5, 0x26, 0xab, 0x72, 0x91, 0xcb, 0xb3, 0x07, 0xce, 0xab,
+            0xfc, 0xe0, 0xb1, 0xdf, 0xd5, 0xcd, 0x95, 0x08, 0x09, 0x6d,
+            0x5b, 0x2b, 0x8b, 0x6d, 0xf5, 0xd6, 0x71, 0xef, 0x63, 0x77,
+            0xc0, 0x92, 0x1c, 0xb2, 0x3c, 0x27, 0x0a, 0x70, 0xe2, 0x59,
+            0x8e, 0x6f, 0xf8, 0x9d, 0x19, 0xf1, 0x05, 0xac, 0xc2, 0xd3,
+            0xf0, 0xcb, 0x35, 0xf2, 0x92, 0x80, 0xe1, 0x38, 0x6b, 0x6f,
+            0x64, 0xc4, 0xef, 0x22, 0xe1, 0xe1, 0xf2, 0x0d, 0x0c, 0xe8,
+            0xcf, 0xfb, 0x22, 0x49, 0xbd, 0x9a, 0x21, 0x37 },
+        128,
+        (unsigned char[]){ 0x01, 0x00, 0x01 }, 3,
+        (unsigned char[]){
+            0x33, 0xa5, 0x04, 0x2a, 0x90, 0xb2, 0x7d, 0x4f, 0x54, 0x51,
+            0xca, 0x9b, 0xbb, 0xd0, 0xb4, 0x47, 0x71, 0xa1, 0x01, 0xaf,
+            0x88, 0x43, 0x40, 0xae, 0xf9, 0x88, 0x5f, 0x2a, 0x4b, 0xbe,
+            0x92, 0xe8, 0x94, 0xa7, 0x24, 0xac, 0x3c, 0x56, 0x8c, 0x8f,
+            0x97, 0x85, 0x3a, 0xd0, 0x7c, 0x02, 0x66, 0xc8, 0xc6, 0xa3,
+            0xca, 0x09, 0x29, 0xf1, 0xe8, 0xf1, 0x12, 0x31, 0x88, 0x44,
+            0x29, 0xfc, 0x4d, 0x9a, 0xe5, 0x5f, 0xee, 0x89, 0x6a, 0x10,
+            0xce, 0x70, 0x7c, 0x3e, 0xd7, 0xe7, 0x34, 0xe4, 0x47, 0x27,
+            0xa3, 0x95, 0x74, 0x50, 0x1a, 0x53, 0x26, 0x83, 0x10, 0x9c,
+            0x2a, 0xba, 0xca, 0xba, 0x28, 0x3c, 0x31, 0xb4, 0xbd, 0x2f,
+            0x53, 0xc3, 0xee, 0x37, 0xe3, 0x52, 0xce, 0xe3, 0x4f, 0x9e,
+            0x50, 0x3b, 0xd8, 0x0c, 0x06, 0x22, 0xad, 0x79, 0xc6, 0xdc,
+            0xee, 0x88, 0x35, 0x47, 0xc6, 0xa3, 0xb3, 0x25 },
+        128,
+        (unsigned char[]){
+            0xb6, 0x9d, 0xca, 0x1c, 0xf7, 0xd4, 0xd7, 0xec, 0x81, 0xe7,
+            0x5b, 0x90, 0xfc, 0xca, 0x87, 0x4a, 0xbc, 0xde, 0x12, 0x3f,
+            0xd2, 0x70, 0x01, 0x80, 0xaa, 0x90, 0x47, 0x9b, 0x6e, 0x48,
+            0xde, 0x8d, 0x67, 0xed, 0x24, 0xf9, 0xf1, 0x9d, 0x85, 0xba,
+            0x27, 0x58, 0x74, 0xf5, 0x42, 0xcd, 0x20, 0xdc, 0x72, 0x3e,
+            0x69, 0x63, 0x36, 0x4a, 0x1f, 0x94, 0x25, 0x45, 0x2b, 0x26,
+            0x9a, 0x67, 0x99, 0xfd },
+        64,
+        (unsigned char[]){
+            0xe7, 0xe8, 0x94, 0x27, 0x20, 0xa8, 0x77, 0x51, 0x72, 0x73,
+            0xa3, 0x56, 0x05, 0x3e, 0xa2, 0xa1, 0xbc, 0x0c, 0x94, 0xaa,
+            0x72, 0xd5, 0x5c, 0x6e, 0x86, 0x29, 0x6b, 0x2d, 0xfc, 0x96,
+            0x79, 0x48, 0xc0, 0xa7, 0x2c, 0xbc, 0xcc, 0xa7, 0xea, 0xcb,
+            0x35, 0x70, 0x6e, 0x09, 0xa1, 0xdf, 0x55, 0xa1, 0x53, 0x5b,
+            0xd9, 0xb3, 0xcc, 0x34, 0x16, 0x0b, 0x3b, 0x6d, 0xcd, 0x3e,
+            0xda, 0x8e, 0x64, 0x43 },
+        64,
+    },
+    {
+        (unsigned char[]){
+            0xa5, 0x6e, 0x4a, 0x0e, 0x70, 0x10, 0x17, 0x58, 0x9a, 0x51,
+            0x87, 0xdc, 0x7e, 0xa8, 0x41, 0xd1, 0x56, 0xf2, 0xec, 0x0e,
+            0x36, 0xad, 0x52, 0xa4, 0x4d, 0xfe, 0xb1, 0xe6, 0x1f, 0x7a,
+            0xd9, 0x91, 0xd8, 0xc5, 0x10, 0x56, 0xff, 0xed, 0xb1, 0x62,
+            0xb4, 0xc0, 0xf2, 0x83, 0xa1, 0x2a, 0x88, 0xa3, 0x94, 0xdf,
+            0xf5, 0x26, 0xab, 0x72, 0x91, 0xcb, 0xb3, 0x07, 0xce, 0xab,
+            0xfc, 0xe0, 0xb1, 0xdf, 0xd5, 0xcd, 0x95, 0x08, 0x09, 0x6d,
+            0x5b, 0x2b, 0x8b, 0x6d, 0xf5, 0xd6, 0x71, 0xef, 0x63, 0x77,
+            0xc0, 0x92, 0x1c, 0xb2, 0x3c, 0x27, 0x0a, 0x70, 0xe2, 0x59,
+            0x8e, 0x6f, 0xf8, 0x9d, 0x19, 0xf1, 0x05, 0xac, 0xc2, 0xd3,
+            0xf0, 0xcb, 0x35, 0xf2, 0x92, 0x80, 0xe1, 0x38, 0x6b, 0x6f,
+            0x64, 0xc4, 0xef, 0x22, 0xe1, 0xe1, 0xf2, 0x0d, 0x0c, 0xe8,
+            0xcf, 0xfb, 0x22, 0x49, 0xbd, 0x9a, 0x21, 0x37 },
+        128,
+        (unsigned char[]){ 0x01, 0x00, 0x01 }, 3,
+        (unsigned char[]){
+            0x33, 0xa5, 0x04, 0x2a, 0x90, 0xb2, 0x7d, 0x4f, 0x54, 0x51,
+            0xca, 0x9b, 0xbb, 0xd0, 0xb4, 0x47, 0x71, 0xa1, 0x01, 0xaf,
+            0x88, 0x43, 0x40, 0xae, 0xf9, 0x88, 0x5f, 0x2a, 0x4b, 0xbe,
+            0x92, 0xe8, 0x94, 0xa7, 0x24, 0xac, 0x3c, 0x56, 0x8c, 0x8f,
+            0x97, 0x85, 0x3a, 0xd0, 0x7c, 0x02, 0x66, 0xc8, 0xc6, 0xa3,
+            0xca, 0x09, 0x29, 0xf1, 0xe8, 0xf1, 0x12, 0x31, 0x88, 0x44,
+            0x29, 0xfc, 0x4d, 0x9a, 0xe5, 0x5f, 0xee, 0x89, 0x6a, 0x10,
+            0xce, 0x70, 0x7c, 0x3e, 0xd7, 0xe7, 0x34, 0xe4, 0x47, 0x27,
+            0xa3, 0x95, 0x74, 0x50, 0x1a, 0x53, 0x26, 0x83, 0x10, 0x9c,
+            0x2a, 0xba, 0xca, 0xba, 0x28, 0x3c, 0x31, 0xb4, 0xbd, 0x2f,
+            0x53, 0xc3, 0xee, 0x37, 0xe3, 0x52, 0xce, 0xe3, 0x4f, 0x9e,
+            0x50, 0x3b, 0xd8, 0x0c, 0x06, 0x22, 0xad, 0x79, 0xc6, 0xdc,
+            0xee, 0x88, 0x35, 0x47, 0xc6, 0xa3, 0xb3, 0x25 },
+        128,
+        (unsigned char[]){
+            0xb6, 0x9d, 0xca, 0x1c, 0xf7, 0xd4, 0xd7, 0xec, 0x81, 0xe7,
+            0x5b, 0x90, 0xfc, 0xca, 0x87, 0x4a, 0xbc, 0xde, 0x12, 0x3f,
+            0xd2, 0x70, 0x01, 0x80, 0xaa, 0x90, 0x47, 0x9b, 0x6e, 0x48,
+            0xde, 0x8d, 0x67, 0xed, 0x24, 0xf9, 0xf1, 0x9d, 0x85, 0xba,
+            0x27, 0x58, 0x74, 0xf5, 0x42, 0xcd, 0x20, 0xdc, 0x72, 0x3e,
+            0x69, 0x63, 0x36, 0x4a, 0x1f, 0x94, 0x25, 0x45, 0x2b, 0x26,
+            0x9a, 0x67, 0x99, 0xfd },
+        64,
+        (unsigned char[]){
+            0xe7, 0xe8, 0x94, 0x27, 0x20, 0xa8, 0x77, 0x51, 0x72, 0x73,
+            0xa3, 0x56, 0x05, 0x3e, 0xa2, 0xa1, 0xbc, 0x0c, 0x94, 0xaa,
+            0x72, 0xd5, 0x5c, 0x6e, 0x86, 0x29, 0x6b, 0x2d, 0xfc, 0x96,
+            0x79, 0x48, 0xc0, 0xa7, 0x2c, 0xbc, 0xcc, 0xa7, 0xea, 0xcb,
+            0x35, 0x70, 0x6e, 0x09, 0xa1, 0xdf, 0x55, 0xa1, 0x53, 0x5b,
+            0xd9, 0xb3, 0xcc, 0x34, 0x16, 0x0b, 0x3b, 0x6d, 0xcd, 0x3e,
+            0xda, 0x8e, 0x64, 0x43 },
+        64,
+    },
+    {
+        (unsigned char[]){
+            0xa5, 0x6e, 0x4a, 0x0e, 0x70, 0x10, 0x17, 0x58, 0x9a, 0x51,
+            0x87, 0xdc, 0x7e, 0xa8, 0x41, 0xd1, 0x56, 0xf2, 0xec, 0x0e,
+            0x36, 0xad, 0x52, 0xa4, 0x4d, 0xfe, 0xb1, 0xe6, 0x1f, 0x7a,
+            0xd9, 0x91, 0xd8, 0xc5, 0x10, 0x56, 0xff, 0xed, 0xb1, 0x62,
+            0xb4, 0xc0, 0xf2, 0x83, 0xa1, 0x2a, 0x88, 0xa3, 0x94, 0xdf,
+            0xf5, 0x26, 0xab, 0x72, 0x91, 0xcb, 0xb3, 0x07, 0xce, 0xab,
+            0xfc, 0xe0, 0xb1, 0xdf, 0xd5, 0xcd, 0x95, 0x08, 0x09, 0x6d,
+            0x5b, 0x2b, 0x8b, 0x6d, 0xf5, 0xd6, 0x71, 0xef, 0x63, 0x77,
+            0xc0, 0x92, 0x1c, 0xb2, 0x3c, 0x27, 0x0a, 0x70, 0xe2, 0x59,
+            0x8e, 0x6f, 0xf8, 0x9d, 0x19, 0xf1, 0x05, 0xac, 0xc2, 0xd3,
+            0xf0, 0xcb, 0x35, 0xf2, 0x92, 0x80, 0xe1, 0x38, 0x6b, 0x6f,
+            0x64, 0xc4, 0xef, 0x22, 0xe1, 0xe1, 0xf2, 0x0d, 0x0c, 0xe8,
+            0xcf, 0xfb, 0x22, 0x49, 0xbd, 0x9a, 0x21, 0x37 },
+        128,
+        (unsigned char[]){ 0x01, 0x00, 0x01 }, 3,
+        (unsigned char[]){
+            0x33, 0xa5, 0x04, 0x2a, 0x90, 0xb2, 0x7d, 0x4f, 0x54, 0x51,
+            0xca, 0x9b, 0xbb, 0xd0, 0xb4, 0x47, 0x71, 0xa1, 0x01, 0xaf,
+            0x88, 0x43, 0x40, 0xae, 0xf9, 0x88, 0x5f, 0x2a, 0x4b, 0xbe,
+            0x92, 0xe8, 0x94, 0xa7, 0x24, 0xac, 0x3c, 0x56, 0x8c, 0x8f,
+            0x97, 0x85, 0x3a, 0xd0, 0x7c, 0x02, 0x66, 0xc8, 0xc6, 0xa3,
+            0xca, 0x09, 0x29, 0xf1, 0xe8, 0xf1, 0x12, 0x31, 0x88, 0x44,
+            0x29, 0xfc, 0x4d, 0x9a, 0xe5, 0x5f, 0xee, 0x89, 0x6a, 0x10,
+            0xce, 0x70, 0x7c, 0x3e, 0xd7, 0xe7, 0x34, 0xe4, 0x47, 0x27,
+            0xa3, 0x95, 0x74, 0x50, 0x1a, 0x53, 0x26, 0x83, 0x10, 0x9c,
+            0x2a, 0xba, 0xca, 0xba, 0x28, 0x3c, 0x31, 0xb4, 0xbd, 0x2f,
+            0x53, 0xc3, 0xee, 0x37, 0xe3, 0x52, 0xce, 0xe3, 0x4f, 0x9e,
+            0x50, 0x3b, 0xd8, 0x0c, 0x06, 0x22, 0xad, 0x79, 0xc6, 0xdc,
+            0xee, 0x88, 0x35, 0x47, 0xc6, 0xa3, 0xb3, 0x25 },
+        128,
+        (unsigned char[]){
+            0xb6, 0x9d, 0xca, 0x1c, 0xf7, 0xd4, 0xd7, 0xec, 0x81, 0xe7,
+            0x5b, 0x90, 0xfc, 0xca, 0x87, 0x4a, 0xbc, 0xde, 0x12, 0x3f,
+            0xd2, 0x70, 0x01, 0x80, 0xaa, 0x90, 0x47, 0x9b, 0x6e, 0x48,
+            0xde, 0x8d, 0x67, 0xed, 0x24, 0xf9, 0xf1, 0x9d, 0x85, 0xba,
+            0x27, 0x58, 0x74, 0xf5, 0x42, 0xcd, 0x20, 0xdc, 0x72, 0x3e,
+            0x69, 0x63, 0x36, 0x4a, 0x1f, 0x94, 0x25, 0x45, 0x2b, 0x26,
+            0x9a, 0x67, 0x99, 0xfd },
+        64,
+        (unsigned char[]){
+            0xe7, 0xe8, 0x94, 0x27, 0x20, 0xa8, 0x77, 0x51, 0x72, 0x73,
+            0xa3, 0x56, 0x05, 0x3e, 0xa2, 0xa1, 0xbc, 0x0c, 0x94, 0xaa,
+            0x72, 0xd5, 0x5c, 0x6e, 0x86, 0x29, 0x6b, 0x2d, 0xfc, 0x96,
+            0x79, 0x48, 0xc0, 0xa7, 0x2c, 0xbc, 0xcc, 0xa7, 0xea, 0xcb,
+            0x35, 0x70, 0x6e, 0x09, 0xa1, 0xdf, 0x55, 0xa1, 0x53, 0x5b,
+            0xd9, 0xb3, 0xcc, 0x34, 0x16, 0x0b, 0x3b, 0x6d, 0xcd, 0x3e,
+            0xda, 0x8e, 0x64, 0x43 },
+        64,
+    },
+    {
+        (unsigned char[]){
+            0xa5, 0x6e, 0x4a, 0x0e, 0x70, 0x10, 0x17, 0x58, 0x9a, 0x51,
+            0x87, 0xdc, 0x7e, 0xa8, 0x41, 0xd1, 0x56, 0xf2, 0xec, 0x0e,
+            0x36, 0xad, 0x52, 0xa4, 0x4d, 0xfe, 0xb1, 0xe6, 0x1f, 0x7a,
+            0xd9, 0x91, 0xd8, 0xc5, 0x10, 0x56, 0xff, 0xed, 0xb1, 0x62,
+            0xb4, 0xc0, 0xf2, 0x83, 0xa1, 0x2a, 0x88, 0xa3, 0x94, 0xdf,
+            0xf5, 0x26, 0xab, 0x72, 0x91, 0xcb, 0xb3, 0x07, 0xce, 0xab,
+            0xfc, 0xe0, 0xb1, 0xdf, 0xd5, 0xcd, 0x95, 0x08, 0x09, 0x6d,
+            0x5b, 0x2b, 0x8b, 0x6d, 0xf5, 0xd6, 0x71, 0xef, 0x63, 0x77,
+            0xc0, 0x92, 0x1c, 0xb2, 0x3c, 0x27, 0x0a, 0x70, 0xe2, 0x59,
+            0x8e, 0x6f, 0xf8, 0x9d, 0x19, 0xf1, 0x05, 0xac, 0xc2, 0xd3,
+            0xf0, 0xcb, 0x35, 0xf2, 0x92, 0x80, 0xe1, 0x38, 0x6b, 0x6f,
+            0x64, 0xc4, 0xef, 0x22, 0xe1, 0xe1, 0xf2, 0x0d, 0x0c, 0xe8,
+            0xcf, 0xfb, 0x22, 0x49, 0xbd, 0x9a, 0x21, 0x37 },
+        128,
+        (unsigned char[]){ 0x01, 0x00, 0x01 }, 3,
+        (unsigned char[]){
+            0x33, 0xa5, 0x04, 0x2a, 0x90, 0xb2, 0x7d, 0x4f, 0x54, 0x51,
+            0xca, 0x9b, 0xbb, 0xd0, 0xb4, 0x47, 0x71, 0xa1, 0x01, 0xaf,
+            0x88, 0x43, 0x40, 0xae, 0xf9, 0x88, 0x5f, 0x2a, 0x4b, 0xbe,
+            0x92, 0xe8, 0x94, 0xa7, 0x24, 0xac, 0x3c, 0x56, 0x8c, 0x8f,
+            0x97, 0x85, 0x3a, 0xd0, 0x7c, 0x02, 0x66, 0xc8, 0xc6, 0xa3,
+            0xca, 0x09, 0x29, 0xf1, 0xe8, 0xf1, 0x12, 0x31, 0x88, 0x44,
+            0x29, 0xfc, 0x4d, 0x9a, 0xe5, 0x5f, 0xee, 0x89, 0x6a, 0x10,
+            0xce, 0x70, 0x7c, 0x3e, 0xd7, 0xe7, 0x34, 0xe4, 0x47, 0x27,
+            0xa3, 0x95, 0x74, 0x50, 0x1a, 0x53, 0x26, 0x83, 0x10, 0x9c,
+            0x2a, 0xba, 0xca, 0xba, 0x28, 0x3c, 0x31, 0xb4, 0xbd, 0x2f,
+            0x53, 0xc3, 0xee, 0x37, 0xe3, 0x52, 0xce, 0xe3, 0x4f, 0x9e,
+            0x50, 0x3b, 0xd8, 0x0c, 0x06, 0x22, 0xad, 0x79, 0xc6, 0xdc,
+            0xee, 0x88, 0x35, 0x47, 0xc6, 0xa3, 0xb3, 0x25 },
+        128,
+        (unsigned char[]){
+            0xb6, 0x9d, 0xca, 0x1c, 0xf7, 0xd4, 0xd7, 0xec, 0x81, 0xe7,
+            0x5b, 0x90, 0xfc, 0xca, 0x87, 0x4a, 0xbc, 0xde, 0x12, 0x3f,
+            0xd2, 0x70, 0x01, 0x80, 0xaa, 0x90, 0x47, 0x9b, 0x6e, 0x48,
+            0xde, 0x8d, 0x67, 0xed, 0x24, 0xf9, 0xf1, 0x9d, 0x85, 0xba,
+            0x27, 0x58, 0x74, 0xf5, 0x42, 0xcd, 0x20, 0xdc, 0x72, 0x3e,
+            0x69, 0x63, 0x36, 0x4a, 0x1f, 0x94, 0x25, 0x45, 0x2b, 0x26,
+            0x9a, 0x67, 0x99, 0xfd },
+        64,
+        (unsigned char[]){
+            0xe7, 0xe8, 0x94, 0x27, 0x20, 0xa8, 0x77, 0x51, 0x72, 0x73,
+            0xa3, 0x56, 0x05, 0x3e, 0xa2, 0xa1, 0xbc, 0x0c, 0x94, 0xaa,
+            0x72, 0xd5, 0x5c, 0x6e, 0x86, 0x29, 0x6b, 0x2d, 0xfc, 0x96,
+            0x79, 0x48, 0xc0, 0xa7, 0x2c, 0xbc, 0xcc, 0xa7, 0xea, 0xcb,
+            0x35, 0x70, 0x6e, 0x09, 0xa1, 0xdf, 0x55, 0xa1, 0x53, 0x5b,
+            0xd9, 0xb3, 0xcc, 0x34, 0x16, 0x0b, 0x3b, 0x6d, 0xcd, 0x3e,
+            0xda, 0x8e, 0x64, 0x43 },
+        64,
+    },
+    {
+        (unsigned char[]){
+            0xa5, 0x6e, 0x4a, 0x0e, 0x70, 0x10, 0x17, 0x58, 0x9a, 0x51,
+            0x87, 0xdc, 0x7e, 0xa8, 0x41, 0xd1, 0x56, 0xf2, 0xec, 0x0e,
+            0x36, 0xad, 0x52, 0xa4, 0x4d, 0xfe, 0xb1, 0xe6, 0x1f, 0x7a,
+            0xd9, 0x91, 0xd8, 0xc5, 0x10, 0x56, 0xff, 0xed, 0xb1, 0x62,
+            0xb4, 0xc0, 0xf2, 0x83, 0xa1, 0x2a, 0x88, 0xa3, 0x94, 0xdf,
+            0xf5, 0x26, 0xab, 0x72, 0x91, 0xcb, 0xb3, 0x07, 0xce, 0xab,
+            0xfc, 0xe0, 0xb1, 0xdf, 0xd5, 0xcd, 0x95, 0x08, 0x09, 0x6d,
+            0x5b, 0x2b, 0x8b, 0x6d, 0xf5, 0xd6, 0x71, 0xef, 0x63, 0x77,
+            0xc0, 0x92, 0x1c, 0xb2, 0x3c, 0x27, 0x0a, 0x70, 0xe2, 0x59,
+            0x8e, 0x6f, 0xf8, 0x9d, 0x19, 0xf1, 0x05, 0xac, 0xc2, 0xd3,
+            0xf0, 0xcb, 0x35, 0xf2, 0x92, 0x80, 0xe1, 0x38, 0x6b, 0x6f,
+            0x64, 0xc4, 0xef, 0x22, 0xe1, 0xe1, 0xf2, 0x0d, 0x0c, 0xe8,
+            0xcf, 0xfb, 0x22, 0x49, 0xbd, 0x9a, 0x21, 0x37 },
+        128,
+        (unsigned char[]){ 0x01, 0x00, 0x01 }, 3,
+        (unsigned char[]){
+            0x33, 0xa5, 0x04, 0x2a, 0x90, 0xb2, 0x7d, 0x4f, 0x54, 0x51,
+            0xca, 0x9b, 0xbb, 0xd0, 0xb4, 0x47, 0x71, 0xa1, 0x01, 0xaf,
+            0x88, 0x43, 0x40, 0xae, 0xf9, 0x88,
+            0x5f, 0x2a, 0x4b, 0xbe, 0x92, 0xe8, 0x94, 0xa7, 0x24, 0xac,
+
+            0x3c, 0x56, 0x8c, 0x8f, 0x97, 0x85, 0x3a, 0xd0, 0x7c, 0x02,
+
+            0x66, 0xc8, 0xc6, 0xa3, 0xca, 0x09, 0x29, 0xf1, 0xe8, 0xf1,
+            0x12, 0x31, 0x88, 0x44, 0x29, 0xfc, 0x4d, 0x9a, 0xe5, 0x5f,
+            0xee, 0x89, 0x6a, 0x10, 0xce, 0x70, 0x7c, 0x3e, 0xd7, 0xe7,
+            0x34, 0xe4, 0x47, 0x27, 0xa3, 0x95, 0x74, 0x50, 0x1a, 0x53,
+            0x26, 0x83, 0x10, 0x9c, 0x2a, 0xba, 0xca, 0xba, 0x28, 0x3c,
+            0x31, 0xb4, 0xbd, 0x2f, 0x53, 0xc3, 0xee, 0x37, 0xe3, 0x52,
+            0xce, 0xe3, 0x4f, 0x9e, 0x50, 0x3b, 0xd8, 0x0c, 0x06, 0x22,
+            0xad, 0x79, 0xc6, 0xdc, 0xee, 0x88, 0x35, 0x47, 0xc6, 0xa3,
+            0xb3, 0x25 },
+        128,
+        (unsigned char[]){
+            0xb6, 0x9d, 0xca, 0x1c, 0xf7, 0xd4, 0xd7, 0xec, 0x81, 0xe7,
+            0x5b, 0x90, 0xfc, 0xca, 0x87, 0x4a, 0xbc, 0xde, 0x12, 0x3f,
+            0xd2, 0x70, 0x01, 0x80, 0xaa, 0x90, 0x47, 0x9b, 0x6e, 0x48,
+            0xde, 0x8d, 0x67, 0xed, 0x24, 0xf9, 0xf1, 0x9d, 0x85, 0xba,
+            0x27, 0x58, 0x74, 0xf5, 0x42, 0xcd, 0x20, 0xdc, 0x72, 0x3e,
+            0x69, 0x63, 0x36, 0x4a, 0x1f, 0x94, 0x25, 0x45, 0x2b, 0x26,
+            0x9a, 0x67, 0x99, 0xfd },
+        64,
+        (unsigned char[]){
+            0xe7, 0xe8, 0x94, 0x27, 0x20, 0xa8, 0x77, 0x51, 0x72, 0x73,
+            0xa3, 0x56, 0x05, 0x3e, 0xa2, 0xa1, 0xbc, 0x0c, 0x94, 0xaa,
+            0x72, 0xd5, 0x5c, 0x6e, 0x86, 0x29, 0x6b, 0x2d, 0xfc, 0x96,
+            0x79, 0x48, 0xc0, 0xa7, 0x2c, 0xbc, 0xcc, 0xa7, 0xea, 0xcb,
+            0x35, 0x70, 0x6e, 0x09, 0xa1, 0xdf, 0x55, 0xa1, 0x53, 0x5b,
+            0xd9, 0xb3, 0xcc, 0x34, 0x16, 0x0b, 0x3b, 0x6d, 0xcd, 0x3e,
+            0xda, 0x8e, 0x64, 0x43 },
+        64,
+    },
+    {
+        (unsigned char[]){
+            0xa5, 0x6e, 0x4a, 0x0e, 0x70, 0x10, 0x17, 0x58, 0x9a, 0x51,
+            0x87, 0xdc, 0x7e, 0xa8, 0x41, 0xd1, 0x56, 0xf2, 0xec, 0x0e,
+            0x36, 0xad, 0x52, 0xa4, 0x4d, 0xfe, 0xb1, 0xe6, 0x1f, 0x7a,
+            0xd9, 0x91, 0xd8, 0xc5, 0x10, 0x56, 0xff, 0xed, 0xb1, 0x62,
+            0xb4, 0xc0, 0xf2, 0x83, 0xa1, 0x2a, 0x88, 0xa3, 0x94, 0xdf,
+            0xf5, 0x26, 0xab, 0x72, 0x91, 0xcb, 0xb3, 0x07, 0xce, 0xab,
+            0xfc, 0xe0, 0xb1, 0xdf, 0xd5, 0xcd, 0x95, 0x08, 0x09, 0x6d,
+            0x5b, 0x2b, 0x8b, 0x6d, 0xf5, 0xd6, 0x71, 0xef, 0x63, 0x77,
+            0xc0, 0x92, 0x1c, 0xb2, 0x3c, 0x27, 0x0a, 0x70, 0xe2, 0x59,
+            0x8e, 0x6f, 0xf8, 0x9d, 0x19, 0xf1, 0x05, 0xac, 0xc2, 0xd3,
+            0xf0, 0xcb, 0x35, 0xf2, 0x92, 0x80, 0xe1, 0x38, 0x6b, 0x6f,
+            0x64, 0xc4, 0xef, 0x22, 0xe1, 0xe1, 0xf2, 0x0d, 0x0c, 0xe8,
+            0xcf, 0xfb, 0x22, 0x49, 0xbd, 0x9a, 0x21, 0x37 },
+        128,
+        (unsigned char[]){ 0x01, 0x00, 0x01 }, 3,
+        (unsigned char[]){
+            0x33, 0xa5, 0x04, 0x2a, 0x90, 0xb2, 0x7d, 0x4f, 0x54, 0x51,
+            0xca, 0x9b, 0xbb, 0xd0, 0xb4, 0x47, 0x71, 0xa1, 0x01, 0xaf,
+            0x88, 0x43, 0x40, 0xae, 0xf9, 0x88, 0x5f, 0x2a, 0x4b, 0xbe,
+            0x92, 0xe8, 0x94, 0xa7, 0x24, 0xac, 0x3c, 0x56, 0x8c, 0x8f,
+            0x97, 0x85, 0x3a, 0xd0, 0x7c, 0x02, 0x66, 0xc8, 0xc6, 0xa3,
+            0xca, 0x09, 0x29, 0xf1, 0xe8, 0xf1, 0x12, 0x31, 0x88, 0x44,
+            0x29, 0xfc, 0x4d, 0x9a, 0xe5, 0x5f, 0xee, 0x89, 0x6a, 0x10,
+            0xce, 0x70, 0x7c, 0x3e, 0xd7, 0xe7, 0x34, 0xe4, 0x47, 0x27,
+            0xa3, 0x95, 0x74, 0x50, 0x1a, 0x53, 0x26, 0x83, 0x10, 0x9c,
+            0x2a, 0xba, 0xca, 0xba, 0x28, 0x3c, 0x31, 0xb4, 0xbd, 0x2f,
+            0x53, 0xc3, 0xee, 0x37, 0xe3, 0x52, 0xce, 0xe3, 0x4f, 0x9e,
+            0x50, 0x3b, 0xd8, 0x0c, 0x06, 0x22, 0xad, 0x79, 0xc6, 0xdc,
+            0xee, 0x88, 0x35, 0x47, 0xc6, 0xa3, 0xb3, 0x25 },
+        128,
+        (unsigned char[]){
+            0xb6, 0x9d, 0xca, 0x1c, 0xf7, 0xd4, 0xd7, 0xec, 0x81, 0xe7,
+            0x5b, 0x90, 0xfc, 0xca, 0x87, 0x4a, 0xbc, 0xde, 0x12, 0x3f,
+            0xd2, 0x70, 0x01, 0x80, 0xaa, 0x90, 0x47, 0x9b, 0x6e, 0x48,
+            0xde, 0x8d, 0x67, 0xed, 0x24, 0xf9, 0xf1, 0x9d, 0x85, 0xba,
+            0x27, 0x58, 0x74, 0xf5, 0x42, 0xcd, 0x20, 0xdc, 0x72, 0x3e,
+            0x69, 0x63, 0x36, 0x4a, 0x1f, 0x94, 0x25, 0x45, 0x2b, 0x26,
+            0x9a, 0x67, 0x99, 0xfd },
+        64,
+        (unsigned char[]){
+            0xe7, 0xe8, 0x94, 0x27, 0x20, 0xa8, 0x77, 0x51, 0x72, 0x73,
+            0xa3, 0x56, 0x05, 0x3e, 0xa2, 0xa1, 0xbc, 0x0c, 0x94, 0xaa,
+            0x72, 0xd5, 0x5c, 0x6e, 0x86, 0x29, 0x6b, 0x2d, 0xfc, 0x96,
+            0x79, 0x48, 0xc0, 0xa7, 0x2c, 0xbc, 0xcc, 0xa7, 0xea, 0xcb,
+            0x35, 0x70, 0x6e, 0x09, 0xa1, 0xdf, 0x55, 0xa1, 0x53, 0x5b,
+            0xd9, 0xb3, 0xcc, 0x34, 0x16, 0x0b, 0x3b, 0x6d, 0xcd, 0x3e,
+            0xda, 0x8e, 0x64, 0x43 },
+        64,
+    },
+    {
+        (unsigned char[]){
+            0xa5, 0x6e, 0x4a, 0x0e, 0x70, 0x10, 0x17, 0x58, 0x9a, 0x51,
+            0x87, 0xdc, 0x7e, 0xa8, 0x41, 0xd1, 0x56, 0xf2, 0xec, 0x0e,
+            0x36, 0xad, 0x52, 0xa4, 0x4d, 0xfe, 0xb1, 0xe6, 0x1f, 0x7a,
+            0xd9, 0x91, 0xd8, 0xc5, 0x10, 0x56, 0xff, 0xed, 0xb1, 0x62,
+            0xb4, 0xc0, 0xf2, 0x83, 0xa1, 0x2a, 0x88, 0xa3, 0x94, 0xdf,
+            0xf5, 0x26, 0xab, 0x72, 0x91, 0xcb, 0xb3, 0x07, 0xce, 0xab,
+            0xfc, 0xe0, 0xb1, 0xdf, 0xd5, 0xcd, 0x95, 0x08, 0x09, 0x6d,
+            0x5b, 0x2b, 0x8b, 0x6d, 0xf5, 0xd6, 0x71, 0xef, 0x63, 0x77,
+            0xc0, 0x92, 0x1c, 0xb2, 0x3c, 0x27, 0x0a, 0x70, 0xe2, 0x59,
+            0x8e, 0x6f, 0xf8, 0x9d, 0x19, 0xf1, 0x05, 0xac, 0xc2, 0xd3,
+            0xf0, 0xcb, 0x35, 0xf2, 0x92, 0x80, 0xe1, 0x38, 0x6b, 0x6f,
+            0x64, 0xc4, 0xef, 0x22, 0xe1, 0xe1, 0xf2, 0x0d, 0x0c, 0xe8,
+            0xcf, 0xfb, 0x22, 0x49, 0xbd, 0x9a, 0x21, 0x37 },
+        128,
+        (unsigned char[]){ 0x01, 0x00, 0x01 }, 3,
+        (unsigned char[]){
+            0x33, 0xa5, 0x04, 0x2a, 0x90, 0xb2, 0x7d, 0x4f, 0x54, 0x51,
+            0xca, 0x9b, 0xbb, 0xd0, 0xb4, 0x47, 0x71, 0xa1, 0x01, 0xaf,
+            0x88, 0x43, 0x40, 0xae, 0xf9, 0x88, 0x5f, 0x2a, 0x4b, 0xbe,
+            0x92, 0xe8, 0x94, 0xa7, 0x24, 0xac, 0x3c, 0x56, 0x8c, 0x8f,
+            0x97, 0x85, 0x3a, 0xd0, 0x7c, 0x02, 0x66, 0xc8, 0xc6, 0xa3,
+            0xca, 0x09, 0x29, 0xf1, 0xe8, 0xf1, 0x12, 0x31, 0x88, 0x44,
+            0x29, 0xfc, 0x4d, 0x9a, 0xe5, 0x5f, 0xee, 0x89, 0x6a, 0x10,
+            0xce, 0x70, 0x7c, 0x3e, 0xd7, 0xe7, 0x34, 0xe4, 0x47, 0x27,
+            0xa3, 0x95, 0x74, 0x50, 0x1a, 0x53, 0x26, 0x83, 0x10, 0x9c,
+            0x2a, 0xba, 0xca, 0xba, 0x28, 0x3c, 0x31, 0xb4, 0xbd, 0x2f,
+            0x53, 0xc3, 0xee, 0x37, 0xe3, 0x52, 0xce, 0xe3, 0x4f, 0x9e,
+            0x50, 0x3b, 0xd8, 0x0c, 0x06, 0x22, 0xad, 0x79, 0xc6, 0xdc,
+            0xee, 0x88, 0x35, 0x47, 0xc6, 0xa3, 0xb3, 0x25 },
+        128,
+        (unsigned char[]){
+            0xb6, 0x9d, 0xca, 0x1c, 0xf7, 0xd4, 0xd7, 0xec, 0x81, 0xe7,
+            0x5b, 0x90, 0xfc, 0xca, 0x87, 0x4a, 0xbc, 0xde, 0x12, 0x3f,
+            0xd2, 0x70, 0x01, 0x80, 0xaa, 0x90, 0x47, 0x9b, 0x6e, 0x48,
+            0xde, 0x8d, 0x67, 0xed, 0x24, 0xf9, 0xf1, 0x9d, 0x85, 0xba,
+            0x27, 0x58, 0x74, 0xf5, 0x42, 0xcd, 0x20, 0xdc, 0x72, 0x3e,
+            0x69, 0x63, 0x36, 0x4a, 0x1f, 0x94, 0x25, 0x45, 0x2b, 0x26,
+            0x9a, 0x67, 0x99, 0xfd },
+        64,
+        (unsigned char[]){
+            0xe7, 0xe8, 0x94, 0x27, 0x20, 0xa8, 0x77, 0x51, 0x72, 0x73,
+            0xa3, 0x56, 0x05, 0x3e, 0xa2, 0xa1, 0xbc, 0x0c, 0x94, 0xaa,
+            0x72, 0xd5, 0x5c, 0x6e, 0x86, 0x29, 0x6b, 0x2d, 0xfc, 0x96,
+            0x79, 0x48, 0xc0, 0xa7, 0x2c, 0xbc, 0xcc, 0xa7, 0xea, 0xcb,
+            0x35, 0x70, 0x6e, 0x09, 0xa1, 0xdf, 0x55, 0xa1, 0x53, 0x5b,
+            0xd9, 0xb3, 0xcc, 0x34, 0x16, 0x0b, 0x3b, 0x6d, 0xcd, 0x3e,
+            0xda, 0x8e, 0x64, 0x43 },
+        64,
+    },
+    {
+        (unsigned char[]){
+            0xa5, 0x6e, 0x4a, 0x0e, 0x70, 0x10, 0x17, 0x58, 0x9a, 0x51,
+            0x87, 0xdc, 0x7e, 0xa8, 0x41, 0xd1, 0x56, 0xf2, 0xec, 0x0e,
+            0x36, 0xad, 0x52, 0xa4, 0x4d, 0xfe, 0xb1, 0xe6, 0x1f, 0x7a,
+            0xd9, 0x91, 0xd8, 0xc5, 0x10, 0x56, 0xff, 0xed, 0xb1, 0x62,
+            0xb4, 0xc0, 0xf2, 0x83, 0xa1, 0x2a, 0x88, 0xa3, 0x94, 0xdf,
+            0xf5, 0x26, 0xab, 0x72, 0x91, 0xcb, 0xb3, 0x07, 0xce, 0xab,
+            0xfc, 0xe0, 0xb1, 0xdf, 0xd5, 0xcd, 0x95, 0x08, 0x09, 0x6d,
+            0x5b, 0x2b, 0x8b, 0x6d, 0xf5, 0xd6, 0x71, 0xef, 0x63, 0x77,
+            0xc0, 0x92, 0x1c, 0xb2, 0x3c, 0x27, 0x0a, 0x70, 0xe2, 0x59,
+            0x8e, 0x6f, 0xf8, 0x9d, 0x19, 0xf1, 0x05, 0xac, 0xc2, 0xd3,
+            0xf0, 0xcb, 0x35, 0xf2, 0x92, 0x80, 0xe1, 0x38, 0x6b, 0x6f,
+            0x64, 0xc4, 0xef, 0x22, 0xe1, 0xe1, 0xf2, 0x0d, 0x0c, 0xe8,
+            0xcf, 0xfb, 0x22, 0x49, 0xbd, 0x9a, 0x21, 0x37 },
+        128,
+        (unsigned char[]){ 0x01, 0x00, 0x01 }, 3,
+        (unsigned char[]){
+            0x33, 0xa5, 0x04, 0x2a, 0x90, 0xb2, 0x7d, 0x4f, 0x54, 0x51,
+            0xca, 0x9b, 0xbb, 0xd0, 0xb4, 0x47, 0x71, 0xa1, 0x01, 0xaf,
+            0x88, 0x43, 0x40, 0xae, 0xf9, 0x88, 0x5f, 0x2a, 0x4b, 0xbe,
+            0x92, 0xe8, 0x94, 0xa7, 0x24, 0xac, 0x3c, 0x56, 0x8c, 0x8f,
+            0x97, 0x85, 0x3a, 0xd0, 0x7c, 0x02, 0x66, 0xc8, 0xc6, 0xa3,
+            0xca, 0x09, 0x29, 0xf1, 0xe8, 0xf1, 0x12, 0x31, 0x88, 0x44,
+            0x29, 0xfc, 0x4d, 0x9a, 0xe5, 0x5f, 0xee, 0x89, 0x6a, 0x10,
+            0xce, 0x70, 0x7c, 0x3e, 0xd7, 0xe7, 0x34, 0xe4, 0x47, 0x27,
+            0xa3, 0x95, 0x74, 0x50, 0x1a, 0x53, 0x26, 0x83, 0x10, 0x9c,
+            0x2a, 0xba, 0xca, 0xba, 0x28, 0x3c, 0x31, 0xb4, 0xbd, 0x2f,
+            0x53, 0xc3, 0xee, 0x37, 0xe3, 0x52, 0xce, 0xe3, 0x4f, 0x9e,
+            0x50, 0x3b, 0xd8, 0x0c, 0x06, 0x22, 0xad, 0x79, 0xc6, 0xdc,
+            0xee, 0x88, 0x35, 0x47, 0xc6, 0xa3, 0xb3, 0x25 },
+        128,
+        (unsigned char[]){
+            0xb6, 0x9d, 0xca, 0x1c, 0xf7, 0xd4, 0xd7, 0xec, 0x81, 0xe7,
+            0x5b, 0x90, 0xfc, 0xca, 0x87, 0x4a, 0xbc, 0xde, 0x12, 0x3f,
+            0xd2, 0x70, 0x01, 0x80, 0xaa, 0x90, 0x47, 0x9b, 0x6e, 0x48,
+            0xde, 0x8d, 0x67, 0xed, 0x24, 0xf9, 0xf1, 0x9d, 0x85, 0xba,
+            0x27, 0x58, 0x74, 0xf5, 0x42, 0xcd, 0x20, 0xdc, 0x72, 0x3e,
+            0x69, 0x63, 0x36, 0x4a, 0x1f, 0x94, 0x25, 0x45, 0x2b, 0x26,
+            0x9a, 0x67, 0x99, 0xfd },
+        64,
+        (unsigned char[]){
+            0xe7, 0xe8, 0x94, 0x27, 0x20, 0xa8, 0x77, 0x51, 0x72, 0x73,
+            0xa3, 0x56, 0x05, 0x3e, 0xa2, 0xa1, 0xbc, 0x0c, 0x94, 0xaa,
+            0x72, 0xd5, 0x5c, 0x6e, 0x86, 0x29, 0x6b, 0x2d, 0xfc, 0x96,
+            0x79, 0x48, 0xc0, 0xa7, 0x2c, 0xbc, 0xcc, 0xa7, 0xea, 0xcb,
+            0x35, 0x70, 0x6e, 0x09, 0xa1, 0xdf, 0x55, 0xa1, 0x53, 0x5b,
+            0xd9, 0xb3, 0xcc, 0x34, 0x16, 0x0b, 0x3b, 0x6d, 0xcd, 0x3e,
+            0xda, 0x8e, 0x64, 0x43 },
+        64,
+    },
+    {
+        (unsigned char[]){
+            0xa5, 0x6e, 0x4a, 0x0e, 0x70, 0x10, 0x17, 0x58, 0x9a, 0x51,
+            0x87, 0xdc, 0x7e, 0xa8, 0x41, 0xd1, 0x56, 0xf2, 0xec, 0x0e,
+            0x36, 0xad, 0x52, 0xa4, 0x4d, 0xfe, 0xb1, 0xe6, 0x1f, 0x7a,
+            0xd9, 0x91, 0xd8, 0xc5, 0x10, 0x56, 0xff, 0xed, 0xb1, 0x62,
+            0xb4, 0xc0, 0xf2, 0x83, 0xa1, 0x2a, 0x88, 0xa3, 0x94, 0xdf,
+            0xf5, 0x26, 0xab, 0x72, 0x91, 0xcb, 0xb3, 0x07, 0xce, 0xab,
+            0xfc, 0xe0, 0xb1, 0xdf, 0xd5, 0xcd, 0x95, 0x08, 0x09, 0x6d,
+            0x5b, 0x2b, 0x8b, 0x6d, 0xf5, 0xd6, 0x71, 0xef, 0x63, 0x77,
+            0xc0, 0x92, 0x1c, 0xb2, 0x3c, 0x27, 0x0a, 0x70, 0xe2, 0x59,
+            0x8e, 0x6f, 0xf8, 0x9d, 0x19, 0xf1, 0x05, 0xac, 0xc2, 0xd3,
+            0xf0, 0xcb, 0x35, 0xf2, 0x92, 0x80, 0xe1, 0x38, 0x6b, 0x6f,
+            0x64, 0xc4, 0xef, 0x22, 0xe1, 0xe1, 0xf2, 0x0d, 0x0c, 0xe8,
+            0xcf, 0xfb, 0x22, 0x49, 0xbd, 0x9a, 0x21, 0x37 },
+        128,
+        (unsigned char[]){ 0x01, 0x00, 0x01 }, 3,
+        (unsigned char[]){
+            0x33, 0xa5, 0x04, 0x2a, 0x90, 0xb2, 0x7d, 0x4f, 0x54, 0x51,
+            0xca, 0x9b, 0xbb, 0xd0, 0xb4, 0x47, 0x71, 0xa1, 0x01, 0xaf,
+            0x88, 0x43, 0x40, 0xae, 0xf9, 0x88, 0x5f, 0x2a, 0x4b, 0xbe,
+            0x92, 0xe8, 0x94, 0xa7, 0x24, 0xac, 0x3c, 0x56, 0x8c, 0x8f,
+            0x97, 0x85, 0x3a, 0xd0, 0x7c, 0x02, 0x66, 0xc8, 0xc6, 0xa3,
+            0xca, 0x09, 0x29, 0xf1, 0xe8, 0xf1, 0x12, 0x31, 0x88, 0x44,
+            0x29, 0xfc, 0x4d, 0x9a, 0xe5, 0x5f, 0xee, 0x89, 0x6a, 0x10,
+            0xce, 0x70, 0x7c, 0x3e, 0xd7, 0xe7, 0x34, 0xe4, 0x47, 0x27,
+            0xa3, 0x95, 0x74, 0x50, 0x1a, 0x53, 0x26, 0x83, 0x10, 0x9c,
+            0x2a, 0xba, 0xca, 0xba, 0x28, 0x3c, 0x31, 0xb4, 0xbd, 0x2f,
+            0x53, 0xc3, 0xee, 0x37, 0xe3, 0x52, 0xce, 0xe3, 0x4f, 0x9e,
+            0x50, 0x3b, 0xd8, 0x0c, 0x06, 0x22, 0xad, 0x79, 0xc6, 0xdc,
+            0xee, 0x88, 0x35, 0x47, 0xc6, 0xa3, 0xb3, 0x25 },
+        128,
+        (unsigned char[]){
+            0xb6, 0x9d, 0xca, 0x1c, 0xf7, 0xd4, 0xd7, 0xec, 0x81, 0xe7,
+            0x5b, 0x90, 0xfc, 0xca, 0x87, 0x4a, 0xbc, 0xde, 0x12, 0x3f,
+            0xd2, 0x70, 0x01, 0x80, 0xaa, 0x90, 0x47, 0x9b, 0x6e, 0x48,
+            0xde, 0x8d, 0x67, 0xed, 0x24, 0xf9, 0xf1, 0x9d, 0x85, 0xba,
+            0x27, 0x58, 0x74, 0xf5, 0x42, 0xcd, 0x20, 0xdc, 0x72, 0x3e,
+            0x69, 0x63, 0x36, 0x4a, 0x1f, 0x94, 0x25, 0x45, 0x2b, 0x26,
+            0x9a, 0x67, 0x99, 0xfd },
+        64,
+        (unsigned char[]){
+            0xe7, 0xe8, 0x94, 0x27, 0x20, 0xa8, 0x77, 0x51, 0x72, 0x73,
+            0xa3, 0x56, 0x05, 0x3e, 0xa2, 0xa1, 0xbc, 0x0c, 0x94, 0xaa,
+            0x72, 0xd5, 0x5c, 0x6e, 0x86, 0x29, 0x6b, 0x2d, 0xfc, 0x96,
+            0x79, 0x48, 0xc0, 0xa7, 0x2c, 0xbc, 0xcc, 0xa7, 0xea, 0xcb,
+            0x35, 0x70, 0x6e, 0x09, 0xa1, 0xdf, 0x55, 0xa1, 0x53, 0x5b,
+            0xd9, 0xb3, 0xcc, 0x34, 0x16, 0x0b, 0x3b, 0x6d, 0xcd, 0x3e,
+            0xda, 0x8e, 0x64, 0x43 },
+        64,
+    },
+    {
+        (unsigned char[]){
+            0xa5, 0x6e, 0x4a, 0x0e, 0x70, 0x10, 0x17, 0x58, 0x9a, 0x51,
+            0x87, 0xdc, 0x7e, 0xa8, 0x41, 0xd1, 0x56, 0xf2, 0xec, 0x0e,
+            0x36, 0xad, 0x52, 0xa4, 0x4d, 0xfe, 0xb1, 0xe6, 0x1f, 0x7a,
+            0xd9, 0x91, 0xd8, 0xc5, 0x10, 0x56, 0xff, 0xed, 0xb1, 0x62,
+            0xb4, 0xc0, 0xf2, 0x83, 0xa1, 0x2a, 0x88, 0xa3, 0x94, 0xdf,
+            0xf5, 0x26, 0xab, 0x72, 0x91, 0xcb, 0xb3, 0x07, 0xce, 0xab,
+            0xfc, 0xe0, 0xb1, 0xdf, 0xd5, 0xcd, 0x95, 0x08, 0x09, 0x6d,
+            0x5b, 0x2b, 0x8b, 0x6d, 0xf5, 0xd6, 0x71, 0xef, 0x63, 0x77,
+            0xc0, 0x92, 0x1c, 0xb2, 0x3c, 0x27, 0x0a, 0x70, 0xe2, 0x59,
+            0x8e, 0x6f, 0xf8, 0x9d, 0x19, 0xf1, 0x05, 0xac, 0xc2, 0xd3,
+            0xf0, 0xcb, 0x35, 0xf2, 0x92, 0x80, 0xe1, 0x38, 0x6b, 0x6f,
+            0x64, 0xc4, 0xef, 0x22, 0xe1, 0xe1, 0xf2, 0x0d, 0x0c, 0xe8,
+            0xcf, 0xfb, 0x22, 0x49, 0xbd, 0x9a, 0x21, 0x37 },
+        128,
+        (unsigned char[]){ 0x01, 0x00, 0x01 }, 3,
+        (unsigned char[]){
+            0x33, 0xa5, 0x04, 0x2a, 0x90, 0xb2, 0x7d, 0x4f, 0x54, 0x51,
+            0xca, 0x9b, 0xbb, 0xd0, 0xb4, 0x47, 0x71, 0xa1, 0x01, 0xaf,
+            0x88, 0x43, 0x40, 0xae, 0xf9, 0x88, 0x5f, 0x2a, 0x4b, 0xbe,
+            0x92, 0xe8, 0x94, 0xa7, 0x24, 0xac, 0x3c, 0x56, 0x8c, 0x8f,
+            0x97, 0x85, 0x3a, 0xd0, 0x7c, 0x02, 0x66, 0xc8, 0xc6, 0xa3,
+            0xca, 0x09, 0x29, 0xf1, 0xe8, 0xf1, 0x12, 0x31, 0x88, 0x44,
+            0x29, 0xfc, 0x4d, 0x9a, 0xe5, 0x5f, 0xee, 0x89, 0x6a, 0x10,
+            0xce, 0x70, 0x7c, 0x3e, 0xd7, 0xe7, 0x34, 0xe4, 0x47, 0x27,
+            0xa3, 0x95, 0x74, 0x50, 0x1a, 0x53, 0x26, 0x83, 0x10, 0x9c,
+            0x2a, 0xba, 0xca, 0xba, 0x28, 0x3c, 0x31, 0xb4, 0xbd, 0x2f,
+            0x53, 0xc3, 0xee, 0x37, 0xe3, 0x52, 0xce, 0xe3, 0x4f, 0x9e,
+            0x50, 0x3b, 0xd8, 0x0c, 0x06, 0x22, 0xad, 0x79, 0xc6, 0xdc,
+            0xee, 0x88, 0x35, 0x47, 0xc6, 0xa3, 0xb3, 0x25 },
+        128,
+        (unsigned char[]){
+            0xb6, 0x9d, 0xca, 0x1c, 0xf7, 0xd4, 0xd7, 0xec, 0x81, 0xe7,
+            0x5b, 0x90, 0xfc, 0xca, 0x87, 0x4a, 0xbc, 0xde, 0x12, 0x3f,
+            0xd2, 0x70, 0x01, 0x80, 0xaa, 0x90, 0x47, 0x9b, 0x6e, 0x48,
+            0xde, 0x8d, 0x67, 0xed, 0x24, 0xf9, 0xf1, 0x9d, 0x85, 0xba,
+            0x27, 0x58, 0x74, 0xf5, 0x42, 0xcd, 0x20, 0xdc, 0x72, 0x3e,
+            0x69, 0x63, 0x36, 0x4a, 0x1f, 0x94, 0x25, 0x45, 0x2b, 0x26,
+            0x9a, 0x67, 0x99, 0xfd },
+        64,
+        (unsigned char[]){
+            0xe7, 0xe8, 0x94, 0x27, 0x20, 0xa8, 0x77, 0x51, 0x72, 0x73,
+            0xa3, 0x56, 0x05, 0x3e, 0xa2, 0xa1, 0xbc, 0x0c, 0x94, 0xaa,
+            0x72, 0xd5, 0x5c, 0x6e, 0x86, 0x29, 0x6b, 0x2d, 0xfc, 0x96,
+            0x79, 0x48, 0xc0, 0xa7, 0x2c, 0xbc, 0xcc, 0xa7, 0xea, 0xcb,
+            0x35, 0x70, 0x6e, 0x09, 0xa1, 0xdf, 0x55, 0xa1, 0x53, 0x5b,
+            0xd9, 0xb3, 0xcc, 0x34, 0x16, 0x0b, 0x3b, 0x6d, 0xcd, 0x3e,
+            0xda, 0x8e, 0x64, 0x43 },
+        64,
+    },
+    {
+        (unsigned char[]){
+            0xa5, 0x6e, 0x4a, 0x0e, 0x70, 0x10, 0x17, 0x58, 0x9a, 0x51,
+            0x87, 0xdc, 0x7e, 0xa8, 0x41, 0xd1, 0x56, 0xf2, 0xec, 0x0e,
+            0x36, 0xad, 0x52, 0xa4, 0x4d, 0xfe, 0xb1, 0xe6, 0x1f, 0x7a,
+            0xd9, 0x91, 0xd8, 0xc5, 0x10, 0x56, 0xff, 0xed, 0xb1, 0x62,
+            0xb4, 0xc0, 0xf2, 0x83, 0xa1, 0x2a, 0x88, 0xa3, 0x94, 0xdf,
+            0xf5, 0x26, 0xab, 0x72, 0x91, 0xcb, 0xb3, 0x07, 0xce, 0xab,
+            0xfc, 0xe0, 0xb1, 0xdf, 0xd5, 0xcd, 0x95, 0x08, 0x09, 0x6d,
+            0x5b, 0x2b, 0x8b, 0x6d, 0xf5, 0xd6, 0x71, 0xef, 0x63, 0x77,
+            0xc0, 0x92, 0x1c, 0xb2, 0x3c, 0x27, 0x0a, 0x70, 0xe2, 0x59,
+            0x8e, 0x6f, 0xf8, 0x9d, 0x19, 0xf1, 0x05, 0xac, 0xc2, 0xd3,
+            0xf0, 0xcb, 0x35, 0xf2, 0x92, 0x80, 0xe1, 0x38, 0x6b, 0x6f,
+            0x64, 0xc4, 0xef, 0x22, 0xe1, 0xe1, 0xf2, 0x0d, 0x0c, 0xe8,
+            0xcf, 0xfb, 0x22, 0x49, 0xbd, 0x9a, 0x21, 0x37 },
+        128,
+        (unsigned char[]){ 0x01, 0x00, 0x01 }, 3,
+        (unsigned char[]){
+            0x33, 0xa5, 0x04, 0x2a, 0x90, 0xb2, 0x7d, 0x4f, 0x54, 0x51,
+            0xca, 0x9b, 0xbb, 0xd0, 0xb4, 0x47, 0x71, 0xa1, 0x01, 0xaf,
+            0x88, 0x43, 0x40, 0xae, 0xf9, 0x88, 0x5f, 0x2a, 0x4b, 0xbe,
+            0x92, 0xe8, 0x94, 0xa7, 0x24, 0xac, 0x3c, 0x56, 0x8c, 0x8f,
+            0x97, 0x85, 0x3a, 0xd0, 0x7c, 0x02, 0x66, 0xc8, 0xc6, 0xa3,
+            0xca, 0x09, 0x29, 0xf1, 0xe8, 0xf1, 0x12, 0x31, 0x88, 0x44,
+            0x29, 0xfc, 0x4d, 0x9a, 0xe5, 0x5f, 0xee, 0x89, 0x6a, 0x10,
+            0xce, 0x70, 0x7c, 0x3e, 0xd7, 0xe7, 0x34, 0xe4, 0x47, 0x27,
+            0xa3, 0x95, 0x74, 0x50, 0x1a, 0x53, 0x26, 0x83, 0x10, 0x9c,
+            0x2a, 0xba, 0xca, 0xba, 0x28, 0x3c, 0x31, 0xb4, 0xbd, 0x2f,
+            0x53, 0xc3, 0xee, 0x37, 0xe3, 0x52, 0xce, 0xe3, 0x4f, 0x9e,
+            0x50, 0x3b, 0xd8, 0x0c, 0x06, 0x22, 0xad, 0x79, 0xc6, 0xdc,
+            0xee, 0x88, 0x35, 0x47, 0xc6, 0xa3, 0xb3, 0x25 },
+        128,
+        (unsigned char[]){
+            0xb6, 0x9d, 0xca, 0x1c, 0xf7, 0xd4, 0xd7, 0xec, 0x81, 0xe7,
+            0x5b, 0x90, 0xfc, 0xca, 0x87, 0x4a, 0xbc, 0xde, 0x12, 0x3f,
+            0xd2, 0x70, 0x01, 0x80, 0xaa, 0x90, 0x47, 0x9b, 0x6e, 0x48,
+            0xde, 0x8d, 0x67, 0xed, 0x24, 0xf9, 0xf1, 0x9d, 0x85, 0xba,
+            0x27, 0x58, 0x74, 0xf5, 0x42, 0xcd, 0x20, 0xdc, 0x72, 0x3e,
+            0x69, 0x63, 0x36, 0x4a, 0x1f, 0x94, 0x25, 0x45, 0x2b, 0x26,
+            0x9a, 0x67, 0x99, 0xfd },
+        64,
+        (unsigned char[]){
+            0xe7, 0xe8, 0x94, 0x27, 0x20, 0xa8, 0x77, 0x51, 0x72, 0x73,
+            0xa3, 0x56, 0x05, 0x3e, 0xa2, 0xa1, 0xbc, 0x0c, 0x94, 0xaa,
+            0x72, 0xd5, 0x5c, 0x6e, 0x86, 0x29, 0x6b, 0x2d, 0xfc, 0x96,
+            0x79, 0x48, 0xc0, 0xa7, 0x2c, 0xbc, 0xcc, 0xa7, 0xea, 0xcb,
+            0x35, 0x70, 0x6e, 0x09, 0xa1, 0xdf, 0x55, 0xa1, 0x53, 0x5b,
+            0xd9, 0xb3, 0xcc, 0x34, 0x16, 0x0b, 0x3b, 0x6d, 0xcd, 0x3e,
+            0xda, 0x8e, 0x64, 0x43 },
+        64,
+    },
+    {
+        (unsigned char[]){
+            0xa5, 0x6e, 0x4a, 0x0e, 0x70, 0x10, 0x17, 0x58, 0x9a, 0x51,
+            0x87, 0xdc, 0x7e, 0xa8, 0x41, 0xd1, 0x56, 0xf2, 0xec, 0x0e,
+            0x36, 0xad, 0x52, 0xa4, 0x4d, 0xfe, 0xb1, 0xe6, 0x1f, 0x7a,
+            0xd9, 0x91, 0xd8, 0xc5, 0x10, 0x56, 0xff, 0xed, 0xb1, 0x62,
+            0xb4, 0xc0, 0xf2, 0x83, 0xa1, 0x2a, 0x88, 0xa3, 0x94, 0xdf,
+            0xf5, 0x26, 0xab, 0x72, 0x91, 0xcb, 0xb3, 0x07, 0xce, 0xab,
+            0xfc, 0xe0, 0xb1, 0xdf, 0xd5, 0xcd, 0x95, 0x08, 0x09, 0x6d,
+            0x5b, 0x2b, 0x8b, 0x6d, 0xf5, 0xd6, 0x71, 0xef, 0x63, 0x77,
+            0xc0, 0x92, 0x1c, 0xb2, 0x3c, 0x27, 0x0a, 0x70, 0xe2, 0x59,
+            0x8e, 0x6f, 0xf8, 0x9d, 0x19, 0xf1, 0x05, 0xac, 0xc2, 0xd3,
+            0xf0, 0xcb, 0x35, 0xf2, 0x92, 0x80, 0xe1, 0x38, 0x6b, 0x6f,
+            0x64, 0xc4, 0xef, 0x22, 0xe1, 0xe1, 0xf2, 0x0d, 0x0c, 0xe8,
+            0xcf, 0xfb, 0x22, 0x49, 0xbd, 0x9a, 0x21, 0x37 },
+        128,
+        (unsigned char[]){ 0x01, 0x00, 0x01 }, 3,
+        (unsigned char[]){
+            0x33, 0xa5, 0x04, 0x2a, 0x90, 0xb2, 0x7d, 0x4f, 0x54, 0x51,
+            0xca, 0x9b, 0xbb, 0xd0, 0xb4, 0x47, 0x71, 0xa1, 0x01, 0xaf,
+            0x88, 0x43, 0x40, 0xae, 0xf9, 0x88, 0x5f, 0x2a, 0x4b, 0xbe,
+            0x92, 0xe8, 0x94, 0xa7, 0x24, 0xac, 0x3c, 0x56, 0x8c, 0x8f,
+            0x97, 0x85, 0x3a, 0xd0, 0x7c, 0x02, 0x66, 0xc8, 0xc6, 0xa3,
+            0xca, 0x09, 0x29, 0xf1, 0xe8, 0xf1, 0x12, 0x31, 0x88, 0x44,
+            0x29, 0xfc, 0x4d, 0x9a, 0xe5, 0x5f, 0xee, 0x89, 0x6a, 0x10,
+            0xce, 0x70, 0x7c, 0x3e, 0xd7, 0xe7, 0x34, 0xe4, 0x47, 0x27,
+            0xa3, 0x95, 0x74, 0x50, 0x1a, 0x53, 0x26, 0x83, 0x10, 0x9c,
+            0x2a, 0xba, 0xca, 0xba, 0x28, 0x3c, 0x31, 0xb4, 0xbd, 0x2f,
+            0x53, 0xc3, 0xee, 0x37, 0xe3, 0x52, 0xce, 0xe3, 0x4f, 0x9e,
+            0x50, 0x3b, 0xd8, 0x0c, 0x06, 0x22, 0xad, 0x79, 0xc6, 0xdc,
+            0xee, 0x88, 0x35, 0x47, 0xc6, 0xa3, 0xb3, 0x25 },
+        128,
+        (unsigned char[]){
+            0xb6, 0x9d, 0xca, 0x1c, 0xf7, 0xd4, 0xd7, 0xec, 0x81, 0xe7,
+            0x5b, 0x90, 0xfc, 0xca, 0x87, 0x4a, 0xbc, 0xde, 0x12, 0x3f,
+            0xd2, 0x70, 0x01, 0x80, 0xaa, 0x90, 0x47, 0x9b, 0x6e, 0x48,
+            0xde, 0x8d, 0x67, 0xed, 0x24, 0xf9, 0xf1, 0x9d, 0x85, 0xba,
+            0x27, 0x58, 0x74, 0xf5, 0x42, 0xcd, 0x20, 0xdc, 0x72, 0x3e,
+            0x69, 0x63, 0x36, 0x4a, 0x1f, 0x94, 0x25, 0x45, 0x2b, 0x26,
+            0x9a, 0x67, 0x99, 0xfd },
+        64,
+        (unsigned char[]){
+            0xe7, 0xe8, 0x94, 0x27, 0x20, 0xa8, 0x77, 0x51, 0x72, 0x73,
+            0xa3, 0x56, 0x05, 0x3e, 0xa2, 0xa1, 0xbc, 0x0c, 0x94, 0xaa,
+            0x72, 0xd5, 0x5c, 0x6e, 0x86, 0x29, 0x6b, 0x2d, 0xfc, 0x96,
+            0x79, 0x48, 0xc0, 0xa7, 0x2c, 0xbc, 0xcc, 0xa7, 0xea, 0xcb,
+            0x35, 0x70, 0x6e, 0x09, 0xa1, 0xdf, 0x55, 0xa1, 0x53, 0x5b,
+            0xd9, 0xb3, 0xcc, 0x34, 0x16, 0x0b, 0x3b, 0x6d, 0xcd, 0x3e,
+            0xda, 0x8e, 0x64, 0x43 },
+        64,
+    },
+    {
+        (unsigned char[]){
+            0xa5, 0x6e, 0x4a, 0x0e, 0x70, 0x10, 0x17, 0x58, 0x9a, 0x51,
+            0x87, 0xdc, 0x7e, 0xa8, 0x41, 0xd1, 0x56, 0xf2, 0xec, 0x0e,
+            0x36, 0xad, 0x52, 0xa4, 0x4d, 0xfe, 0xb1, 0xe6, 0x1f, 0x7a,
+            0xd9, 0x91, 0xd8, 0xc5, 0x10, 0x56, 0xff, 0xed, 0xb1, 0x62,
+            0xb4, 0xc0, 0xf2, 0x83, 0xa1, 0x2a, 0x88, 0xa3, 0x94, 0xdf,
+            0xf5, 0x26, 0xab, 0x72, 0x91, 0xcb, 0xb3, 0x07, 0xce, 0xab,
+            0xfc, 0xe0, 0xb1, 0xdf, 0xd5, 0xcd, 0x95, 0x08, 0x09, 0x6d,
+            0x5b, 0x2b, 0x8b, 0x6d, 0xf5, 0xd6, 0x71, 0xef, 0x63, 0x77,
+            0xc0, 0x92, 0x1c, 0xb2, 0x3c, 0x27, 0x0a, 0x70, 0xe2, 0x59,
+            0x8e, 0x6f, 0xf8, 0x9d, 0x19, 0xf1, 0x05, 0xac, 0xc2, 0xd3,
+            0xf0, 0xcb, 0x35, 0xf2, 0x92, 0x80, 0xe1, 0x38, 0x6b, 0x6f,
+            0x64, 0xc4, 0xef, 0x22, 0xe1, 0xe1, 0xf2, 0x0d, 0x0c, 0xe8,
+            0xcf, 0xfb, 0x22, 0x49, 0xbd, 0x9a, 0x21, 0x37 },
+        128,
+        (unsigned char[]){ 0x01, 0x00, 0x01 }, 3,
+        (unsigned char[]){
+            0x33, 0xa5, 0x04, 0x2a, 0x90, 0xb2, 0x7d, 0x4f, 0x54, 0x51,
+            0xca, 0x9b, 0xbb, 0xd0, 0xb4, 0x47, 0x71, 0xa1, 0x01, 0xaf,
+            0x88, 0x43, 0x40, 0xae, 0xf9, 0x88, 0x5f, 0x2a, 0x4b, 0xbe,
+            0x92, 0xe8, 0x94, 0xa7, 0x24, 0xac, 0x3c, 0x56, 0x8c, 0x8f,
+            0x97, 0x85, 0x3a, 0xd0, 0x7c, 0x02, 0x66, 0xc8, 0xc6, 0xa3,
+            0xca, 0x09, 0x29, 0xf1, 0xe8, 0xf1, 0x12, 0x31, 0x88, 0x44,
+            0x29, 0xfc, 0x4d, 0x9a, 0xe5, 0x5f, 0xee, 0x89, 0x6a, 0x10,
+            0xce, 0x70, 0x7c, 0x3e, 0xd7, 0xe7, 0x34, 0xe4, 0x47, 0x27,
+            0xa3, 0x95, 0x74, 0x50, 0x1a, 0x53, 0x26, 0x83, 0x10, 0x9c,
+            0x2a, 0xba, 0xca, 0xba, 0x28, 0x3c, 0x31, 0xb4, 0xbd, 0x2f,
+            0x53, 0xc3, 0xee, 0x37, 0xe3, 0x52, 0xce, 0xe3, 0x4f, 0x9e,
+            0x50, 0x3b, 0xd8, 0x0c, 0x06, 0x22, 0xad, 0x79, 0xc6, 0xdc,
+            0xee, 0x88, 0x35, 0x47, 0xc6, 0xa3, 0xb3, 0x25 },
+        128,
+        (unsigned char[]){
+            0xb6, 0x9d, 0xca, 0x1c, 0xf7, 0xd4, 0xd7, 0xec, 0x81, 0xe7,
+            0x5b, 0x90, 0xfc, 0xca, 0x87, 0x4a, 0xbc, 0xde, 0x12, 0x3f,
+            0xd2, 0x70, 0x01, 0x80, 0xaa, 0x90, 0x47, 0x9b, 0x6e, 0x48,
+            0xde, 0x8d, 0x67, 0xed, 0x24, 0xf9, 0xf1, 0x9d, 0x85, 0xba,
+            0x27, 0x58, 0x74, 0xf5, 0x42, 0xcd, 0x20, 0xdc, 0x72, 0x3e,
+            0x69, 0x63, 0x36, 0x4a, 0x1f, 0x94, 0x25, 0x45, 0x2b, 0x26,
+            0x9a, 0x67, 0x99, 0xfd },
+        64,
+        (unsigned char[]){
+            0xe7, 0xe8, 0x94, 0x27, 0x20, 0xa8, 0x77, 0x51, 0x72, 0x73,
+            0xa3, 0x56, 0x05, 0x3e, 0xa2, 0xa1, 0xbc, 0x0c, 0x94, 0xaa,
+            0x72, 0xd5, 0x5c, 0x6e, 0x86, 0x29, 0x6b, 0x2d, 0xfc, 0x96,
+            0x79, 0x48, 0xc0, 0xa7, 0x2c, 0xbc, 0xcc, 0xa7, 0xea, 0xcb,
+            0x35, 0x70, 0x6e, 0x09, 0xa1, 0xdf, 0x55, 0xa1, 0x53, 0x5b,
+            0xd9, 0xb3, 0xcc, 0x34, 0x16, 0x0b, 0x3b, 0x6d, 0xcd, 0x3e,
+            0xda, 0x8e, 0x64, 0x43 },
+        64,
+    }
+};
--- a/lib/freebl/rsa.c
+++ b/lib/freebl/rsa.c
@@ -378,91 +378,182 @@ rsa_is_prime(mp_int *p)
     }
 
     /* If that passed, run some Miller-Rabin tests */
     res = mpp_pprime(p, 2);
     return res;
 }
 
 /*
- * Try to find the two primes based on 2 exponents plus either a prime
- *   or a modulus.
+ * Factorize a RSA modulus n into p and q by using the exponents e and d.
+ *
+ * In: e, d, n
+ * Out: p, q
+ *
+ * See Handbook of Applied Cryptography, 8.2.2(i).
+ *
+ * The algorithm is probabilistic, it is run 64 times and each run has a 50%
+ * chance of succeeding with a runtime of O(log(e*d)).
  *
- * In: e, d and either p or n (depending on the setting of hasModulus).
+ * The returned p might be smaller than q.
+ */
+static mp_err
+rsa_factorize_n_from_exponents(mp_int *e, mp_int *d, mp_int *p, mp_int *q,
+                               mp_int *n)
+{
+    /* lambda is the private modulus: e*d = 1 mod lambda */
+    /* so: e*d - 1 = k*lambda = t*2^s where t is odd */
+    mp_int klambda;
+    mp_int t, onetwentyeight;
+    unsigned long s = 0;
+    unsigned long i;
+
+    /* cand = a^(t * 2^i) mod n, next_cand = a^(t * 2^(i+1)) mod n */
+    mp_int a;
+    mp_int cand;
+    mp_int next_cand;
+
+    mp_int n_minus_one;
+    mp_err err = MP_OKAY;
+
+    MP_DIGITS(&klambda) = 0;
+    MP_DIGITS(&t) = 0;
+    MP_DIGITS(&a) = 0;
+    MP_DIGITS(&cand) = 0;
+    MP_DIGITS(&n_minus_one) = 0;
+    MP_DIGITS(&next_cand) = 0;
+    MP_DIGITS(&onetwentyeight) = 0;
+    CHECK_MPI_OK(mp_init(&klambda));
+    CHECK_MPI_OK(mp_init(&t));
+    CHECK_MPI_OK(mp_init(&a));
+    CHECK_MPI_OK(mp_init(&cand));
+    CHECK_MPI_OK(mp_init(&n_minus_one));
+    CHECK_MPI_OK(mp_init(&next_cand));
+    CHECK_MPI_OK(mp_init(&onetwentyeight));
+
+    mp_set_int(&onetwentyeight, 128);
+
+    /* calculate k*lambda = e*d - 1 */
+    CHECK_MPI_OK(mp_mul(e, d, &klambda));
+    CHECK_MPI_OK(mp_sub_d(&klambda, 1, &klambda));
+
+    /* factorize klambda into t*2^s */
+    CHECK_MPI_OK(mp_copy(&klambda, &t));
+    while (mpp_divis_d(&t, 2) == MP_YES) {
+        CHECK_MPI_OK(mp_div_2(&t, &t));
+        s += 1;
+    }
+
+    /* precompute n_minus_one = n - 1 */
+    CHECK_MPI_OK(mp_copy(n, &n_minus_one));
+    CHECK_MPI_OK(mp_sub_d(&n_minus_one, 1, &n_minus_one));
+
+    /* pick random bases a, each one has a 50% leading to a factorization */
+    CHECK_MPI_OK(mp_set_int(&a, 2));
+    /* The following is equivalent to for (a=2, a <= 128, a+=2) */
+    while (mp_cmp(&a, &onetwentyeight) <= 0) {
+        /* compute the base cand = a^(t * 2^0) [i = 0] */
+        CHECK_MPI_OK(mp_exptmod(&a, &t, n, &cand));
+
+        for (i = 0; i < s; i++) {
+            /* condition 1: skip the base if we hit a trivial factor of n */
+            if (mp_cmp(&cand, &n_minus_one) == 0 || mp_cmp_d(&cand, 1) == 0) {
+                break;
+            }
+
+            /* increase i in a^(t * 2^i) by squaring the number */
+            CHECK_MPI_OK(mp_exptmod_d(&cand, 2, n, &next_cand));
+
+            /* condition 2: a^(t * 2^(i+1)) = 1 mod n */
+            if (mp_cmp_d(&next_cand, 1) == 0) {
+                /* conditions verified, gcd(a^(t * 2^i) - 1, n) is a factor */
+                CHECK_MPI_OK(mp_sub_d(&cand, 1, &cand));
+                CHECK_MPI_OK(mp_gcd(&cand, n, p));
+                if (mp_cmp_d(p, 1) == 0) {
+                    CHECK_MPI_OK(mp_add_d(&cand, 1, &cand));
+                    break;
+                }
+                CHECK_MPI_OK(mp_div(n, p, q, NULL));
+                goto cleanup;
+            }
+            CHECK_MPI_OK(mp_copy(&next_cand, &cand));
+        }
+
+        CHECK_MPI_OK(mp_add_d(&a, 2, &a));
+    }
+
+    /* if we reach here it's likely (2^64 - 1 / 2^64) that d is wrong */
+    err = MP_RANGE;
+
+cleanup:
+    mp_clear(&klambda);
+    mp_clear(&t);
+    mp_clear(&a);
+    mp_clear(&cand);
+    mp_clear(&n_minus_one);
+    mp_clear(&next_cand);
+    mp_clear(&onetwentyeight);
+    return err;
+}
+
+/*
+ * Try to find the two primes based on 2 exponents plus a prime.
+ *
+ * In: e, d and p.
  * Out: p,q.
  *
  * Step 1, Since d = e**-1 mod phi, we know that d*e == 1 mod phi, or
  *  d*e = 1+k*phi, or d*e-1 = k*phi. since d is less than phi and e is
  *  usually less than d, then k must be an integer between e-1 and 1
  *  (probably on the order of e).
- * Step 1a, If we were passed just a prime, we can divide k*phi by that
- *      prime-1 and get k*(q-1). This will reduce the size of our division
- *      through the rest of the loop.
+ * Step 1a, We can divide k*phi by prime-1 and get k*(q-1). This will reduce
+ *      the size of our division through the rest of the loop.
  * Step 2, Loop through the values k=e-1 to 1 looking for k. k should be on
  *  the order or e, and e is typically small. This may take a while for
  *  a large random e. We are looking for a k that divides kphi
  *  evenly. Once we find a k that divides kphi evenly, we assume it
  *  is the true k. It's possible this k is not the 'true' k but has
  *  swapped factors of p-1 and/or q-1. Because of this, we
  *  tentatively continue Steps 3-6 inside this loop, and may return looking
  *  for another k on failure.
- * Step 3, Calculate are tentative phi=kphi/k. Note: real phi is (p-1)*(q-1).
- * Step 4a, if we have a prime, kphi is already k*(q-1), so phi is or tenative
- *      q-1. q = phi+1. If k is correct, q should be the right length and
- *      prime.
+ * Step 3, Calculate our tentative phi=kphi/k. Note: real phi is (p-1)*(q-1).
+ * Step 4a, kphi is k*(q-1), so phi is our tenative q-1. q = phi+1.
+ *      If k is correct, q should be the right length and prime.
  * Step 4b, It's possible q-1 and k could have swapped factors. We now have a
  *  possible solution that meets our criteria. It may not be the only
  *      solution, however, so we keep looking. If we find more than one,
  *      we will fail since we cannot determine which is the correct
  *      solution, and returning the wrong modulus will compromise both
  *      moduli. If no other solution is found, we return the unique solution.
- * Step 5a, If we have the modulus (n=pq), then use the following formula to
- *  calculate  s=(p+q): , phi = (p-1)(q-1) = pq  -p-q +1 = n-s+1. so
- *  s=n-phi+1.
- * Step 5b, Use n=pq and s=p+q to solve for p and q as follows:
- *  since q=s-p, then n=p*(s-p)= sp - p^2, rearranging p^2-s*p+n = 0.
- *  from the quadratic equation we have p=1/2*(s+sqrt(s*s-4*n)) and
- *  q=1/2*(s-sqrt(s*s-4*n)) if s*s-4*n is a perfect square, we are DONE.
- *  If it is not, continue in our look looking for another k. NOTE: the
- *  code actually distributes the 1/2 and results in the equations:
- *  sqrt = sqrt(s/2*s/2-n), p=s/2+sqrt, q=s/2-sqrt. The algebra saves us
- *  and extra divide by 2 and a multiply by 4.
  *
  * This will return p & q. q may be larger than p in the case that p was given
  * and it was the smaller prime.
  */
 static mp_err
-rsa_get_primes_from_exponents(mp_int *e, mp_int *d, mp_int *p, mp_int *q,
-                              mp_int *n, PRBool hasModulus,
-                              unsigned int keySizeInBits)
+rsa_get_prime_from_exponents(mp_int *e, mp_int *d, mp_int *p, mp_int *q,
+                             mp_int *n, unsigned int keySizeInBits)
 {
     mp_int kphi; /* k*phi */
     mp_int k;    /* current guess at 'k' */
     mp_int phi;  /* (p-1)(q-1) */
-    mp_int s;    /* p+q/2 (s/2 in the algebra) */
     mp_int r;    /* remainder */
-    mp_int tmp;  /* p-1 if p is given, n+1 is modulus is given */
-    mp_int sqrt; /* sqrt(s/2*s/2-n) */
+    mp_int tmp;  /* p-1 if p is given */
     mp_err err = MP_OKAY;
     unsigned int order_k;
 
     MP_DIGITS(&kphi) = 0;
     MP_DIGITS(&phi) = 0;
-    MP_DIGITS(&s) = 0;
     MP_DIGITS(&k) = 0;
     MP_DIGITS(&r) = 0;
     MP_DIGITS(&tmp) = 0;
-    MP_DIGITS(&sqrt) = 0;
     CHECK_MPI_OK(mp_init(&kphi));
     CHECK_MPI_OK(mp_init(&phi));
-    CHECK_MPI_OK(mp_init(&s));
     CHECK_MPI_OK(mp_init(&k));
     CHECK_MPI_OK(mp_init(&r));
     CHECK_MPI_OK(mp_init(&tmp));
-    CHECK_MPI_OK(mp_init(&sqrt));
 
     /* our algorithm looks for a factor k whose maximum size is dependent
      * on the size of our smallest exponent, which had better be the public
      * exponent (if it's the private, the key is vulnerable to a brute force
      * attack).
      *
      * since our factor search is linear, we need to limit the maximum
      * size of the public key. this should not be a problem normally, since
@@ -501,161 +592,103 @@ rsa_get_primes_from_exponents(mp_int *e,
     if (mp_cmp(&k, e) >= 0) {
         /* also can't be bigger then e-1 */
         CHECK_MPI_OK(mp_sub_d(e, 1, &k));
     }
 
     /* calculate our temp value */
     /* This saves recalculating this value when the k guess is wrong, which
      * is reasonably frequent. */
-    /* for the modulus case, tmp = n+1 (used to calculate p+q = tmp - phi) */
-    /* for the prime case, tmp = p-1 (used to calculate q-1= phi/tmp) */
-    if (hasModulus) {
-        CHECK_MPI_OK(mp_add_d(n, 1, &tmp));
-    } else {
-        CHECK_MPI_OK(mp_sub_d(p, 1, &tmp));
-        CHECK_MPI_OK(mp_div(&kphi, &tmp, &kphi, &r));
-        if (mp_cmp_z(&r) != 0) {
-            /* p-1 doesn't divide kphi, some parameter wasn't correct */
-            err = MP_RANGE;
-            goto cleanup;
-        }
-        mp_zero(q);
-        /* kphi is now k*(q-1) */
+    /* tmp = p-1 (used to calculate q-1= phi/tmp) */
+    CHECK_MPI_OK(mp_sub_d(p, 1, &tmp));
+    CHECK_MPI_OK(mp_div(&kphi, &tmp, &kphi, &r));
+    if (mp_cmp_z(&r) != 0) {
+        /* p-1 doesn't divide kphi, some parameter wasn't correct */
+        err = MP_RANGE;
+        goto cleanup;
     }
+    mp_zero(q);
+    /* kphi is now k*(q-1) */
 
     /* rest of the for loop */
     for (; (err == MP_OKAY) && (mpl_significant_bits(&k) >= order_k);
          err = mp_sub_d(&k, 1, &k)) {
+        CHECK_MPI_OK(err);
         /* looking for k as a factor of kphi */
         CHECK_MPI_OK(mp_div(&kphi, &k, &phi, &r));
         if (mp_cmp_z(&r) != 0) {
             /* not a factor, try the next one */
             continue;
         }
         /* we have a possible phi, see if it works */
-        if (!hasModulus) {
-            if ((unsigned)mpl_significant_bits(&phi) != keySizeInBits / 2) {
-                /* phi is not the right size */
-                continue;
-            }
-            /* phi should be divisible by 2, since
-         * q is odd and phi=(q-1). */
-            if (mpp_divis_d(&phi, 2) == MP_NO) {
-                /* phi is not divisible by 4 */
-                continue;
-            }
-            /* we now have a candidate for the second prime */
-            CHECK_MPI_OK(mp_add_d(&phi, 1, &tmp));
-
-            /* check to make sure it is prime */
-            err = rsa_is_prime(&tmp);
-            if (err != MP_OKAY) {
-                if (err == MP_NO) {
-                    /* No, then we still have the wrong phi */
-                    continue;
-                }
-                goto cleanup;
-            }
-            /*
-             * It is possible that we have the wrong phi if
-             * k_guess*(q_guess-1) = k*(q-1) (k and q-1 have swapped factors).
-             * since our q_quess is prime, however. We have found a valid
-             * rsa key because:
-             *   q is the correct order of magnitude.
-             *   phi = (p-1)(q-1) where p and q are both primes.
-             *   e*d mod phi = 1.
-             * There is no way to know from the info given if this is the
-             * original key. We never want to return the wrong key because if
-             * two moduli with the same factor is known, then euclid's gcd
-             * algorithm can be used to find that factor. Even though the
-             * caller didn't pass the original modulus, it doesn't mean the
-             * modulus wasn't known or isn't available somewhere. So to be safe
-             * if we can't be sure we have the right q, we don't return any.
-             *
-             * So to make sure we continue looking for other valid q's. If none
-             * are found, then we can safely return this one, otherwise we just
-             * fail */
-            if (mp_cmp_z(q) != 0) {
-                /* this is the second valid q, don't return either,
-                 * just fail */
-                err = MP_RANGE;
-                break;
-            }
-            /* we only have one q so far, save it and if no others are found,
-             * it's safe to return it */
-            CHECK_MPI_OK(mp_copy(&tmp, q));
-            continue;
-        }
-        /* test our tentative phi */
-        /* phi should be the correct order */
-        if ((unsigned)mpl_significant_bits(&phi) != keySizeInBits) {
+        if ((unsigned)mpl_significant_bits(&phi) != keySizeInBits / 2) {
             /* phi is not the right size */
             continue;
         }
-        /* phi should be divisible by 4, since
-         * p and q are odd and phi=(p-1)(q-1). */
-        if (mpp_divis_d(&phi, 4) == MP_NO) {
+        /* phi should be divisible by 2, since
+         * q is odd and phi=(q-1). */
+        if (mpp_divis_d(&phi, 2) == MP_NO) {
             /* phi is not divisible by 4 */
             continue;
         }
-        /* n was given, calculate s/2=(p+q)/2 */
-        CHECK_MPI_OK(mp_sub(&tmp, &phi, &s));
-        CHECK_MPI_OK(mp_div_2(&s, &s));
+        /* we now have a candidate for the second prime */
+        CHECK_MPI_OK(mp_add_d(&phi, 1, &tmp));
 
-        /* calculate sqrt(s/2*s/2-n) */
-        CHECK_MPI_OK(mp_sqr(&s, &sqrt));
-        CHECK_MPI_OK(mp_sub(&sqrt, n, &r)); /* r as a tmp */
-        CHECK_MPI_OK(mp_sqrt(&r, &sqrt));
-        /* make sure it's a perfect square */
-        /* r is our original value we took the square root of */
-        /* q is the square of our tentative square root. They should be equal*/
-        CHECK_MPI_OK(mp_sqr(&sqrt, q)); /* q as a tmp */
-        if (mp_cmp(&r, q) != 0) {
-            /* sigh according to the doc, mp_sqrt could return sqrt-1 */
-            CHECK_MPI_OK(mp_add_d(&sqrt, 1, &sqrt));
-            CHECK_MPI_OK(mp_sqr(&sqrt, q));
-            if (mp_cmp(&r, q) != 0) {
-                /* s*s-n not a perfect square, this phi isn't valid, find another.*/
+        /* check to make sure it is prime */
+        err = rsa_is_prime(&tmp);
+        if (err != MP_OKAY) {
+            if (err == MP_NO) {
+                /* No, then we still have the wrong phi */
                 continue;
             }
+            goto cleanup;
         }
-
-        /* NOTE: In this case we know we have the one and only answer.
-         * "Why?", you ask. Because:
-         *    1) n is a composite of two large primes (or it wasn't a
-         *       valid RSA modulus).
-         *    2) If we know any number such that x^2-n is a perfect square
-         *       and x is not (n+1)/2, then we can calculate 2 non-trivial
-         *       factors of n.
-         *    3) Since we know that n has only 2 non-trivial prime factors,
-         *       we know the two factors we have are the only possible factors.
-         */
-
-        /* Now we are home free to calculate p and q */
-        /* p = s/2 + sqrt, q= s/2 - sqrt */
-        CHECK_MPI_OK(mp_add(&s, &sqrt, p));
-        CHECK_MPI_OK(mp_sub(&s, &sqrt, q));
-        break;
+        /*
+         * It is possible that we have the wrong phi if
+         * k_guess*(q_guess-1) = k*(q-1) (k and q-1 have swapped factors).
+         * since our q_quess is prime, however. We have found a valid
+         * rsa key because:
+         *   q is the correct order of magnitude.
+         *   phi = (p-1)(q-1) where p and q are both primes.
+         *   e*d mod phi = 1.
+         * There is no way to know from the info given if this is the
+         * original key. We never want to return the wrong key because if
+         * two moduli with the same factor is known, then euclid's gcd
+         * algorithm can be used to find that factor. Even though the
+         * caller didn't pass the original modulus, it doesn't mean the
+         * modulus wasn't known or isn't available somewhere. So to be safe
+         * if we can't be sure we have the right q, we don't return any.
+         *
+         * So to make sure we continue looking for other valid q's. If none
+         * are found, then we can safely return this one, otherwise we just
+         * fail */
+        if (mp_cmp_z(q) != 0) {
+            /* this is the second valid q, don't return either,
+             * just fail */
+            err = MP_RANGE;
+            break;
+        }
+        /* we only have one q so far, save it and if no others are found,
+         * it's safe to return it */
+        CHECK_MPI_OK(mp_copy(&tmp, q));
+        continue;
     }
     if ((unsigned)mpl_significant_bits(&k) < order_k) {
-        if (hasModulus || (mp_cmp_z(q) == 0)) {
+        if (mp_cmp_z(q) == 0) {
             /* If we get here, something was wrong with the parameters we
              * were given */
             err = MP_RANGE;
         }
     }
 cleanup:
     mp_clear(&kphi);
     mp_clear(&phi);
-    mp_clear(&s);
     mp_clear(&k);
     mp_clear(&r);
     mp_clear(&tmp);
-    mp_clear(&sqrt);
     return err;
 }
 
 /*
  * take a private key with only a few elements and fill out the missing pieces.
  *
  * All the entries will be overwritten with data allocated out of the arena
  * If no arena is supplied, one will be created.
@@ -675,37 +708,33 @@ cleanup:
  *
  * All parameters will be replaced in the key structure with new parameters
  * Allocated out of the arena. There is no attempt to free the old structures.
  * Prime1 will always be greater than prime2 (even if the caller supplies the
  * smaller prime as prime1 or the larger prime as prime2). The parameters are
  * not overwritten on failure.
  *
  *  How it works:
- *     We can generate all the parameters from:
- *        one of the exponents, plus the two primes. (rsa_build_key_from_primes) *
+ *     We can generate all the parameters from one of the exponents, plus the
+ *        two primes. (rsa_build_key_from_primes)
  *     If we are given one of the exponents and both primes, we are done.
  *     If we are given one of the exponents, the modulus and one prime, we
  *        caclulate the second prime by dividing the modulus by the given
- *        prime, giving us and exponent and 2 primes.
- *     If we are given 2 exponents and either the modulus or one of the primes
- *        we calculate k*phi = d*e-1, where k is an integer less than d which
+ *        prime, giving us an exponent and 2 primes.
+ *     If we are given 2 exponents and one of the primes we calculate
+ *        k*phi = d*e-1, where k is an integer less than d which
  *        divides d*e-1. We find factor k so we can isolate phi.
  *            phi = (p-1)(q-1)
- *       If one of the primes are given, we can use phi to find the other prime
- *        as follows: q = (phi/(p-1)) + 1. We now have 2 primes and an
- *        exponent. (NOTE: if more then one prime meets this condition, the
- *        operation will fail. See comments elsewhere in this file about this).
- *       If the modulus is given, then we can calculate the sum of the primes
- *        as follows: s := (p+q), phi = (p-1)(q-1) = pq -p - q +1, pq = n ->
- *        phi = n - s + 1, s = n - phi +1.  Now that we have s = p+q and n=pq,
- *    we can solve our 2 equations and 2 unknowns as follows: q=s-p ->
- *        n=p*(s-p)= sp -p^2 -> p^2-sp+n = 0. Using the quadratic to solve for
- *        p, p=1/2*(s+ sqrt(s*s-4*n)) [q=1/2*(s-sqrt(s*s-4*n)]. We again have
- *        2 primes and an exponent.
+ *        We can use phi to find the other prime as follows:
+ *        q = (phi/(p-1)) + 1. We now have 2 primes and an exponent.
+ *        (NOTE: if more then one prime meets this condition, the operation
+ *        will fail. See comments elsewhere in this file about this).
+ *        (rsa_get_prime_from_exponents)
+ *     If we are given 2 exponents and the modulus we factor the modulus to
+ *        get the 2 missing primes (rsa_factorize_n_from_exponents)
  *
  */
 SECStatus
 RSA_PopulatePrivateKey(RSAPrivateKey *key)
 {
     PLArenaPool *arena = NULL;
     PRBool needPublicExponent = PR_TRUE;
     PRBool needPrivateExponent = PR_TRUE;
@@ -797,21 +826,23 @@ RSA_PopulatePrivateKey(RSAPrivateKey *ke
         }
         prime_count++;
     }
 
     /* If we didn't have enough primes try to calculate the primes from
      * the exponents */
     if (prime_count < 2) {
         /* if we don't have at least 2 primes at this point, then we need both
-     * exponents and one prime or a modulus*/
+         * exponents and one prime or a modulus*/
         if (!needPublicExponent && !needPrivateExponent &&
-            ((prime_count > 0) || hasModulus)) {
-            CHECK_MPI_OK(rsa_get_primes_from_exponents(&e, &d, &p, &q,
-                                                       &n, hasModulus, keySizeInBits));
+            (prime_count > 0)) {
+            CHECK_MPI_OK(rsa_get_prime_from_exponents(&e, &d, &p, &q, &n,
+                                                      keySizeInBits));
+        } else if (!needPublicExponent && !needPrivateExponent && hasModulus) {
+            CHECK_MPI_OK(rsa_factorize_n_from_exponents(&e, &d, &p, &q, &n));
         } else {
             /* not enough given parameters to get both primes */
             err = MP_BADARG;
             goto cleanup;
         }
     }
 
     /* Assure p > q */
--- a/tests/cipher/cipher.txt
+++ b/tests/cipher/cipher.txt
@@ -40,16 +40,17 @@
 	0	rc4_-E		RC4_Encrypt
 	0	rc4_-D		RC4_Decrypt
 	0	rsa_-E		RSA_Encrypt
 	0	rsa_-D		RSA_Decrypt
 	0	rsa_oaep_-E	RSA_EncryptOAEP
 	0	rsa_oaep_-D	RSA_DecryptOAEP
 	0	rsa_pss_-S	RSA_SignPSS
 	0	rsa_pss_-V	RSA_CheckSignPSS
+	0	rsa_-K		RSA_Populate
 	0	dsa_-S		DSA_Sign
 	0	dsa_-V		DSA_Verify
 	0	md2_-H		MD2_Hash
 	0	md5_-H		MD5_Hash
 	0	sha1_-H		SHA1_Hash
 	0	sha224_-H	SHA224_Hash
 	0	sha256_-H	SHA256_Hash
 	0	sha384_-H	SHA384_Hash