~ubuntu-branches/ubuntu/lucid/openssl/lucid-proposed

« back to all changes in this revision

Viewing changes to fips/fips.c

  • Committer: Bazaar Package Importer
  • Author(s): Kurt Roeckx
  • Date: 2009-06-13 18:15:46 UTC
  • mto: (11.1.5 squeeze)
  • mto: This revision was merged to the branch mainline in revision 34.
  • Revision ID: james.westby@ubuntu.com-20090613181546-vbfntai3b009dl1u
Tags: upstream-0.9.8k
ImportĀ upstreamĀ versionĀ 0.9.8k

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* ====================================================================
 
2
 * Copyright (c) 2003 The OpenSSL Project.  All rights reserved.
 
3
 *
 
4
 * Redistribution and use in source and binary forms, with or without
 
5
 * modification, are permitted provided that the following conditions
 
6
 * are met:
 
7
 *
 
8
 * 1. Redistributions of source code must retain the above copyright
 
9
 *    notice, this list of conditions and the following disclaimer. 
 
10
 *
 
11
 * 2. Redistributions in binary form must reproduce the above copyright
 
12
 *    notice, this list of conditions and the following disclaimer in
 
13
 *    the documentation and/or other materials provided with the
 
14
 *    distribution.
 
15
 *
 
16
 * 3. All advertising materials mentioning features or use of this
 
17
 *    software must display the following acknowledgment:
 
18
 *    "This product includes software developed by the OpenSSL Project
 
19
 *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
 
20
 *
 
21
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
 
22
 *    endorse or promote products derived from this software without
 
23
 *    prior written permission. For written permission, please contact
 
24
 *    openssl-core@openssl.org.
 
25
 *
 
26
 * 5. Products derived from this software may not be called "OpenSSL"
 
27
 *    nor may "OpenSSL" appear in their names without prior written
 
28
 *    permission of the OpenSSL Project.
 
29
 *
 
30
 * 6. Redistributions of any form whatsoever must retain the following
 
31
 *    acknowledgment:
 
32
 *    "This product includes software developed by the OpenSSL Project
 
33
 *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
 
34
 *
 
35
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
 
36
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
37
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 
38
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
 
39
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
40
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 
41
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 
42
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
43
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 
44
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 
45
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 
46
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 
47
 *
 
48
 */
 
49
 
 
50
 
 
51
#include <openssl/rand.h>
 
52
#include <openssl/fips_rand.h>
 
53
#include <openssl/err.h>
 
54
#include <openssl/bio.h>
 
55
#include <openssl/hmac.h>
 
56
#include <openssl/rsa.h>
 
57
#include <string.h>
 
58
#include <limits.h>
 
59
#include "fips_locl.h"
 
60
 
 
61
#ifdef OPENSSL_FIPS
 
62
 
 
63
#include <openssl/fips.h>
 
64
 
 
65
#ifndef PATH_MAX
 
66
#define PATH_MAX 1024
 
67
#endif
 
68
 
 
69
static int fips_selftest_fail;
 
70
static int fips_mode;
 
71
static const void *fips_rand_check;
 
72
 
 
73
static void fips_set_mode(int onoff)
 
74
        {
 
75
        int owning_thread = fips_is_owning_thread();
 
76
 
 
77
        if (fips_is_started())
 
78
                {
 
79
                if (!owning_thread) fips_w_lock();
 
80
                fips_mode = onoff;
 
81
                if (!owning_thread) fips_w_unlock();
 
82
                }
 
83
        }
 
84
 
 
85
static void fips_set_rand_check(const void *rand_check)
 
86
        {
 
87
        int owning_thread = fips_is_owning_thread();
 
88
 
 
89
        if (fips_is_started())
 
90
                {
 
91
                if (!owning_thread) fips_w_lock();
 
92
                fips_rand_check = rand_check;
 
93
                if (!owning_thread) fips_w_unlock();
 
94
                }
 
95
        }
 
96
 
 
97
int FIPS_mode(void)
 
98
        {
 
99
        int ret = 0;
 
100
        int owning_thread = fips_is_owning_thread();
 
101
 
 
102
        if (fips_is_started())
 
103
                {
 
104
                if (!owning_thread) fips_r_lock();
 
105
                ret = fips_mode;
 
106
                if (!owning_thread) fips_r_unlock();
 
107
                }
 
108
        return ret;
 
109
        }
 
110
 
 
111
const void *FIPS_rand_check(void)
 
112
        {
 
113
        const void *ret = 0;
 
114
        int owning_thread = fips_is_owning_thread();
 
115
 
 
116
        if (fips_is_started())
 
117
                {
 
118
                if (!owning_thread) fips_r_lock();
 
119
                ret = fips_rand_check;
 
120
                if (!owning_thread) fips_r_unlock();
 
121
                }
 
122
        return ret;
 
123
        }
 
124
 
 
125
int FIPS_selftest_failed(void)
 
126
    {
 
127
    int ret = 0;
 
128
    if (fips_is_started())
 
129
        {
 
130
        int owning_thread = fips_is_owning_thread();
 
131
 
 
132
        if (!owning_thread) fips_r_lock();
 
133
        ret = fips_selftest_fail;
 
134
        if (!owning_thread) fips_r_unlock();
 
135
        }
 
136
    return ret;
 
137
    }
 
138
 
 
139
/* Selftest failure fatal exit routine. This will be called
 
140
 * during *any* cryptographic operation. It has the minimum
 
141
 * overhead possible to avoid too big a performance hit.
 
142
 */
 
143
 
 
144
void FIPS_selftest_check(void)
 
145
    {
 
146
    if (fips_selftest_fail)
 
147
        {
 
148
        OpenSSLDie(__FILE__,__LINE__, "FATAL FIPS SELFTEST FAILURE");
 
149
        }
 
150
    }
 
151
 
 
152
void fips_set_selftest_fail(void)
 
153
    {
 
154
    fips_selftest_fail = 1;
 
155
    }
 
156
 
 
157
int FIPS_selftest()
 
158
    {
 
159
 
 
160
    return FIPS_selftest_sha1()
 
161
        && FIPS_selftest_hmac()
 
162
        && FIPS_selftest_aes()
 
163
        && FIPS_selftest_des()
 
164
        && FIPS_selftest_rsa()
 
165
        && FIPS_selftest_dsa();
 
166
    }
 
167
 
 
168
extern const void         *FIPS_text_start(),  *FIPS_text_end();
 
169
extern const unsigned char FIPS_rodata_start[], FIPS_rodata_end[];
 
170
unsigned char              FIPS_signature [20] = { 0 };
 
171
static const char          FIPS_hmac_key[]="etaonrishdlcupfm";
 
172
 
 
173
unsigned int FIPS_incore_fingerprint(unsigned char *sig,unsigned int len)
 
174
    {
 
175
    const unsigned char *p1 = FIPS_text_start();
 
176
    const unsigned char *p2 = FIPS_text_end();
 
177
    const unsigned char *p3 = FIPS_rodata_start;
 
178
    const unsigned char *p4 = FIPS_rodata_end;
 
179
    HMAC_CTX c;
 
180
 
 
181
    HMAC_CTX_init(&c);
 
182
    HMAC_Init(&c,FIPS_hmac_key,strlen(FIPS_hmac_key),EVP_sha1());
 
183
 
 
184
    /* detect overlapping regions */
 
185
    if (p1<=p3 && p2>=p3)
 
186
        p3=p1, p4=p2>p4?p2:p4, p1=NULL, p2=NULL;
 
187
    else if (p3<=p1 && p4>=p1)
 
188
        p3=p3, p4=p2>p4?p2:p4, p1=NULL, p2=NULL;
 
189
 
 
190
    if (p1)
 
191
        HMAC_Update(&c,p1,(size_t)p2-(size_t)p1);
 
192
 
 
193
    if (FIPS_signature>=p3 && FIPS_signature<p4)
 
194
        {
 
195
        /* "punch" hole */
 
196
        HMAC_Update(&c,p3,(size_t)FIPS_signature-(size_t)p3);
 
197
        p3 = FIPS_signature+sizeof(FIPS_signature);
 
198
        if (p3<p4)
 
199
            HMAC_Update(&c,p3,(size_t)p4-(size_t)p3);
 
200
        }
 
201
    else
 
202
        HMAC_Update(&c,p3,(size_t)p4-(size_t)p3);
 
203
 
 
204
    HMAC_Final(&c,sig,&len);
 
205
    HMAC_CTX_cleanup(&c);
 
206
 
 
207
    return len;
 
208
    }
 
209
 
 
210
int FIPS_check_incore_fingerprint(void)
 
211
    {
 
212
    unsigned char sig[EVP_MAX_MD_SIZE];
 
213
    unsigned int len;
 
214
#if defined(__sgi) && (defined(__mips) || defined(mips))
 
215
    extern int __dso_displacement[];
 
216
#else
 
217
    extern int OPENSSL_NONPIC_relocated;
 
218
#endif
 
219
 
 
220
    if (FIPS_text_start()==NULL)
 
221
        {
 
222
        FIPSerr(FIPS_F_FIPS_CHECK_INCORE_FINGERPRINT,FIPS_R_UNSUPPORTED_PLATFORM);
 
223
        return 0;
 
224
        }
 
225
 
 
226
    len=FIPS_incore_fingerprint (sig,sizeof(sig));
 
227
 
 
228
    if (len!=sizeof(FIPS_signature) ||
 
229
        memcmp(FIPS_signature,sig,sizeof(FIPS_signature)))
 
230
        {
 
231
        if (FIPS_signature>=FIPS_rodata_start && FIPS_signature<FIPS_rodata_end)
 
232
            FIPSerr(FIPS_F_FIPS_CHECK_INCORE_FINGERPRINT,FIPS_R_FINGERPRINT_DOES_NOT_MATCH_SEGMENT_ALIASING);
 
233
#if defined(__sgi) && (defined(__mips) || defined(mips))
 
234
        else if (__dso_displacement!=NULL)
 
235
#else
 
236
        else if (OPENSSL_NONPIC_relocated)
 
237
#endif
 
238
            FIPSerr(FIPS_F_FIPS_CHECK_INCORE_FINGERPRINT,FIPS_R_FINGERPRINT_DOES_NOT_MATCH_NONPIC_RELOCATED);
 
239
        else
 
240
            FIPSerr(FIPS_F_FIPS_CHECK_INCORE_FINGERPRINT,FIPS_R_FINGERPRINT_DOES_NOT_MATCH);
 
241
        return 0;
 
242
        }
 
243
 
 
244
    return 1;
 
245
    }
 
246
 
 
247
int FIPS_mode_set(int onoff)
 
248
    {
 
249
    int fips_set_owning_thread();
 
250
    int fips_clear_owning_thread();
 
251
    int ret = 0;
 
252
 
 
253
    fips_w_lock();
 
254
    fips_set_started();
 
255
    fips_set_owning_thread();
 
256
 
 
257
    if(onoff)
 
258
        {
 
259
        unsigned char buf[48];
 
260
 
 
261
        fips_selftest_fail = 0;
 
262
 
 
263
        /* Don't go into FIPS mode twice, just so we can do automagic
 
264
           seeding */
 
265
        if(FIPS_mode())
 
266
            {
 
267
            FIPSerr(FIPS_F_FIPS_MODE_SET,FIPS_R_FIPS_MODE_ALREADY_SET);
 
268
            fips_selftest_fail = 1;
 
269
            ret = 0;
 
270
            goto end;
 
271
            }
 
272
 
 
273
#ifdef OPENSSL_IA32_SSE2
 
274
        if ((OPENSSL_ia32cap & (1<<25|1<<26)) != (1<<25|1<<26))
 
275
            {
 
276
            FIPSerr(FIPS_F_FIPS_MODE_SET,FIPS_R_UNSUPPORTED_PLATFORM);
 
277
            fips_selftest_fail = 1;
 
278
            ret = 0;
 
279
            goto end;
 
280
            }
 
281
#endif
 
282
 
 
283
        if(fips_signature_witness() != FIPS_signature)
 
284
            {
 
285
            FIPSerr(FIPS_F_FIPS_MODE_SET,FIPS_R_CONTRADICTING_EVIDENCE);
 
286
            fips_selftest_fail = 1;
 
287
            ret = 0;
 
288
            goto end;
 
289
            }
 
290
 
 
291
        if(!FIPS_check_incore_fingerprint())
 
292
            {
 
293
            fips_selftest_fail = 1;
 
294
            ret = 0;
 
295
            goto end;
 
296
            }
 
297
 
 
298
        /* Perform RNG KAT before seeding */
 
299
        if (!FIPS_selftest_rng())
 
300
            {
 
301
            fips_selftest_fail = 1;
 
302
            ret = 0;
 
303
            goto end;
 
304
            }
 
305
 
 
306
        /* automagically seed PRNG if not already seeded */
 
307
        if(!FIPS_rand_status())
 
308
            {
 
309
            if(RAND_bytes(buf,sizeof buf) <= 0)
 
310
                {
 
311
                fips_selftest_fail = 1;
 
312
                ret = 0;
 
313
                goto end;
 
314
                }
 
315
            FIPS_rand_set_key(buf,32);
 
316
            FIPS_rand_seed(buf+32,16);
 
317
            }
 
318
 
 
319
        /* now switch into FIPS mode */
 
320
        fips_set_rand_check(FIPS_rand_method());
 
321
        RAND_set_rand_method(FIPS_rand_method());
 
322
        if(FIPS_selftest())
 
323
            fips_set_mode(1);
 
324
        else
 
325
            {
 
326
            fips_selftest_fail = 1;
 
327
            ret = 0;
 
328
            goto end;
 
329
            }
 
330
        ret = 1;
 
331
        goto end;
 
332
        }
 
333
    fips_set_mode(0);
 
334
    fips_selftest_fail = 0;
 
335
    ret = 1;
 
336
end:
 
337
    fips_clear_owning_thread();
 
338
    fips_w_unlock();
 
339
    return ret;
 
340
    }
 
341
 
 
342
void fips_w_lock(void)          { CRYPTO_w_lock(CRYPTO_LOCK_FIPS); }
 
343
void fips_w_unlock(void)        { CRYPTO_w_unlock(CRYPTO_LOCK_FIPS); }
 
344
void fips_r_lock(void)          { CRYPTO_r_lock(CRYPTO_LOCK_FIPS); }
 
345
void fips_r_unlock(void)        { CRYPTO_r_unlock(CRYPTO_LOCK_FIPS); }
 
346
 
 
347
static int fips_started = 0;
 
348
static unsigned long fips_thread = 0;
 
349
 
 
350
void fips_set_started(void)
 
351
        {
 
352
        fips_started = 1;
 
353
        }
 
354
 
 
355
int fips_is_started(void)
 
356
        {
 
357
        return fips_started;
 
358
        }
 
359
 
 
360
int fips_is_owning_thread(void)
 
361
        {
 
362
        int ret = 0;
 
363
 
 
364
        if (fips_is_started())
 
365
                {
 
366
                CRYPTO_r_lock(CRYPTO_LOCK_FIPS2);
 
367
                if (fips_thread != 0 && fips_thread == CRYPTO_thread_id())
 
368
                        ret = 1;
 
369
                CRYPTO_r_unlock(CRYPTO_LOCK_FIPS2);
 
370
                }
 
371
        return ret;
 
372
        }
 
373
 
 
374
int fips_set_owning_thread(void)
 
375
        {
 
376
        int ret = 0;
 
377
 
 
378
        if (fips_is_started())
 
379
                {
 
380
                CRYPTO_w_lock(CRYPTO_LOCK_FIPS2);
 
381
                if (fips_thread == 0)
 
382
                        {
 
383
                        fips_thread = CRYPTO_thread_id();
 
384
                        ret = 1;
 
385
                        }
 
386
                CRYPTO_w_unlock(CRYPTO_LOCK_FIPS2);
 
387
                }
 
388
        return ret;
 
389
        }
 
390
 
 
391
int fips_clear_owning_thread(void)
 
392
        {
 
393
        int ret = 0;
 
394
 
 
395
        if (fips_is_started())
 
396
                {
 
397
                CRYPTO_w_lock(CRYPTO_LOCK_FIPS2);
 
398
                if (fips_thread == CRYPTO_thread_id())
 
399
                        {
 
400
                        fips_thread = 0;
 
401
                        ret = 1;
 
402
                        }
 
403
                CRYPTO_w_unlock(CRYPTO_LOCK_FIPS2);
 
404
                }
 
405
        return ret;
 
406
        }
 
407
 
 
408
unsigned char *fips_signature_witness(void)
 
409
        {
 
410
        extern unsigned char FIPS_signature[];
 
411
        return FIPS_signature;
 
412
        }
 
413
 
 
414
/* Generalized public key test routine. Signs and verifies the data
 
415
 * supplied in tbs using mesage digest md and setting option digest
 
416
 * flags md_flags. If the 'kat' parameter is not NULL it will
 
417
 * additionally check the signature matches it: a known answer test
 
418
 * The string "fail_str" is used for identification purposes in case
 
419
 * of failure.
 
420
 */
 
421
 
 
422
int fips_pkey_signature_test(EVP_PKEY *pkey,
 
423
                        const unsigned char *tbs, int tbslen,
 
424
                        const unsigned char *kat, unsigned int katlen,
 
425
                        const EVP_MD *digest, unsigned int md_flags,
 
426
                        const char *fail_str)
 
427
        {       
 
428
        int ret = 0;
 
429
        unsigned char sigtmp[256], *sig = sigtmp;
 
430
        unsigned int siglen;
 
431
        EVP_MD_CTX mctx;
 
432
        EVP_MD_CTX_init(&mctx);
 
433
 
 
434
        if ((pkey->type == EVP_PKEY_RSA)
 
435
                && (RSA_size(pkey->pkey.rsa) > sizeof(sigtmp)))
 
436
                {
 
437
                sig = OPENSSL_malloc(RSA_size(pkey->pkey.rsa));
 
438
                if (!sig)
 
439
                        {
 
440
                        FIPSerr(FIPS_F_FIPS_PKEY_SIGNATURE_TEST,ERR_R_MALLOC_FAILURE);
 
441
                        return 0;
 
442
                        }
 
443
                }
 
444
 
 
445
        if (tbslen == -1)
 
446
                tbslen = strlen((char *)tbs);
 
447
 
 
448
        if (md_flags)
 
449
                M_EVP_MD_CTX_set_flags(&mctx, md_flags);
 
450
 
 
451
        if (!EVP_SignInit_ex(&mctx, digest, NULL))
 
452
                goto error;
 
453
        if (!EVP_SignUpdate(&mctx, tbs, tbslen))
 
454
                goto error;
 
455
        if (!EVP_SignFinal(&mctx, sig, &siglen, pkey))
 
456
                goto error;
 
457
 
 
458
        if (kat && ((siglen != katlen) || memcmp(kat, sig, katlen)))
 
459
                goto error;
 
460
 
 
461
        if (!EVP_VerifyInit_ex(&mctx, digest, NULL))
 
462
                goto error;
 
463
        if (!EVP_VerifyUpdate(&mctx, tbs, tbslen))
 
464
                goto error;
 
465
        ret = EVP_VerifyFinal(&mctx, sig, siglen, pkey);
 
466
 
 
467
        error:
 
468
        if (sig != sigtmp)
 
469
                OPENSSL_free(sig);
 
470
        EVP_MD_CTX_cleanup(&mctx);
 
471
        if (ret != 1)
 
472
                {
 
473
                FIPSerr(FIPS_F_FIPS_PKEY_SIGNATURE_TEST,FIPS_R_TEST_FAILURE);
 
474
                if (fail_str)
 
475
                        ERR_add_error_data(2, "Type=", fail_str);
 
476
                return 0;
 
477
                }
 
478
        return 1;
 
479
        }
 
480
 
 
481
/* Generalized symmetric cipher test routine. Encrypt data, verify result
 
482
 * against known answer, decrypt and compare with original plaintext.
 
483
 */
 
484
 
 
485
int fips_cipher_test(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
 
486
                        const unsigned char *key,
 
487
                        const unsigned char *iv,
 
488
                        const unsigned char *plaintext,
 
489
                        const unsigned char *ciphertext,
 
490
                        int len)
 
491
        {
 
492
        unsigned char pltmp[FIPS_MAX_CIPHER_TEST_SIZE];
 
493
        unsigned char citmp[FIPS_MAX_CIPHER_TEST_SIZE];
 
494
        OPENSSL_assert(len <= FIPS_MAX_CIPHER_TEST_SIZE);
 
495
        if (EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, 1) <= 0)
 
496
                return 0;
 
497
        EVP_Cipher(ctx, citmp, plaintext, len);
 
498
        if (memcmp(citmp, ciphertext, len))
 
499
                return 0;
 
500
        if (EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, 0) <= 0)
 
501
                return 0;
 
502
        EVP_Cipher(ctx, pltmp, citmp, len);
 
503
        if (memcmp(pltmp, plaintext, len))
 
504
                return 0;
 
505
        return 1;
 
506
        }
 
507
 
 
508
#if 0
 
509
/* The purpose of this is to ensure the error code exists and the function
 
510
 * name is to keep the error checking script quiet
 
511
 */
 
512
void hash_final(void)
 
513
        {
 
514
        FIPSerr(FIPS_F_HASH_FINAL,FIPS_R_NON_FIPS_METHOD);
 
515
        }
 
516
#endif
 
517
 
 
518
 
 
519
#endif