rsa_x931g.c revision 296465
1279264Sdelphij/* crypto/rsa/rsa_gen.c */ 2110010Smarkm/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3110010Smarkm * All rights reserved. 4142429Snectar * 5110010Smarkm * This package is an SSL implementation written 6110010Smarkm * by Eric Young (eay@cryptsoft.com). 7110010Smarkm * The implementation was written so as to conform with Netscapes SSL. 8110010Smarkm * 9110010Smarkm * This library is free for commercial and non-commercial use as long as 10110010Smarkm * the following conditions are aheared to. The following conditions 11110010Smarkm * apply to all code found in this distribution, be it the RC4, RSA, 12110010Smarkm * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13110010Smarkm * included with this distribution is covered by the same copyright terms 14110010Smarkm * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15110010Smarkm * 16110010Smarkm * Copyright remains Eric Young's, and as such any Copyright notices in 17110010Smarkm * the code are not to be removed. 18110010Smarkm * If this package is used in a product, Eric Young should be given attribution 19110010Smarkm * as the author of the parts of the library used. 20215698Ssimon * This can be in the form of a textual message at program startup or 21215698Ssimon * in documentation (online or textual) provided with the package. 22215698Ssimon * 23215698Ssimon * Redistribution and use in source and binary forms, with or without 24215698Ssimon * modification, are permitted provided that the following conditions 25110010Smarkm * are met: 26110010Smarkm * 1. Redistributions of source code must retain the copyright 27110010Smarkm * notice, this list of conditions and the following disclaimer. 28110010Smarkm * 2. Redistributions in binary form must reproduce the above copyright 29110010Smarkm * notice, this list of conditions and the following disclaimer in the 30110010Smarkm * documentation and/or other materials provided with the distribution. 31110010Smarkm * 3. All advertising materials mentioning features or use of this software 32110010Smarkm * must display the following acknowledgement: 33110010Smarkm * "This product includes cryptographic software written by 34110010Smarkm * Eric Young (eay@cryptsoft.com)" 35110010Smarkm * The word 'cryptographic' can be left out if the rouines from the library 36110010Smarkm * being used are not cryptographic related :-). 37110010Smarkm * 4. If you include any Windows specific code (or a derivative thereof) from 38110010Smarkm * the apps directory (application code) you must include an acknowledgement: 39110010Smarkm * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40110010Smarkm * 41279264Sdelphij * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42279264Sdelphij * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43110010Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44110010Smarkm * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45215698Ssimon * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46215698Ssimon * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47215698Ssimon * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48215698Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49142429Snectar * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50215698Ssimon * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51142429Snectar * SUCH DAMAGE. 52142429Snectar * 53279264Sdelphij * The licence and distribution terms for any publically available version or 54279264Sdelphij * derivative of this code cannot be changed. i.e. this code cannot simply be 55279264Sdelphij * copied and put under another distribution licence 56110010Smarkm * [including the GNU Public Licence.] 57279264Sdelphij */ 58279264Sdelphij 59279264Sdelphij#include <stdio.h> 60279264Sdelphij#include <string.h> 61279264Sdelphij#include <time.h> 62279264Sdelphij#include <openssl/err.h> 63215698Ssimon#include <openssl/bn.h> 64279264Sdelphij#include <openssl/rsa.h> 65279264Sdelphij 66279264Sdelphij#ifndef OPENSSL_FIPS 67279264Sdelphij 68279264Sdelphij/* X9.31 RSA key derivation and generation */ 69215698Ssimon 70279264Sdelphijint RSA_X931_derive_ex(RSA *rsa, BIGNUM *p1, BIGNUM *p2, BIGNUM *q1, 71110010Smarkm BIGNUM *q2, const BIGNUM *Xp1, const BIGNUM *Xp2, 72110010Smarkm const BIGNUM *Xp, const BIGNUM *Xq1, const BIGNUM *Xq2, 73110010Smarkm const BIGNUM *Xq, const BIGNUM *e, BN_GENCB *cb) 74110010Smarkm{ 75110010Smarkm BIGNUM *r0 = NULL, *r1 = NULL, *r2 = NULL, *r3 = NULL; 76110010Smarkm BN_CTX *ctx = NULL, *ctx2 = NULL; 77110010Smarkm 78110010Smarkm if (!rsa) 79110010Smarkm goto err; 80110010Smarkm 81110010Smarkm ctx = BN_CTX_new(); 82110010Smarkm if (!ctx) 83110010Smarkm goto err; 84110010Smarkm BN_CTX_start(ctx); 85110010Smarkm 86110010Smarkm r0 = BN_CTX_get(ctx); 87110010Smarkm r1 = BN_CTX_get(ctx); 88110010Smarkm r2 = BN_CTX_get(ctx); 89110010Smarkm r3 = BN_CTX_get(ctx); 90110010Smarkm 91110010Smarkm if (r3 == NULL) 92110010Smarkm goto err; 93110010Smarkm if (!rsa->e) { 94110010Smarkm rsa->e = BN_dup(e); 95110010Smarkm if (!rsa->e) 96110010Smarkm goto err; 97110010Smarkm } else 98110010Smarkm e = rsa->e; 99110010Smarkm 100110010Smarkm /* 101110010Smarkm * If not all parameters present only calculate what we can. This allows 102110010Smarkm * test programs to output selective parameters. 103110010Smarkm */ 104110010Smarkm 105110010Smarkm if (Xp && !rsa->p) { 106110010Smarkm rsa->p = BN_new(); 107110010Smarkm if (!rsa->p) 108110010Smarkm goto err; 109110010Smarkm 110110010Smarkm if (!BN_X931_derive_prime_ex(rsa->p, p1, p2, 111110010Smarkm Xp, Xp1, Xp2, e, ctx, cb)) 112110010Smarkm goto err; 113110010Smarkm } 114110010Smarkm 115110010Smarkm if (Xq && !rsa->q) { 116110010Smarkm rsa->q = BN_new(); 117110010Smarkm if (!rsa->q) 118110010Smarkm goto err; 119110010Smarkm if (!BN_X931_derive_prime_ex(rsa->q, q1, q2, 120110010Smarkm Xq, Xq1, Xq2, e, ctx, cb)) 121110010Smarkm goto err; 122110010Smarkm } 123110010Smarkm 124110010Smarkm if (!rsa->p || !rsa->q) { 125110010Smarkm BN_CTX_end(ctx); 126110010Smarkm BN_CTX_free(ctx); 127110010Smarkm return 2; 128110010Smarkm } 129110010Smarkm 130110010Smarkm /* 131110010Smarkm * Since both primes are set we can now calculate all remaining 132110010Smarkm * components. 133142429Snectar */ 134110010Smarkm 135110010Smarkm /* calculate n */ 136279264Sdelphij rsa->n = BN_new(); 137215698Ssimon if (rsa->n == NULL) 138215698Ssimon goto err; 139215698Ssimon if (!BN_mul(rsa->n, rsa->p, rsa->q, ctx)) 140215698Ssimon goto err; 141110010Smarkm 142110010Smarkm /* calculate d */ 143110010Smarkm if (!BN_sub(r1, rsa->p, BN_value_one())) 144110010Smarkm goto err; /* p-1 */ 145215698Ssimon if (!BN_sub(r2, rsa->q, BN_value_one())) 146215698Ssimon goto err; /* q-1 */ 147215698Ssimon if (!BN_mul(r0, r1, r2, ctx)) 148215698Ssimon goto err; /* (p-1)(q-1) */ 149215698Ssimon 150215698Ssimon if (!BN_gcd(r3, r1, r2, ctx)) 151215698Ssimon goto err; 152110010Smarkm 153110010Smarkm if (!BN_div(r0, NULL, r0, r3, ctx)) 154110010Smarkm goto err; /* LCM((p-1)(q-1)) */ 155110010Smarkm 156110010Smarkm ctx2 = BN_CTX_new(); 157110010Smarkm if (!ctx2) 158110010Smarkm goto err; 159279264Sdelphij 160110010Smarkm rsa->d = BN_mod_inverse(NULL, rsa->e, r0, ctx2); /* d */ 161110010Smarkm if (rsa->d == NULL) 162110010Smarkm goto err; 163110010Smarkm 164110010Smarkm /* calculate d mod (p-1) */ 165110010Smarkm rsa->dmp1 = BN_new(); 166110010Smarkm if (rsa->dmp1 == NULL) 167110010Smarkm goto err; 168110010Smarkm if (!BN_mod(rsa->dmp1, rsa->d, r1, ctx)) 169110010Smarkm goto err; 170110010Smarkm 171110010Smarkm /* calculate d mod (q-1) */ 172110010Smarkm rsa->dmq1 = BN_new(); 173110010Smarkm if (rsa->dmq1 == NULL) 174110010Smarkm goto err; 175110010Smarkm if (!BN_mod(rsa->dmq1, rsa->d, r2, ctx)) 176110010Smarkm goto err; 177110010Smarkm 178110010Smarkm /* calculate inverse of q mod p */ 179110010Smarkm rsa->iqmp = BN_mod_inverse(NULL, rsa->q, rsa->p, ctx2); 180110010Smarkm 181110010Smarkm err: 182110010Smarkm if (ctx) { 183110010Smarkm BN_CTX_end(ctx); 184110010Smarkm BN_CTX_free(ctx); 185110010Smarkm } 186110010Smarkm if (ctx2) 187110010Smarkm BN_CTX_free(ctx2); 188110010Smarkm /* If this is set all calls successful */ 189110010Smarkm if (rsa && rsa->iqmp != NULL) 190110010Smarkm return 1; 191110010Smarkm 192110010Smarkm return 0; 193110010Smarkm 194110010Smarkm} 195110010Smarkm 196110010Smarkmint RSA_X931_generate_key_ex(RSA *rsa, int bits, const BIGNUM *e, 197110010Smarkm BN_GENCB *cb) 198110010Smarkm{ 199110010Smarkm int ok = 0; 200110010Smarkm BIGNUM *Xp = NULL, *Xq = NULL; 201110010Smarkm BN_CTX *ctx = NULL; 202110010Smarkm 203110010Smarkm ctx = BN_CTX_new(); 204110010Smarkm if (!ctx) 205110010Smarkm goto error; 206110010Smarkm 207110010Smarkm BN_CTX_start(ctx); 208110010Smarkm Xp = BN_CTX_get(ctx); 209110010Smarkm Xq = BN_CTX_get(ctx); 210110010Smarkm if (!BN_X931_generate_Xpq(Xp, Xq, bits, ctx)) 211110010Smarkm goto error; 212110010Smarkm 213110010Smarkm rsa->p = BN_new(); 214110010Smarkm rsa->q = BN_new(); 215110010Smarkm if (!rsa->p || !rsa->q) 216110010Smarkm goto error; 217110010Smarkm 218110010Smarkm /* Generate two primes from Xp, Xq */ 219110010Smarkm 220110010Smarkm if (!BN_X931_generate_prime_ex(rsa->p, NULL, NULL, NULL, NULL, Xp, 221110010Smarkm e, ctx, cb)) 222110010Smarkm goto error; 223110010Smarkm 224110010Smarkm if (!BN_X931_generate_prime_ex(rsa->q, NULL, NULL, NULL, NULL, Xq, 225110010Smarkm e, ctx, cb)) 226110010Smarkm goto error; 227110010Smarkm 228110010Smarkm /* 229110010Smarkm * Since rsa->p and rsa->q are valid this call will just derive remaining 230110010Smarkm * RSA components. 231110010Smarkm */ 232110010Smarkm 233142429Snectar if (!RSA_X931_derive_ex(rsa, NULL, NULL, NULL, NULL, 234110010Smarkm NULL, NULL, NULL, NULL, NULL, NULL, e, cb)) 235110010Smarkm goto error; 236110010Smarkm 237110010Smarkm ok = 1; 238110010Smarkm 239110010Smarkm error: 240110010Smarkm if (ctx) { 241110010Smarkm BN_CTX_end(ctx); 242110010Smarkm BN_CTX_free(ctx); 243110010Smarkm } 244142429Snectar 245110010Smarkm if (ok) 246110010Smarkm return 1; 247110010Smarkm 248 return 0; 249 250} 251 252#endif 253