~ubuntu-branches/ubuntu/maverick/openssl/maverick

« back to all changes in this revision

Viewing changes to fips/rsa/fips_rsa_gen.c

  • Committer: Bazaar Package Importer
  • Author(s): Christoph Martin
  • Date: 2004-12-16 18:41:29 UTC
  • mto: (11.1.1 lenny)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20041216184129-z7xjkul57mh1jiha
Tags: upstream-0.9.7e
ImportĀ upstreamĀ versionĀ 0.9.7e

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* crypto/rsa/rsa_gen.c */
 
2
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
 
3
 * All rights reserved.
 
4
 *
 
5
 * This package is an SSL implementation written
 
6
 * by Eric Young (eay@cryptsoft.com).
 
7
 * The implementation was written so as to conform with Netscapes SSL.
 
8
 * 
 
9
 * This library is free for commercial and non-commercial use as long as
 
10
 * the following conditions are aheared to.  The following conditions
 
11
 * apply to all code found in this distribution, be it the RC4, RSA,
 
12
 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
 
13
 * included with this distribution is covered by the same copyright terms
 
14
 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
 
15
 * 
 
16
 * Copyright remains Eric Young's, and as such any Copyright notices in
 
17
 * the code are not to be removed.
 
18
 * If this package is used in a product, Eric Young should be given attribution
 
19
 * as the author of the parts of the library used.
 
20
 * This can be in the form of a textual message at program startup or
 
21
 * in documentation (online or textual) provided with the package.
 
22
 * 
 
23
 * Redistribution and use in source and binary forms, with or without
 
24
 * modification, are permitted provided that the following conditions
 
25
 * are met:
 
26
 * 1. Redistributions of source code must retain the copyright
 
27
 *    notice, this list of conditions and the following disclaimer.
 
28
 * 2. Redistributions in binary form must reproduce the above copyright
 
29
 *    notice, this list of conditions and the following disclaimer in the
 
30
 *    documentation and/or other materials provided with the distribution.
 
31
 * 3. All advertising materials mentioning features or use of this software
 
32
 *    must display the following acknowledgement:
 
33
 *    "This product includes cryptographic software written by
 
34
 *     Eric Young (eay@cryptsoft.com)"
 
35
 *    The word 'cryptographic' can be left out if the rouines from the library
 
36
 *    being used are not cryptographic related :-).
 
37
 * 4. If you include any Windows specific code (or a derivative thereof) from 
 
38
 *    the apps directory (application code) you must include an acknowledgement:
 
39
 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
 
40
 * 
 
41
 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
 
42
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
43
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
44
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 
45
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
46
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 
47
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
48
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
49
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 
50
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 
51
 * SUCH DAMAGE.
 
52
 * 
 
53
 * The licence and distribution terms for any publically available version or
 
54
 * derivative of this code cannot be changed.  i.e. this code cannot simply be
 
55
 * copied and put under another distribution licence
 
56
 * [including the GNU Public Licence.]
 
57
 */
 
58
 
 
59
#include <stdio.h>
 
60
#include <string.h>
 
61
#include <time.h>
 
62
#include <openssl/err.h>
 
63
#include <openssl/bn.h>
 
64
#include <openssl/rsa.h>
 
65
#include <openssl/fips.h>
 
66
 
 
67
#ifdef OPENSSL_FIPS
 
68
 
 
69
static int fips_check_rsa(RSA *rsa)
 
70
    {
 
71
    int n;
 
72
    unsigned char ctext[256];
 
73
    unsigned char ptext[256];
 
74
    /* The longest we can have with OAEP padding and a 512 bit key */
 
75
    static unsigned char original_ptext[] =
 
76
        "\x01\x23\x45\x67\x89\xab\xcd\xef\x12\x34\x56\x78\x9a\xbc\xde\xf0"
 
77
        "\x23\x45\x67\x89\xab\xcd";
 
78
 
 
79
    /* this will fail for keys shorter than 512 bits */
 
80
    n=RSA_public_encrypt(sizeof(original_ptext)-1,original_ptext,ctext,rsa,
 
81
                         RSA_PKCS1_OAEP_PADDING);
 
82
    if(n < 0)
 
83
        {
 
84
        ERR_print_errors_fp(stderr);
 
85
        exit(1);
 
86
        }
 
87
    if(!memcmp(ctext,original_ptext,n))
 
88
        {
 
89
        FIPSerr(FIPS_F_FIPS_CHECK_RSA,FIPS_R_PAIRWISE_TEST_FAILED);
 
90
        return 0;
 
91
        }
 
92
    n=RSA_private_decrypt(n,ctext,ptext,rsa,RSA_PKCS1_OAEP_PADDING);
 
93
    if(n < 0)
 
94
        {
 
95
        ERR_print_errors_fp(stderr);
 
96
        exit(1);
 
97
        }
 
98
    if(n != sizeof(original_ptext)-1 || memcmp(ptext,original_ptext,n))
 
99
        {
 
100
        FIPSerr(FIPS_F_FIPS_CHECK_RSA,FIPS_R_PAIRWISE_TEST_FAILED);
 
101
        return 0;
 
102
        }
 
103
 
 
104
    return 1;
 
105
    }
 
106
 
 
107
RSA *RSA_generate_key(FIPS_RSA_SIZE_T bits, unsigned long e_value,
 
108
             void (*callback)(int,int,void *), void *cb_arg)
 
109
        {
 
110
        RSA *rsa=NULL;
 
111
        BIGNUM *r0=NULL,*r1=NULL,*r2=NULL,*r3=NULL,*tmp;
 
112
        int bitsp,bitsq,ok= -1,n=0,i;
 
113
        BN_CTX *ctx=NULL,*ctx2=NULL;
 
114
 
 
115
        if(FIPS_selftest_failed())
 
116
            {
 
117
            FIPSerr(FIPS_F_RSA_GENERATE_KEY,FIPS_R_FIPS_SELFTEST_FAILED);
 
118
            return NULL;
 
119
            }
 
120
            
 
121
        ctx=BN_CTX_new();
 
122
        if (ctx == NULL) goto err;
 
123
        ctx2=BN_CTX_new();
 
124
        if (ctx2 == NULL) goto err;
 
125
        BN_CTX_start(ctx);
 
126
        r0 = BN_CTX_get(ctx);
 
127
        r1 = BN_CTX_get(ctx);
 
128
        r2 = BN_CTX_get(ctx);
 
129
        r3 = BN_CTX_get(ctx);
 
130
        if (r3 == NULL) goto err;
 
131
 
 
132
        bitsp=(bits+1)/2;
 
133
        bitsq=bits-bitsp;
 
134
        rsa=RSA_new();
 
135
        if (rsa == NULL) goto err;
 
136
 
 
137
        /* set e */ 
 
138
        rsa->e=BN_new();
 
139
        if (rsa->e == NULL) goto err;
 
140
 
 
141
#if 1
 
142
        /* The problem is when building with 8, 16, or 32 BN_ULONG,
 
143
         * unsigned long can be larger */
 
144
        for (i=0; i<sizeof(unsigned long)*8; i++)
 
145
                {
 
146
                if (e_value & (1UL<<i))
 
147
                        BN_set_bit(rsa->e,i);
 
148
                }
 
149
#else
 
150
        if (!BN_set_word(rsa->e,e_value)) goto err;
 
151
#endif
 
152
 
 
153
        /* generate p and q */
 
154
        for (;;)
 
155
                {
 
156
                rsa->p=BN_generate_prime(NULL,bitsp,0,NULL,NULL,callback,cb_arg);
 
157
                if (rsa->p == NULL) goto err;
 
158
                if (!BN_sub(r2,rsa->p,BN_value_one())) goto err;
 
159
                if (!BN_gcd(r1,r2,rsa->e,ctx)) goto err;
 
160
                if (BN_is_one(r1)) break;
 
161
                if (callback != NULL) callback(2,n++,cb_arg);
 
162
                BN_free(rsa->p);
 
163
                }
 
164
        if (callback != NULL) callback(3,0,cb_arg);
 
165
        for (;;)
 
166
                {
 
167
                rsa->q=BN_generate_prime(NULL,bitsq,0,NULL,NULL,callback,cb_arg);
 
168
                if (rsa->q == NULL) goto err;
 
169
                if (!BN_sub(r2,rsa->q,BN_value_one())) goto err;
 
170
                if (!BN_gcd(r1,r2,rsa->e,ctx)) goto err;
 
171
                if (BN_is_one(r1) && (BN_cmp(rsa->p,rsa->q) != 0))
 
172
                        break;
 
173
                if (callback != NULL) callback(2,n++,cb_arg);
 
174
                BN_free(rsa->q);
 
175
                }
 
176
        if (callback != NULL) callback(3,1,cb_arg);
 
177
        if (BN_cmp(rsa->p,rsa->q) < 0)
 
178
                {
 
179
                tmp=rsa->p;
 
180
                rsa->p=rsa->q;
 
181
                rsa->q=tmp;
 
182
                }
 
183
 
 
184
        /* calculate n */
 
185
        rsa->n=BN_new();
 
186
        if (rsa->n == NULL) goto err;
 
187
        if (!BN_mul(rsa->n,rsa->p,rsa->q,ctx)) goto err;
 
188
 
 
189
        /* calculate d */
 
190
        if (!BN_sub(r1,rsa->p,BN_value_one())) goto err;        /* p-1 */
 
191
        if (!BN_sub(r2,rsa->q,BN_value_one())) goto err;        /* q-1 */
 
192
        if (!BN_mul(r0,r1,r2,ctx)) goto err;    /* (p-1)(q-1) */
 
193
 
 
194
/* should not be needed, since gcd(p-1,e) == 1 and gcd(q-1,e) == 1 */
 
195
/*      for (;;)
 
196
                {
 
197
                if (!BN_gcd(r3,r0,rsa->e,ctx)) goto err;
 
198
                if (BN_is_one(r3)) break;
 
199
 
 
200
                if (1)
 
201
                        {
 
202
                        if (!BN_add_word(rsa->e,2L)) goto err;
 
203
                        continue;
 
204
                        }
 
205
                RSAerr(RSA_F_RSA_GENERATE_KEY,RSA_R_BAD_E_VALUE);
 
206
                goto err;
 
207
                }
 
208
*/
 
209
        rsa->d=BN_mod_inverse(NULL,rsa->e,r0,ctx2);     /* d */
 
210
        if (rsa->d == NULL) goto err;
 
211
 
 
212
        /* calculate d mod (p-1) */
 
213
        rsa->dmp1=BN_new();
 
214
        if (rsa->dmp1 == NULL) goto err;
 
215
        if (!BN_mod(rsa->dmp1,rsa->d,r1,ctx)) goto err;
 
216
 
 
217
        /* calculate d mod (q-1) */
 
218
        rsa->dmq1=BN_new();
 
219
        if (rsa->dmq1 == NULL) goto err;
 
220
        if (!BN_mod(rsa->dmq1,rsa->d,r2,ctx)) goto err;
 
221
 
 
222
        /* calculate inverse of q mod p */
 
223
        rsa->iqmp=BN_mod_inverse(NULL,rsa->q,rsa->p,ctx2);
 
224
        if (rsa->iqmp == NULL) goto err;
 
225
 
 
226
        if(!fips_check_rsa(rsa))
 
227
            goto err;
 
228
 
 
229
        ok=1;
 
230
err:
 
231
        if (ok == -1)
 
232
                {
 
233
                RSAerr(RSA_F_RSA_GENERATE_KEY,ERR_LIB_BN);
 
234
                ok=0;
 
235
                }
 
236
        BN_CTX_end(ctx);
 
237
        BN_CTX_free(ctx);
 
238
        BN_CTX_free(ctx2);
 
239
        
 
240
        if (!ok)
 
241
                {
 
242
                if (rsa != NULL) RSA_free(rsa);
 
243
                return(NULL);
 
244
                }
 
245
        else
 
246
                return(rsa);
 
247
        }
 
248
 
 
249
#endif