Preliminary support for X9.31 RSA key generation for FIPS.
authorDr. Stephen Henson <steve@openssl.org>
Tue, 31 May 2005 12:38:03 +0000 (12:38 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Tue, 31 May 2005 12:38:03 +0000 (12:38 +0000)
Included prime derivation, random prime generation, test program and
new option to genrsa.

13 files changed:
apps/genrsa.c
crypto/bn/Makefile
crypto/bn/bn.h
crypto/bn/bn_x931p.c [new file with mode: 0644]
crypto/rsa/rsa.h
fips/fips.h
fips/fips_err.h
fips/fipshashes.c
fips/rsa/Makefile
fips/rsa/fips_rsa_gen.c
fips/rsa/fips_rsa_x931g.c [new file with mode: 0644]
fips/rsa/fips_rsagtest.c [new file with mode: 0644]
test/Makefile

index 63be873b7bf83fe5099629e38a0835ba7e13071d..7dbd0923b64db8207182f94c149246ce3d3c8021 100644 (file)
@@ -88,6 +88,9 @@ int MAIN(int argc, char **argv)
        RSA *rsa=NULL;
        int i,num=DEFBITS;
        long l;
+#ifdef OPENSSL_FIPS
+       int use_x931 = 0;
+#endif
        const EVP_CIPHER *enc=NULL;
        unsigned long f4=RSA_F4;
        char *outfile=NULL;
@@ -126,6 +129,10 @@ int MAIN(int argc, char **argv)
                        f4=3;
                else if (strcmp(*argv,"-F4") == 0 || strcmp(*argv,"-f4") == 0)
                        f4=RSA_F4;
+#ifdef OPENSSL_FIPS
+               else if (strcmp(*argv,"-x931") == 0)
+                       use_x931 = 1;
+#endif
 #ifndef OPENSSL_NO_ENGINE
                else if (strcmp(*argv,"-engine") == 0)
                        {
@@ -233,11 +240,27 @@ bad:
 
        BIO_printf(bio_err,"Generating RSA private key, %d bit long modulus\n",
                num);
-       rsa=RSA_generate_key(num,f4,genrsa_cb,bio_err);
+#ifdef OPENSSL_FIPS
+       if (use_x931)
+               {
+               BIGNUM *pubexp;
+               pubexp = BN_new();
+               BN_set_word(pubexp, f4);
+               rsa = RSA_X931_generate_key(num, pubexp, genrsa_cb, bio_err);
+               BN_free(pubexp);
+               }
+       else
+#endif
+               rsa=RSA_generate_key(num,f4,genrsa_cb,bio_err);
                
        app_RAND_write_file(NULL, bio_err);
 
-       if (rsa == NULL) goto err;
+       if (rsa == NULL)
+               {
+               BIO_printf(bio_err, "Key Generation error\n");
+
+               goto err;
+               }
        
        /* We need to do the following for when the base number size is <
         * long, esp windows 3.1 :-(. */
index f693d35d87ba27ae11b507532510fcf37d9c8df3..9f26bd51252597a5d139058eea56e10a87bd80db 100644 (file)
@@ -31,12 +31,12 @@ LIB=$(TOP)/libcrypto.a
 LIBSRC=        bn_add.c bn_div.c bn_exp.c bn_lib.c bn_ctx.c bn_mul.c bn_mod.c \
        bn_print.c bn_rand.c bn_shift.c bn_word.c bn_blind.c \
        bn_kron.c bn_sqrt.c bn_gcd.c bn_prime.c bn_err.c bn_sqr.c bn_asm.c \
-       bn_recp.c bn_mont.c bn_mpi.c bn_exp2.c
+       bn_recp.c bn_mont.c bn_mpi.c bn_exp2.c bn_x931p.c
 
 LIBOBJ=        bn_add.o bn_div.o bn_exp.o bn_lib.o bn_ctx.o bn_mul.o bn_mod.o \
        bn_print.o bn_rand.o bn_shift.o bn_word.o bn_blind.o \
        bn_kron.o bn_sqrt.o bn_gcd.o bn_prime.o bn_err.o bn_sqr.o $(BN_ASM) \
-       bn_recp.o bn_mont.o bn_mpi.o bn_exp2.o
+       bn_recp.o bn_mont.o bn_mpi.o bn_exp2.o bn_x931p.o
 
 SRC= $(LIBSRC)
 
index d26c2211f91055af2f737ea5bbdf012b8b28461b..1251521c54d3db3a4c83968190e01b52f5e1aef9 100644 (file)
@@ -438,6 +438,19 @@ int        BN_is_prime_fasttest(const BIGNUM *p,int nchecks,
        void (*callback)(int,int,void *),BN_CTX *ctx,void *cb_arg,
        int do_trial_division);
 
+#ifdef OPENSSL_FIPS
+int BN_X931_derive_prime(BIGNUM *p, BIGNUM *p1, BIGNUM *p2,
+                       void (*cb)(int, int, void *), void *cb_arg,
+                       const BIGNUM *Xp, const BIGNUM *Xp1, const BIGNUM *Xp2,
+                       const BIGNUM *e, BN_CTX *ctx);
+int BN_X931_generate_Xpq(BIGNUM *Xp, BIGNUM *Xq, int nbits, BN_CTX *ctx);
+int BN_X931_generate_prime(BIGNUM *p, BIGNUM *p1, BIGNUM *p2,
+                       BIGNUM *Xp1, BIGNUM *Xp2,
+                       const BIGNUM *Xp,
+                       const BIGNUM *e, BN_CTX *ctx,
+                       void (*cb)(int, int, void *), void *cb_arg);
+#endif
+
 BN_MONT_CTX *BN_MONT_CTX_new(void );
 void BN_MONT_CTX_init(BN_MONT_CTX *ctx);
 int BN_mod_mul_montgomery(BIGNUM *r,const BIGNUM *a,const BIGNUM *b,
diff --git a/crypto/bn/bn_x931p.c b/crypto/bn/bn_x931p.c
new file mode 100644 (file)
index 0000000..6b8543a
--- /dev/null
@@ -0,0 +1,279 @@
+/* bn_x931p.c */
+/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+ * project 2005.
+ */
+/* ====================================================================
+ * Copyright (c) 2005 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include <stdio.h>
+#include <openssl/bn.h>
+
+/* X9.31 routines for prime derivation */
+
+
+/* X9.31 prime derivation. This is used to generate the primes pi
+ * (p1, p2, q1, q2) from a parameter Xpi by checking successive odd
+ * integers.
+ */
+
+static int bn_x931_derive_pi(BIGNUM *pi, const BIGNUM *Xpi, BN_CTX *ctx,
+                       void (*cb)(int, int, void *), void *cb_arg)
+       {
+       int i = 0;
+       if (!BN_copy(pi, Xpi))
+               return 0;
+       if (!BN_is_odd(pi) && !BN_add_word(pi, 1))
+               return 0;
+       for(;;)
+               {
+               i++;
+               if (cb)
+                       cb(0, i, cb_arg);
+               /* NB 27 MR is specificed in X9.31 */
+               if (BN_is_prime_fasttest(pi, 27, cb, ctx, cb_arg, 1))
+                       break;
+               if (!BN_add_word(pi, 2))
+                       return 0;
+               }
+       if (cb)
+               cb(2, i, cb_arg);
+       return 1;
+       }
+
+/* This is the main X9.31 prime derivation function. From parameters
+ * Xp1, Xp2 and Xp derive the prime p. If the parameters p1 or p2 are
+ * not NULL they will be returned too: this is needed for testing.
+ */
+
+int BN_X931_derive_prime(BIGNUM *p, BIGNUM *p1, BIGNUM *p2,
+                       void (*cb)(int, int, void *), void *cb_arg,
+                       const BIGNUM *Xp, const BIGNUM *Xp1, const BIGNUM *Xp2,
+                       const BIGNUM *e, BN_CTX *ctx)
+       {
+       int ret = 0;
+
+       BIGNUM *t, *p1p2, *pm1;
+
+       /* Only even e supported */
+       if (!BN_is_odd(e))
+               return 0;
+
+       BN_CTX_start(ctx);
+       if (!p1)
+               p1 = BN_CTX_get(ctx);
+
+       if (!p2)
+               p2 = BN_CTX_get(ctx);
+
+       t = BN_CTX_get(ctx);
+
+       p1p2 = BN_CTX_get(ctx);
+
+       pm1 = BN_CTX_get(ctx);
+
+       if (!bn_x931_derive_pi(p1, Xp1, ctx, cb, cb_arg))
+               goto err;
+
+       if (!bn_x931_derive_pi(p2, Xp2, ctx, cb, cb_arg))
+               goto err;
+
+       if (!BN_mul(p1p2, p1, p2, ctx))
+               goto err;
+
+       /* First set p to value of Rp */
+
+       if (!BN_mod_inverse(p, p2, p1, ctx))
+               goto err;
+
+       if (!BN_mul(p, p, p2, ctx))
+               goto err;
+
+       if (!BN_mod_inverse(t, p1, p2, ctx))
+               goto err;
+
+       if (!BN_mul(t, t, p1, ctx))
+               goto err;
+
+       if (!BN_sub(p, p, t))
+               goto err;
+
+       if (p->neg && !BN_add(p, p, p1p2))
+               goto err;
+
+       /* p now equals Rp */
+
+       if (!BN_mod_sub(p, p, Xp, p1p2, ctx))
+               goto err;
+
+       if (!BN_add(p, p, Xp))
+               goto err;
+
+       /* p now equals Yp0 */
+
+       for (;;)
+               {
+               int i = 1;
+               if (cb)
+                       cb(0, i++, cb_arg);
+               if (!BN_copy(pm1, p))
+                       goto err;
+               if (!BN_sub_word(pm1, 1))
+                       goto err;
+               if (!BN_gcd(t, pm1, e, ctx))
+                       goto err;
+               if (BN_is_one(t)
+               /* X9.31 specifies 8 MR and 1 Lucas test or any prime test
+                * offering similar or better guarantees 50 MR is considerably 
+                * better.
+                */
+                       && BN_is_prime_fasttest(p, 50, cb, ctx, cb_arg, 1))
+                       break;
+               if (!BN_add(p, p, p1p2))
+                       goto err;
+               }
+
+       if (cb)
+               cb(3, 0, cb_arg);
+
+       ret = 1;
+
+       err:
+
+       BN_CTX_end(ctx);
+
+       return ret;
+       }
+
+/* Generate pair of paramters Xp, Xq for X9.31 prime generation.
+ * Note: nbits paramter is sum of number of bits in both.
+ */
+
+int BN_X931_generate_Xpq(BIGNUM *Xp, BIGNUM *Xq, int nbits, BN_CTX *ctx)
+       {
+       BIGNUM *t;
+       int i;
+       /* Number of bits for each prime is of the form
+        * 512+128s for s = 0, 1, ...
+        */
+       if ((nbits < 1024) || (nbits & 0xff))
+               return 0;
+       nbits >>= 1;
+       /* The random value Xp must be between sqrt(2) * 2^(nbits-1) and
+        * 2^nbits - 1. By setting the top two bits we ensure that the lower
+        * bound is exceeded.
+        */
+       if (!BN_rand(Xp, nbits, 1, 0))
+               return 0;
+
+       BN_CTX_start(ctx);
+       t = BN_CTX_get(ctx);
+
+       for (i = 0; i < 1000; i++)
+               {
+               if (!BN_rand(Xq, nbits, 1, 0))
+                       return 0;
+               /* Check that |Xp - Xq| > 2^(nbits - 100) */
+               BN_sub(t, Xp, Xq);
+               if (BN_num_bits(t) > (nbits - 100))
+                       break;
+               }
+
+       BN_CTX_end(ctx);
+
+       if (i < 1000)
+               return 1;
+
+       return 0;
+
+       }
+
+/* Generate primes using X9.31 algorithm. Of the values p, p1, p2, Xp1
+ * and Xp2 only 'p' needs to be non-NULL. If any of the others are not NULL
+ * the relevant parameter will be stored in it.
+ *
+ * Due to the fact that |Xp - Xq| > 2^(nbits - 100) must be satisfied Xp and Xq
+ * are generated using the previous function and supplied as input.
+ */
+
+int BN_X931_generate_prime(BIGNUM *p, BIGNUM *p1, BIGNUM *p2,
+                       BIGNUM *Xp1, BIGNUM *Xp2,
+                       const BIGNUM *Xp,
+                       const BIGNUM *e, BN_CTX *ctx,
+                       void (*cb)(int, int, void *), void *cb_arg)
+       {
+       int ret = 0;
+
+       BN_CTX_start(ctx);
+       if (!Xp1)
+               Xp1 = BN_CTX_get(ctx);
+       if (!Xp2)
+               Xp2 = BN_CTX_get(ctx);
+
+       if (!BN_rand(Xp1, 101, 0, 0))
+               goto error;
+       if (!BN_rand(Xp2, 101, 0, 0))
+               goto error;
+       if (!BN_X931_derive_prime(p, p1, p2, cb, cb_arg,
+                                               Xp, Xp1, Xp2, e, ctx))
+               goto error;
+
+       ret = 1;
+
+       error:
+       BN_CTX_end(ctx);
+
+       return ret;
+
+       }
+
index 7e8d6d99a29877e81e6c262b0d27a17718f59243..f5b36bf630ad1e2b4625c8feb7456c8201c5e799 100644 (file)
@@ -204,6 +204,15 @@ int        RSA_size(const RSA *);
 RSA *  RSA_generate_key(int bits, unsigned long e,void
                (*callback)(int,int,void *),void *cb_arg);
 int    RSA_check_key(const RSA *);
+#ifndef FIPS
+int RSA_X931_derive(RSA *rsa, BIGNUM *p1, BIGNUM *p2, BIGNUM *q1, BIGNUM *q2,
+                       void (*cb)(int, int, void *), void *cb_arg,
+                       const BIGNUM *Xp1, const BIGNUM *Xp2, const BIGNUM *Xp,
+                       const BIGNUM *Xq1, const BIGNUM *Xq2, const BIGNUM *Xq,
+                       const BIGNUM *e);
+RSA *RSA_X931_generate_key(int bits, const BIGNUM *e,
+            void (*cb)(int,int,void *), void *cb_arg);
+#endif
        /* next 4 return -1 on error */
 int    RSA_public_encrypt(int flen, const unsigned char *from,
                unsigned char *to, RSA *rsa,int padding);
index 2ed828fd7349ddfd1f942cb0682857f49349998e..3dbdc661ceaed22fee5f9a8dd5f67291b215c31c 100644 (file)
@@ -108,6 +108,7 @@ void ERR_load_FIPS_strings(void);
 #define FIPS_F_HASH_FINAL                               100
 #define FIPS_F_RSA_EAY_PUBLIC_ENCRYPT                   114
 #define FIPS_F_RSA_GENERATE_KEY                                 113
+#define FIPS_F_RSA_X931_GENERATE_KEY                    119
 #define FIPS_F_SSLEAY_RAND_BYTES                        101
 
 /* Reason codes. */
@@ -116,10 +117,11 @@ void ERR_load_FIPS_strings(void);
 #define FIPS_R_EXE_DIGEST_DOES_NOT_MATCH                105
 #define FIPS_R_FIPS_MODE_ALREADY_SET                    102
 #define FIPS_R_FIPS_SELFTEST_FAILED                     106
+#define FIPS_R_INVALID_KEY_LENGTH                       109
+#define FIPS_R_KEY_TOO_SHORT                            108
 #define FIPS_R_NON_FIPS_METHOD                          100
 #define FIPS_R_PAIRWISE_TEST_FAILED                     107
 #define FIPS_R_SELFTEST_FAILED                          101
-#define FIPS_R_KEY_TOO_SHORT                            108
 
 #ifdef  __cplusplus
 }
index 779787f35e5373c2e9dd9c282c182c70b88e1e9e..59144e4c24bbc4e4f2078333db8d56600d8fc58f 100644 (file)
@@ -84,10 +84,11 @@ static ERR_STRING_DATA FIPS_str_functs[]=
 {ERR_FUNC(FIPS_F_FIPS_SELFTEST_DSA),   "FIPS_selftest_dsa"},
 {ERR_FUNC(FIPS_F_FIPS_SELFTEST_RNG),   "FIPS_selftest_rng"},
 {ERR_FUNC(FIPS_F_FIPS_SELFTEST_RSA),   "FIPS_selftest_rsa"},
-{ERR_FUNC(FIPS_F_FIPS_SELFTEST_SHA),   "FIPS_selftest_sha"},
+{ERR_FUNC(FIPS_F_FIPS_SELFTEST_SHA),   "FIPS_SELFTEST_SHA"},
 {ERR_FUNC(FIPS_F_HASH_FINAL),  "HASH_FINAL"},
 {ERR_FUNC(FIPS_F_RSA_EAY_PUBLIC_ENCRYPT),      "RSA_EAY_PUBLIC_ENCRYPT"},
 {ERR_FUNC(FIPS_F_RSA_GENERATE_KEY),    "RSA_generate_key"},
+{ERR_FUNC(FIPS_F_RSA_X931_GENERATE_KEY),       "RSA_X931_generate_key"},
 {ERR_FUNC(FIPS_F_SSLEAY_RAND_BYTES),   "SSLEAY_RAND_BYTES"},
 {0,NULL}
        };
@@ -99,6 +100,8 @@ static ERR_STRING_DATA FIPS_str_reasons[]=
 {ERR_REASON(FIPS_R_EXE_DIGEST_DOES_NOT_MATCH),"exe digest does not match"},
 {ERR_REASON(FIPS_R_FIPS_MODE_ALREADY_SET),"fips mode already set"},
 {ERR_REASON(FIPS_R_FIPS_SELFTEST_FAILED) ,"fips selftest failed"},
+{ERR_REASON(FIPS_R_INVALID_KEY_LENGTH)   ,"invalid key length"},
+{ERR_REASON(FIPS_R_KEY_TOO_SHORT)        ,"key too short"},
 {ERR_REASON(FIPS_R_NON_FIPS_METHOD)      ,"non fips method"},
 {ERR_REASON(FIPS_R_PAIRWISE_TEST_FAILED) ,"pairwise test failed"},
 {ERR_REASON(FIPS_R_SELFTEST_FAILED)      ,"selftest failed"},
@@ -109,11 +112,11 @@ static ERR_STRING_DATA FIPS_str_reasons[]=
 
 void ERR_load_FIPS_strings(void)
        {
-       static int init;
+       static int init=1;
 
-       if (!init)
+       if (init)
                {
-               init=1;
+               init=0;
 #ifndef OPENSSL_NO_ERR
                ERR_load_strings(0,FIPS_str_functs);
                ERR_load_strings(0,FIPS_str_reasons);
index 388ca9a60677d6822dcba8d6a12014851517f931..040ab284009c76bce99834ce593186cda2e3443e 100644 (file)
@@ -1,8 +1,8 @@
 const char * const FIPS_source_hashes[] = {
 "HMAC-SHA1(fips.c)= 7cbbda3b9e8aec46ee31797179cb72faeef80712",
 "HMAC-SHA1(fips_err_wrapper.c)= d3e2be316062510312269e98f964cb87e7577898",
-"HMAC-SHA1(fips.h)= e85fdc2fe6ad2dbf0662691e87af4b6b240da62e",
-"HMAC-SHA1(fips_err.h)= 0b2bd6999ee5792fec3739689cde5f352789e63a",
+"HMAC-SHA1(fips.h)= 9e8d77f438eabc36273e2046aa209e6e78515103",
+"HMAC-SHA1(fips_err.h)= fec567f1abe0f8d53a208b7f24b992dda2db3e4d",
 "HMAC-SHA1(aes/fips_aes_core.c)= b70bbbd675efe0613da0d57055310926a0104d55",
 "HMAC-SHA1(aes/asm/fips-ax86-elf.s)= f797b524a79196e7f59458a5b223432fcfd4a868",
 "HMAC-SHA1(aes/fips_aes_selftest.c)= 98b01502221e7fe529fd981222f2cbb52eb4cbe0",
@@ -22,8 +22,9 @@ const char * const FIPS_source_hashes[] = {
 "HMAC-SHA1(rand/fips_rand.h)= bf009ea8963e79b1e414442ede9ae7010a03160b",
 "HMAC-SHA1(rand/fips_rand_selftest.c)= d9c8985e08feecefafe667ad0119d444b42f807c",
 "HMAC-SHA1(rsa/fips_rsa_eay.c)= 2512f849a220daa083f346b10effdb2ee96d4395",
-"HMAC-SHA1(rsa/fips_rsa_gen.c)= af83b857d2be13d59e7f1516e6b1a25edd6369c3",
+"HMAC-SHA1(rsa/fips_rsa_gen.c)= 577466931c054d99caf4ac2aefff0e35efd94024",
 "HMAC-SHA1(rsa/fips_rsa_selftest.c)= a9dc47bd1001f795d1565111d26433c300101e06",
+"HMAC-SHA1(rsa/fips_rsa_x931g.c)= 62ecb2622cf61010561d5800ba2c74f54a3d2526",
 "HMAC-SHA1(sha/fips_sha1dgst.c)= 26e529d630b5e754b4a29bd1bb697e991e7fdc04",
 "HMAC-SHA1(sha/fips_standalone_sha1.c)= faae95bc36cc80f5be6a0cde02ebab0f63d4fd97",
 "HMAC-SHA1(sha/fips_sha1_selftest.c)= a08f9c1e2c0f63b9aa96b927c0333a03b020749f",
index 897b5ceece46844d9dfc5b19a7442dbbe252c33c..7ead49974031cbe2612a4d2c3125efb937240c70 100644 (file)
@@ -18,12 +18,12 @@ AR=         ar r
 CFLAGS= $(INCLUDES) $(CFLAG)
 
 GENERAL=Makefile
-TEST= fips_rsavtest.c fips_rsastest.c
+TEST= fips_rsavtest.c fips_rsastest.c fips_rsagtest.c
 APPS=
 
 LIB=$(TOP)/libcrypto.a
-LIBSRC=fips_rsa_eay.c fips_rsa_gen.c fips_rsa_selftest.c
-LIBOBJ=fips_rsa_eay.o fips_rsa_gen.o fips_rsa_selftest.o
+LIBSRC=fips_rsa_eay.c fips_rsa_gen.c fips_rsa_selftest.c fips_rsa_x931g.c
+LIBOBJ=fips_rsa_eay.o fips_rsa_gen.o fips_rsa_selftest.o fips_rsa_x931g.o
 
 SRC= $(LIBSRC)
 
@@ -68,6 +68,9 @@ top_fips_rsastest:
 top_fips_rsavtest:
        (cd $(TOP); $(MAKE) DIRS=fips FDIRS=$(DIR) TARGET=fips_rsavtest sub_target)
 
+top_fips_rsagtest:
+       (cd $(TOP); $(MAKE) DIRS=fips FDIRS=$(DIR) TARGET=fips_rsagtest sub_target)
+
 fips_rsastest: fips_rsastest.o $(TOP)/libcrypto.a
        $(CC) $(CFLAGS) -o fips_rsastest fips_rsastest.o $(PEX_LIBS) $(TOP)/libcrypto.a $(EX_LIBS)
        TOP=$(TOP) $(TOP)/fips/openssl_fips_fingerprint $(TOP)/libcrypto.a fips_rsastest
@@ -76,10 +79,14 @@ fips_rsavtest: fips_rsavtest.o $(TOP)/libcrypto.a
        $(CC) $(CFLAGS) -o fips_rsavtest fips_rsavtest.o $(PEX_LIBS) $(TOP)/libcrypto.a $(EX_LIBS)
        TOP=$(TOP) $(TOP)/fips/openssl_fips_fingerprint $(TOP)/libcrypto.a fips_rsavtest
 
+fips_rsagtest: fips_rsagtest.o $(TOP)/libcrypto.a
+       $(CC) $(CFLAGS) -o fips_rsagtest fips_rsagtest.o $(PEX_LIBS) $(TOP)/libcrypto.a $(EX_LIBS)
+       TOP=$(TOP) $(TOP)/fips/openssl_fips_fingerprint $(TOP)/libcrypto.a fips_rsagtest
+
 Q=../testvectors/rsa/req
 A=../testvectors/rsa/rsp
 
-fips_test: top top_fips_rsastest top_fips_rsavtest
+fips_test: top top_fips_rsastest top_fips_rsavtest top_fips_rsagtest
        -rm -rf $(A)
        mkdir $(A)
        ./fips_rsastest < $(Q)/SigGen15.req > $(A)/SigGen15.rsp
index 433ce79745d25f295417b8366794fd83d6a6aaa3..3f50746733e2828206072630798a7ef8ddecb3a1 100644 (file)
@@ -68,7 +68,7 @@ void *OPENSSL_stderr(void);
 
 #ifdef OPENSSL_FIPS
 
-static int fips_check_rsa(RSA *rsa)
+int fips_check_rsa(RSA *rsa)
     {
     int n, ret = 0;
     unsigned char tctext[256], *ctext = tctext;
diff --git a/fips/rsa/fips_rsa_x931g.c b/fips/rsa/fips_rsa_x931g.c
new file mode 100644 (file)
index 0000000..cb89937
--- /dev/null
@@ -0,0 +1,286 @@
+/* crypto/rsa/rsa_gen.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <openssl/err.h>
+#include <openssl/bn.h>
+#include <openssl/rsa.h>
+#include <openssl/fips.h>
+
+extern int fips_check_rsa(RSA *rsa);
+
+
+/* X9.31 RSA key derivation and generation */
+
+int RSA_X931_derive(RSA *rsa, BIGNUM *p1, BIGNUM *p2, BIGNUM *q1, BIGNUM *q2,
+                       void (*cb)(int, int, void *), void *cb_arg,
+                       const BIGNUM *Xp1, const BIGNUM *Xp2, const BIGNUM *Xp,
+                       const BIGNUM *Xq1, const BIGNUM *Xq2, const BIGNUM *Xq,
+                       const BIGNUM *e)
+       {
+       BIGNUM *r0=NULL,*r1=NULL,*r2=NULL,*r3=NULL;
+       BN_CTX *ctx=NULL,*ctx2=NULL;
+
+       if (!rsa) 
+               goto err;
+
+       ctx = BN_CTX_new();
+       BN_CTX_start(ctx);
+       if (!ctx) 
+               goto err;
+
+       r0 = BN_CTX_get(ctx);
+       r1 = BN_CTX_get(ctx);
+       r2 = BN_CTX_get(ctx);
+       r3 = BN_CTX_get(ctx);
+
+       if (r3 == NULL)
+               goto err;
+       if (!rsa->e)
+               {
+               rsa->e = BN_dup(e);
+               if (!rsa->e)
+                       goto err;
+               }
+       else
+               e = rsa->e;
+
+       /* If not all parameters present only calculate what we can.
+        * This allows test programs to output selective parameters.
+        */
+
+       if (Xp && !rsa->p)
+               {
+               rsa->p = BN_new();
+               if (!rsa->p)
+                       goto err;
+
+               if (!BN_X931_derive_prime(rsa->p, p1, p2, cb, cb_arg,
+                                       Xp, Xp1, Xp2, e, ctx))
+                       goto err;
+               }
+
+       if (Xq && !rsa->q)
+               {
+               rsa->q = BN_new();
+               if (!rsa->q)
+                       goto err;
+               if (!BN_X931_derive_prime(rsa->q, q1, q2, cb, cb_arg,
+                                       Xq, Xq1, Xq2, e, ctx))
+                       goto err;
+               }
+
+       if (!rsa->p || !rsa->q)
+               {
+               BN_CTX_end(ctx);
+               BN_CTX_free(ctx);
+               return 2;
+               }
+
+       /* Since both primes are set we can now calculate all remaining 
+        * components.
+        */
+
+       /* calculate n */
+       rsa->n=BN_new();
+       if (rsa->n == NULL)
+               goto err;
+       if (!BN_mul(rsa->n,rsa->p,rsa->q,ctx))
+               goto err;
+
+       /* calculate d */
+       if (!BN_sub(r1,rsa->p,BN_value_one()))
+               goto err;       /* p-1 */
+       if (!BN_sub(r2,rsa->q,BN_value_one()))
+               goto err;       /* q-1 */
+       if (!BN_mul(r0,r1,r2,ctx))
+               goto err;       /* (p-1)(q-1) */
+
+       if (!BN_gcd(r3, r1, r2, ctx))
+               goto err;
+
+       if (!BN_div(r0, NULL, r0, r3, ctx))
+               goto err;       /* LCM((p-1)(q-1)) */
+
+       ctx2 = BN_CTX_new();
+       if (!ctx2)
+               goto err;
+
+       rsa->d=BN_mod_inverse(NULL,rsa->e,r0,ctx2);     /* d */
+       if (rsa->d == NULL)
+               goto err;
+
+       /* calculate d mod (p-1) */
+       rsa->dmp1=BN_new();
+       if (rsa->dmp1 == NULL)
+               goto err;
+       if (!BN_mod(rsa->dmp1,rsa->d,r1,ctx))
+               goto err;
+
+       /* calculate d mod (q-1) */
+       rsa->dmq1=BN_new();
+       if (rsa->dmq1 == NULL)
+               goto err;
+       if (!BN_mod(rsa->dmq1,rsa->d,r2,ctx))
+               goto err;
+
+       /* calculate inverse of q mod p */
+       rsa->iqmp=BN_mod_inverse(NULL,rsa->q,rsa->p,ctx2);
+
+       err:
+       if (ctx)
+               {
+               BN_CTX_end(ctx);
+               BN_CTX_free(ctx);
+               }
+       if (ctx2)
+               BN_CTX_free(ctx2);
+       /* If this is set all calls successful */
+       if (rsa->iqmp != NULL)
+               return 1;
+
+       return 0;
+
+       }
+
+RSA *RSA_X931_generate_key(FIPS_RSA_SIZE_T bits, const BIGNUM *e,
+            void (*cb)(int,int,void *), void *cb_arg)
+       {
+       RSA *rsa = NULL;
+       int ok = 0;
+       BIGNUM *Xp = NULL, *Xq = NULL;
+       BN_CTX *ctx = NULL;
+       
+       if (bits < 1024)
+           {
+           FIPSerr(FIPS_F_RSA_X931_GENERATE_KEY,FIPS_R_KEY_TOO_SHORT);
+           return NULL;
+           }
+
+       if (bits & 0xff)
+           {
+           FIPSerr(FIPS_F_RSA_X931_GENERATE_KEY,FIPS_R_INVALID_KEY_LENGTH);
+           return NULL;
+           }
+
+       if(FIPS_selftest_failed())
+           {
+           FIPSerr(FIPS_F_RSA_X931_GENERATE_KEY,FIPS_R_FIPS_SELFTEST_FAILED);
+           return NULL;
+           }
+
+       ctx = BN_CTX_new();
+       if (!ctx)
+               goto error;
+
+       BN_CTX_start(ctx);
+       Xp = BN_CTX_get(ctx);
+       Xq = BN_CTX_get(ctx);
+       if (!BN_X931_generate_Xpq(Xp, Xq, bits, ctx))
+               goto error;
+
+       rsa = RSA_new();
+       if (!rsa)
+               goto error;
+       rsa->p = BN_new();
+       rsa->q = BN_new();
+       if (!rsa->p || !rsa->q)
+               goto error;
+
+       /* Generate two primes from Xp, Xq */
+
+       if (!BN_X931_generate_prime(rsa->p, NULL, NULL, NULL, NULL, Xp,
+                                       e, ctx, cb, cb_arg))
+               goto error;
+
+       if (!BN_X931_generate_prime(rsa->q, NULL, NULL, NULL, NULL, Xq,
+                                       e, ctx, cb, cb_arg))
+               goto error;
+
+       /* Since rsa->p and rsa->q are valid this call will just derive
+        * remaining RSA components.
+        */
+
+       if (!RSA_X931_derive(rsa, NULL, NULL, NULL, NULL, cb, cb_arg,
+                               NULL, NULL, NULL, NULL, NULL, NULL, e))
+               goto error;
+
+       if(!fips_check_rsa(rsa))
+           goto error;
+
+       ok = 1;
+
+       error:
+       if (ctx)
+               {
+               BN_CTX_end(ctx);
+               BN_CTX_free(ctx);
+               }
+
+       if (ok)
+               return rsa;
+
+       if (rsa)
+               RSA_free(rsa);
+
+       return NULL;
+
+       }
+
diff --git a/fips/rsa/fips_rsagtest.c b/fips/rsa/fips_rsagtest.c
new file mode 100644 (file)
index 0000000..f3b05aa
--- /dev/null
@@ -0,0 +1,420 @@
+/* fips_rsagtest.c */
+/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+ * project 2005.
+ */
+/* ====================================================================
+ * Copyright (c) 2005 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <openssl/bio.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+#include <openssl/err.h>
+#include <openssl/x509v3.h>
+
+#ifndef OPENSSL_FIPS
+
+int main(int argc, char *argv[])
+{
+    printf("No FIPS RSA support\n");
+    return(0);
+}
+
+#else
+
+extern int RSA_X931_derive(RSA *rsa, BIGNUM *p1, BIGNUM *p2, BIGNUM *q1, BIGNUM *q2,
+                       void (*cb)(int, int, void *), void *cb_arg,
+                       const BIGNUM *Xp1, const BIGNUM *Xp2, const BIGNUM *Xp,
+                       const BIGNUM *Xq1, const BIGNUM *Xq2, const BIGNUM *Xq,
+                       const BIGNUM *e);
+
+int rsa_test(BIO *err, BIO *out, BIO *in);
+static int rsa_printkey1(BIO *err, BIO *out, RSA *rsa,
+               BIGNUM *Xp1, BIGNUM *Xp2, BIGNUM *Xp,
+               BIGNUM *e);
+static int rsa_printkey2(BIO *err, BIO *out, RSA *rsa,
+               BIGNUM *Xq1, BIGNUM *Xq2, BIGNUM *Xq);
+
+int main(int argc, char **argv)
+       {
+       BIO *in = NULL, *out = NULL, *err = NULL;
+
+       int ret = 1;
+       ERR_load_crypto_strings();
+
+       err = BIO_new_fp(stderr, BIO_NOCLOSE);
+
+       if (!err)
+               {
+               fprintf(stderr, "FATAL stderr initialization error\n");
+               goto end;
+               }
+
+       if(!FIPS_mode_set(1,argv[0]))
+               {
+               ERR_print_errors(err);
+               goto end;
+               }
+
+       if (argc == 1)
+               in = BIO_new_fp(stdin, BIO_NOCLOSE);
+       else
+               in = BIO_new_file(argv[1], "r");
+
+       if (argc < 2)
+               out = BIO_new_fp(stdout, BIO_NOCLOSE);
+       else
+               out = BIO_new_file(argv[2], "w");
+
+       if (!in)
+               {
+               BIO_printf(err, "FATAL input initialization error\n");
+               goto end;
+               }
+
+       if (!out)
+               {
+               fprintf(stderr, "FATAL output initialization error\n");
+               goto end;
+               }
+
+       if (!rsa_test(err, out, in))
+               {
+               fprintf(stderr, "FATAL RSAVTEST file processing error\n");
+               goto end;
+               }
+       else
+               ret = 0;
+
+       end:
+
+       if (ret && err)
+               ERR_print_errors(err);
+
+       if (in)
+               BIO_free(in);
+       if (out)
+               BIO_free(out);
+       if (err)
+               BIO_free(err);
+
+       return ret;
+
+       }
+
+
+static void do_bn_print(BIO *out, const char *name, BIGNUM *b)
+       {
+       char *htmp, *p;
+       /* Can't use BN_print_fp because it uses upper case so
+        * use BN_bn2hex() and convert.
+        */
+       htmp = BN_bn2hex(b);
+       for(p = htmp; *p; p++)
+               {
+               if (isupper(*p))
+                       *p = tolower(*p);
+               }
+       BIO_printf(out, "%s = %s\n", name, htmp);
+       OPENSSL_free(htmp);
+       }
+
+#define RSA_TEST_MAXLINELEN    10240
+
+int rsa_test(BIO *err, BIO *out, BIO *in)
+       {
+       char *linebuf, *olinebuf, *p, *q;
+       char *keyword, *value;
+       RSA *rsa = NULL;
+       BIGNUM *Xp1 = NULL, *Xp2 = NULL, *Xp = NULL;
+       BIGNUM *Xq1 = NULL, *Xq2 = NULL, *Xq = NULL;
+       BIGNUM *e = NULL;
+       int ret = 0;
+       int lnum = 0;
+
+       olinebuf = OPENSSL_malloc(RSA_TEST_MAXLINELEN);
+       linebuf = OPENSSL_malloc(RSA_TEST_MAXLINELEN);
+
+       if (!linebuf || !olinebuf)
+               goto error;
+
+       while (BIO_gets(in, olinebuf, RSA_TEST_MAXLINELEN) > 0)
+               {
+               lnum++;
+               strcpy(linebuf, olinebuf);
+               keyword = linebuf;
+               /* Skip leading space */
+               while (isspace((unsigned char)*keyword))
+                       keyword++;
+
+               /* Look for = sign */
+               p = strchr(linebuf, '=');
+
+               /* If no = or starts with [ (for [foo = bar] line) just copy */
+               if (!p || *keyword=='[')
+                       {
+                       if (!BIO_puts(out, olinebuf))
+                               goto error;
+                       continue;
+                       }
+
+               q = p - 1;
+
+               /* Remove trailing space */
+               while (isspace((unsigned char)*q))
+                       *q-- = 0;
+
+
+               value = p + 1;
+
+               /* Remove leading space from value */
+               while (isspace((unsigned char)*value))
+                       value++;
+
+               /* Remove trailing space from value */
+               p = value + strlen(value) - 1;
+
+               while (*p == '\n' || isspace((unsigned char)*p))
+                       *p-- = 0;
+
+               if (!strcmp(keyword, "xp1"))
+                       {
+                       if (Xp1 || !BN_hex2bn(&Xp1,value))
+                               goto parse_error;
+                       }
+               else if (!strcmp(keyword, "xp2"))
+                       {
+                       if (Xp2 || !BN_hex2bn(&Xp2,value))
+                               goto parse_error;
+                       }
+               else if (!strcmp(keyword, "Xp"))
+                       {
+                       if (Xp || !BN_hex2bn(&Xp,value))
+                               goto parse_error;
+                       }
+               else if (!strcmp(keyword, "xq1"))
+                       {
+                       if (Xq1 || !BN_hex2bn(&Xq1,value))
+                               goto parse_error;
+                       }
+               else if (!strcmp(keyword, "xq2"))
+                       {
+                       if (Xq2 || !BN_hex2bn(&Xq2,value))
+                               goto parse_error;
+                       }
+               else if (!strcmp(keyword, "Xq"))
+                       {
+                       if (Xq || !BN_hex2bn(&Xq,value))
+                               goto parse_error;
+                       }
+               else if (!strcmp(keyword, "e"))
+                       {
+                       if (e || !BN_hex2bn(&e,value))
+                               goto parse_error;
+                       }
+               else if (!strcmp(keyword, "p1"))
+                       continue;
+               else if (!strcmp(keyword, "p2"))
+                       continue;
+               else if (!strcmp(keyword, "p"))
+                       continue;
+               else if (!strcmp(keyword, "q1"))
+                       continue;
+               else if (!strcmp(keyword, "q2"))
+                       continue;
+               else if (!strcmp(keyword, "q"))
+                       continue;
+               else if (!strcmp(keyword, "n"))
+                       continue;
+               else if (!strcmp(keyword, "d"))
+                       continue;
+               else
+                       goto parse_error;
+
+               BIO_puts(out, olinebuf);
+
+               if (e && Xp1 && Xp2 && Xp)
+                       {
+                       rsa = RSA_new();
+                       if (!rsa)
+                               goto error;
+                       if (!rsa_printkey1(err, out, rsa, Xp1, Xp2, Xp, e))
+                               goto error;
+                       BN_free(Xp1);
+                       Xp1 = NULL;
+                       BN_free(Xp2);
+                       Xp2 = NULL;
+                       BN_free(Xp);
+                       Xp = NULL;
+                       BN_free(e);
+                       e = NULL;
+                       }
+
+               if (rsa && Xq1 && Xq2 && Xq)
+                       {
+                       if (!rsa_printkey2(err, out, rsa, Xq1, Xq2, Xq))
+                               goto error;
+                       BN_free(Xq1);
+                       Xq1 = NULL;
+                       BN_free(Xq2);
+                       Xq2 = NULL;
+                       BN_free(Xq);
+                       Xq = NULL;
+                       RSA_free(rsa);
+                       rsa = NULL;
+                       }
+               }
+
+       ret = 1;
+
+       error:
+
+       if (olinebuf)
+               OPENSSL_free(olinebuf);
+       if (linebuf)
+               OPENSSL_free(linebuf);
+
+       if (Xp1)
+               BN_free(Xp1);
+       if (Xp2)
+               BN_free(Xp2);
+       if (Xp)
+               BN_free(Xp);
+       if (Xq1)
+               BN_free(Xq1);
+       if (Xq1)
+               BN_free(Xq1);
+       if (Xq2)
+               BN_free(Xq2);
+       if (Xq)
+               BN_free(Xq);
+       if (e)
+               BN_free(e);
+       if (rsa)
+               RSA_free(rsa);
+
+       return ret;
+
+       parse_error:
+
+       BIO_printf(err, "FATAL parse error processing line %d\n", lnum);
+
+       goto error;
+
+       }
+
+static int rsa_printkey1(BIO *err, BIO *out, RSA *rsa,
+               BIGNUM *Xp1, BIGNUM *Xp2, BIGNUM *Xp,
+               BIGNUM *e)
+       {
+       int ret = 0;
+       BIGNUM *p1 = NULL, *p2 = NULL;
+       p1 = BN_new();
+       p2 = BN_new();
+       if (!p1 || !p2)
+               goto error;
+
+       if (!RSA_X931_derive(rsa, p1, p2, NULL, NULL, 0, NULL, Xp1, Xp2, Xp,
+                                                       NULL, NULL, NULL, e))
+               goto error;
+
+       do_bn_print(out, "p1", p1);
+       do_bn_print(out, "p2", p2);
+       do_bn_print(out, "p", rsa->p);
+
+       ret = 1;
+
+       error:
+       if (p1)
+               BN_free(p1);
+       if (p2)
+               BN_free(p2);
+
+       return ret;
+       }
+
+static int rsa_printkey2(BIO *err, BIO *out, RSA *rsa,
+               BIGNUM *Xq1, BIGNUM *Xq2, BIGNUM *Xq)
+       {
+       int ret = 0;
+       BIGNUM *q1 = NULL, *q2 = NULL;
+       q1 = BN_new();
+       q2 = BN_new();
+       if (!q1 || !q2)
+               goto error;
+
+       if (!RSA_X931_derive(rsa, NULL, NULL, q1, q2, 0, NULL, NULL, NULL, NULL,
+                                                       Xq1, Xq2, Xq, NULL))
+               goto error;
+
+       do_bn_print(out, "q1", q1);
+       do_bn_print(out, "q2", q2);
+       do_bn_print(out, "q", rsa->q);
+       do_bn_print(out, "n", rsa->n);
+       do_bn_print(out, "d", rsa->d);
+
+       ret = 1;
+
+       error:
+       if (q1)
+               BN_free(q1);
+       if (q2)
+               BN_free(q2);
+
+       return ret;
+       }
+
+#endif
index 9956a38fbe4b1b905316dd89cbc26d618777dbe0..3405d7e5c94ba886fdbd24ed98ca3e2527aaba56 100644 (file)
@@ -67,6 +67,7 @@ FIPS_AESTEST= fips_aesavs
 FIPS_HMACTEST= fips_hmactest
 FIPS_RSAVTEST= fips_rsavtest
 FIPS_RSASTEST= fips_rsastest
+FIPS_RSAGTEST= fips_rsagtest
 
 TESTS=         alltests
 
@@ -77,7 +78,7 @@ EXE=  $(BNTEST)$(EXE_EXT) $(ECTEST)$(EXE_EXT) $(IDEATEST)$(EXE_EXT) $(MD2TEST)$(E
        $(BFTEST)$(EXE_EXT) $(CASTTEST)$(EXE_EXT) $(SSLTEST)$(EXE_EXT) $(EXPTEST)$(EXE_EXT) $(DSATEST)$(EXE_EXT) $(FIPS_DSATEST)$(EXE_EXT) $(RSATEST)$(EXE_EXT) \
        $(EVPTEST)$(EXE_EXT) $(FIPS_AESTEST)$(EXE_EXT) \
        $(FIPS_HMACTEST)$(EXE_EXT) $(FIPS_RSAVTEST)$(EXE_EXT) \
-       $(FIPS_RSASTEST)$(EXE_EXT)
+       $(FIPS_RSASTEST)$(EXE_EXT) $(FIPS_RSAGTEST)$(EXE_EXT)
 
 # $(METHTEST)$(EXE_EXT)
 
@@ -88,7 +89,7 @@ OBJ=  $(BNTEST).o $(ECTEST).o $(IDEATEST).o $(MD2TEST).o $(MD4TEST).o $(MD5TEST).
        $(RANDTEST).o $(FIPS_RANDTEST).o $(DHTEST).o $(ENGINETEST).o $(CASTTEST).o \
        $(BFTEST).o  $(SSLTEST).o  $(DSATEST).o $(FIPS_DSATEST).o $(EXPTEST).o $(RSATEST).o \
        $(EVPTEST).o $(FIPS_AESTEST).o $(FIPS_HMACTEST).o $(FIPS_RSAVTEST).o \
-       $(FIPS_RSASTEST).o
+       $(FIPS_RSASTEST).o $(FIPS_RSAGTEST).o
 SRC=   $(BNTEST).c $(ECTEST).c $(IDEATEST).c $(MD2TEST).c  $(MD4TEST).c $(MD5TEST).c \
        $(HMACTEST).c \
        $(RC2TEST).c $(RC4TEST).c $(RC5TEST).c \
@@ -96,7 +97,7 @@ SRC=  $(BNTEST).c $(ECTEST).c $(IDEATEST).c $(MD2TEST).c  $(MD4TEST).c $(MD5TEST)
        $(RANDTEST).c $(FIPS_RANDTEST).c $(DHTEST).c $(ENGINETEST).c $(CASTTEST).c \
        $(BFTEST).c  $(SSLTEST).c $(DSATEST).c $(FIPS_DSATEST).c $(EXPTEST).c $(RSATEST).c \
        $(EVPTEST).c $(FIPS_AESTEST).c $(FIPS_HMACTEST).c $(FIPS_RSAVTEST).c \
-       $(FIPS_RSASTEST).c
+       $(FIPS_RSASTEST).c $(FIPS_RSAGTEST).c
 
 EXHEADER= 
 HEADER=        $(EXHEADER)
@@ -351,6 +352,12 @@ $(FIPS_RSASTEST)$(EXE_EXT): $(FIPS_RSASTEST).o $(DLIBCRYPTO)
          TOP=$(TOP) $(TOP)/fips/openssl_fips_fingerprint $(TOP)/libcrypto.a $(FIPS_RSASTEST); \
        fi
 
+$(FIPS_RSAGTEST)$(EXE_EXT): $(FIPS_RSAGTEST).o $(DLIBCRYPTO)
+       @target=$(FIPS_RSAGTEST); $(BUILD_CMD)
+       if egrep 'define OPENSSL_FIPS' $(TOP)/include/openssl/opensslconf.h > /dev/null; then \
+         TOP=$(TOP) $(TOP)/fips/openssl_fips_fingerprint $(TOP)/libcrypto.a $(FIPS_RSAGTEST); \
+       fi
+
 $(RSATEST)$(EXE_EXT): $(RSATEST).o $(DLIBCRYPTO)
        @target=$(RSATEST); $(BUILD_CMD)