--- rsaref/source/r_keygen.c 2018/04/24 16:37:52 1.1 +++ rsaref/source/r_keygen.c 2018/04/24 16:38:20 1.1.1.2 @@ -1,8 +1,8 @@ /* R_KEYGEN.C - key-pair generation for RSAREF */ -/* Copyright (C) 1991-2 RSA Laboratories, a division of RSA Data - Security, Inc. All rights reserved. +/* Copyright (C) RSA Laboratories, a division of RSA Data Security, + Inc., created 1991. All rights reserved. */ #include "global.h" @@ -11,8 +11,10 @@ #include "nn.h" #include "prime.h" -static int GenerateDigits PROTO_LIST - ((NN_DIGIT *, unsigned int, R_RANDOM_STRUCT *)); +static int RSAFilter PROTO_LIST + ((NN_DIGIT *, unsigned int, NN_DIGIT *, unsigned int)); +static int RelativelyPrime PROTO_LIST + ((NN_DIGIT *, unsigned int, NN_DIGIT *, unsigned int)); /* Generates an RSA key pair with a given length and public exponent. */ @@ -25,27 +27,54 @@ R_RANDOM_STRUCT *randomStruct; NN_DIGIT d[MAX_NN_DIGITS], dP[MAX_NN_DIGITS], dQ[MAX_NN_DIGITS], e[MAX_NN_DIGITS], n[MAX_NN_DIGITS], p[MAX_NN_DIGITS], phiN[MAX_NN_DIGITS], pMinus1[MAX_NN_DIGITS], q[MAX_NN_DIGITS], qInv[MAX_NN_DIGITS], - qMinus1[MAX_NN_DIGITS], t[MAX_NN_DIGITS]; + qMinus1[MAX_NN_DIGITS], t[MAX_NN_DIGITS], u[MAX_NN_DIGITS], + v[MAX_NN_DIGITS]; int status; - unsigned int nDigits, pDigits; + unsigned int nDigits, pBits, pDigits, qBits; if ((protoKey->bits < MIN_RSA_MODULUS_BITS) || (protoKey->bits > MAX_RSA_MODULUS_BITS)) return (RE_MODULUS_LEN); nDigits = (protoKey->bits + NN_DIGIT_BITS - 1) / NN_DIGIT_BITS; pDigits = (nDigits + 1) / 2; - - /* Generate random RSA primes p and q so that product has correct length. - */ - if ((status = GenerateDigits (p, pDigits, randomStruct)) || - (status = GenerateDigits (q, pDigits, randomStruct))) - return (status); + pBits = (protoKey->bits + 1) / 2; + qBits = protoKey->bits - pBits; /* NOTE: for 65537, this assumes NN_DIGIT is at least 17 bits. */ NN_ASSIGN_DIGIT (e, protoKey->useFermat4 ? (NN_DIGIT)65537 : (NN_DIGIT)3, nDigits); - FindRSAPrime (p, (protoKey->bits + 1) / 2, p, pDigits, e, 1); - FindRSAPrime (q, protoKey->bits / 2, q, pDigits, e, 1); + + /* Generate prime p between 3*2^(pBits-2) and 2^pBits-1, searching + in steps of 2, until one satisfies gcd (p-1, e) = 1. + */ + NN_Assign2Exp (t, pBits-1, pDigits); + NN_Assign2Exp (u, pBits-2, pDigits); + NN_Add (t, t, u, pDigits); + NN_ASSIGN_DIGIT (v, 1, pDigits); + NN_Sub (v, t, v, pDigits); + NN_Add (u, u, v, pDigits); + NN_ASSIGN_DIGIT (v, 2, pDigits); + do { + if (status = GeneratePrime (p, t, u, v, pDigits, randomStruct)) + return (status); + } + while (! RSAFilter (p, pDigits, e, 1)); + + /* Generate prime q between 3*2^(qBits-2) and 2^qBits-1, searching + in steps of 2, until one satisfies gcd (q-1, e) = 1. + */ + NN_Assign2Exp (t, qBits-1, pDigits); + NN_Assign2Exp (u, qBits-2, pDigits); + NN_Add (t, t, u, pDigits); + NN_ASSIGN_DIGIT (v, 1, pDigits); + NN_Sub (v, t, v, pDigits); + NN_Add (u, u, v, pDigits); + NN_ASSIGN_DIGIT (v, 2, pDigits); + do { + if (status = GeneratePrime (q, t, u, v, pDigits, randomStruct)) + return (status); + } + while (! RSAFilter (q, pDigits, e, 1)); /* Sort so that p > q. (p = q case is extremely unlikely.) */ @@ -102,21 +131,52 @@ R_RANDOM_STRUCT *randomStruct; return (0); } -static int GenerateDigits (a, digits, randomStruct) -NN_DIGIT *a; -R_RANDOM_STRUCT *randomStruct; -unsigned int digits; +/* Returns nonzero iff GCD (a-1, b) = 1. + + Lengths: a[aDigits], b[bDigits]. + Assumes aDigits < MAX_NN_DIGITS, bDigits < MAX_NN_DIGITS. + */ +static int RSAFilter (a, aDigits, b, bDigits) +NN_DIGIT *a, *b; +unsigned int aDigits, bDigits; +{ + int status; + NN_DIGIT aMinus1[MAX_NN_DIGITS], t[MAX_NN_DIGITS]; + + NN_ASSIGN_DIGIT (t, 1, aDigits); + NN_Sub (aMinus1, a, t, aDigits); + + status = RelativelyPrime (aMinus1, aDigits, b, bDigits); + + /* Zeroize sensitive information. + */ + R_memset ((POINTER)aMinus1, 0, sizeof (aMinus1)); + + return (status); +} + +/* Returns nonzero iff a and b are relatively prime. + + Lengths: a[aDigits], b[bDigits]. + Assumes aDigits >= bDigits, aDigits < MAX_NN_DIGITS. + */ +static int RelativelyPrime (a, aDigits, b, bDigits) +NN_DIGIT *a, *b; +unsigned int aDigits, bDigits; { int status; - unsigned char t[MAX_RSA_MODULUS_LEN]; + NN_DIGIT t[MAX_NN_DIGITS], u[MAX_NN_DIGITS]; + + NN_AssignZero (t, aDigits); + NN_Assign (t, b, bDigits); + NN_Gcd (t, a, t, aDigits); + NN_ASSIGN_DIGIT (u, 1, aDigits); - if (status = R_GenerateBytes (t, digits * NN_DIGIT_LEN, randomStruct)) - return (status); - NN_Decode (a, digits, t, digits * NN_DIGIT_LEN); + status = NN_EQUAL (t, u, aDigits); /* Zeroize sensitive information. */ R_memset ((POINTER)t, 0, sizeof (t)); - return (0); + return (status); }