Install fipscanister.o and friends. Disable warning halt in VC++ build.
[oweals/openssl.git] / fips-1.0 / fips.c
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 #include <openssl/fips.h>
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 #ifndef PATH_MAX
64 #define PATH_MAX 1024
65 #endif
66
67 static int fips_selftest_fail;
68 static int fips_mode;
69 static const void *fips_rand_check;
70
71 static void fips_set_mode(int onoff)
72         {
73         int owning_thread = fips_is_owning_thread();
74
75         if (fips_is_started())
76                 {
77                 if (!owning_thread) fips_w_lock();
78                 fips_mode = onoff;
79                 if (!owning_thread) fips_w_unlock();
80                 }
81         }
82
83 static void fips_set_rand_check(const void *rand_check)
84         {
85         int owning_thread = fips_is_owning_thread();
86
87         if (fips_is_started())
88                 {
89                 if (!owning_thread) fips_w_lock();
90                 fips_rand_check = rand_check;
91                 if (!owning_thread) fips_w_unlock();
92                 }
93         }
94
95 int FIPS_mode(void)
96         {
97         int ret = 0;
98         int owning_thread = fips_is_owning_thread();
99
100         if (fips_is_started())
101                 {
102                 if (!owning_thread) fips_r_lock();
103                 ret = fips_mode;
104                 if (!owning_thread) fips_r_unlock();
105                 }
106         return ret;
107         }
108
109 const void *FIPS_rand_check(void)
110         {
111         const void *ret = 0;
112         int owning_thread = fips_is_owning_thread();
113
114         if (fips_is_started())
115                 {
116                 if (!owning_thread) fips_r_lock();
117                 ret = fips_rand_check;
118                 if (!owning_thread) fips_r_unlock();
119                 }
120         return ret;
121         }
122
123 int FIPS_selftest_failed(void)
124     {
125     int ret = 0;
126     if (fips_is_started())
127         {
128         int owning_thread = fips_is_owning_thread();
129
130         if (!owning_thread) fips_r_lock();
131         ret = fips_selftest_fail;
132         if (!owning_thread) fips_r_unlock();
133         }
134     return ret;
135     }
136
137 /* Selftest failure fatal exit routine. This will be called
138  * during *any* cryptographic operation. It has the minimum
139  * overhead possible to avoid too big a performance hit.
140  */
141
142 void FIPS_selftest_check(void)
143     {
144     if (fips_selftest_fail)
145         {
146         OpenSSLDie(__FILE__,__LINE__, "FATAL FIPS SELFTEST FAILURE");
147         }
148     }
149
150 int FIPS_selftest()
151     {
152
153     return FIPS_selftest_sha1()
154         && FIPS_selftest_hmac()
155         && FIPS_selftest_aes()
156         && FIPS_selftest_des()
157         && FIPS_selftest_rsa()
158         && FIPS_selftest_dsa();
159     }
160
161 extern const void         *FIPS_text_start(),  *FIPS_text_end();
162 extern const unsigned char FIPS_rodata_start[], FIPS_rodata_end[];
163 unsigned char              FIPS_signature [20] = { 0 };
164 static const char          FIPS_hmac_key[]="etaonrishdlcupfm";
165
166 unsigned int FIPS_incore_fingerprint(unsigned char *sig,unsigned int len)
167     {
168     const unsigned char *p1 = FIPS_text_start();
169     const unsigned char *p2 = FIPS_text_end();
170     const unsigned char *p3 = FIPS_rodata_start;
171     const unsigned char *p4 = FIPS_rodata_end;
172     HMAC_CTX c;
173
174     HMAC_CTX_init(&c);
175     HMAC_Init(&c,FIPS_hmac_key,strlen(FIPS_hmac_key),EVP_sha1());
176
177     /* detect overlapping regions */
178     if (p1<=p3 && p2>=p3)
179         p3=p1, p4=p2>p4?p2:p4, p1=NULL, p2=NULL;
180     else if (p3<=p1 && p4>=p1)
181         p3=p3, p4=p2>p4?p2:p4, p1=NULL, p2=NULL;
182
183     if (p1)
184         HMAC_Update(&c,p1,(size_t)p2-(size_t)p1);
185
186     if (FIPS_signature>=p3 && FIPS_signature<p4)
187         {
188         /* "punch" hole */
189         HMAC_Update(&c,p3,(size_t)FIPS_signature-(size_t)p3);
190         p3 = FIPS_signature+sizeof(FIPS_signature);
191         if (p3<p4)
192             HMAC_Update(&c,p3,(size_t)p4-(size_t)p3);
193         }
194     else
195         HMAC_Update(&c,p3,(size_t)p4-(size_t)p3);
196
197     HMAC_Final(&c,sig,&len);
198     HMAC_CTX_cleanup(&c);
199
200     return len;
201     }
202
203 int FIPS_check_incore_fingerprint(void)
204     {
205     unsigned char sig[EVP_MAX_MD_SIZE];
206     unsigned int len;
207     extern int OPENSSL_NONPIC_relocated;
208
209     if (FIPS_text_start()==NULL)
210         {
211         FIPSerr(FIPS_F_FIPS_CHECK_FINGERPRINT,FIPS_R_UNSUPPORTED_PLATFORM);
212         return 0;
213         }
214
215     len=FIPS_incore_fingerprint (sig,sizeof(sig));
216
217     if (len!=sizeof(FIPS_signature) ||
218         memcmp(FIPS_signature,sig,sizeof(FIPS_signature)))
219         {
220         if (FIPS_signature>=FIPS_rodata_start && FIPS_signature<FIPS_rodata_end)
221             FIPSerr(FIPS_F_FIPS_CHECK_FINGERPRINT,FIPS_R_FINGERPRINT_DOES_NOT_MATCH_SEGMENT_ALIASING);
222         else if (OPENSSL_NONPIC_relocated)
223             FIPSerr(FIPS_F_FIPS_CHECK_FINGERPRINT,FIPS_R_FINGERPRINT_DOES_NOT_MATCH_NONPIC_RELOCATED);
224         else
225             FIPSerr(FIPS_F_FIPS_CHECK_FINGERPRINT,FIPS_R_FINGERPRINT_DOES_NOT_MATCH);
226         return 0;
227         }
228
229     return 1;
230     }
231
232 int FIPS_mode_set(int onoff)
233     {
234     int fips_set_owning_thread();
235     int fips_clear_owning_thread();
236     int ret = 0;
237
238     fips_w_lock();
239     fips_set_started();
240     fips_set_owning_thread();
241
242     if(onoff)
243         {
244         unsigned char buf[48];
245
246         fips_selftest_fail = 0;
247
248         /* Don't go into FIPS mode twice, just so we can do automagic
249            seeding */
250         if(FIPS_mode())
251             {
252             FIPSerr(FIPS_F_FIPS_MODE_SET,FIPS_R_FIPS_MODE_ALREADY_SET);
253             fips_selftest_fail = 1;
254             ret = 0;
255             goto end;
256             }
257
258         if(fips_signature_witness() != FIPS_signature)
259             {
260             FIPSerr(FIPS_F_FIPS_MODE_SET,FIPS_R_CONTRADICTING_EVIDENCE);
261             fips_selftest_fail = 1;
262             ret = 0;
263             goto end;
264             }
265
266         if(!FIPS_check_incore_fingerprint())
267             {
268             fips_selftest_fail = 1;
269             ret = 0;
270             goto end;
271             }
272
273         /* Perform RNG KAT before seeding */
274         if (!FIPS_selftest_rng())
275             {
276             fips_selftest_fail = 1;
277             ret = 0;
278             goto end;
279             }
280
281         /* automagically seed PRNG if not already seeded */
282         if(!FIPS_rand_status())
283             {
284             if(RAND_bytes(buf,sizeof buf) <= 0)
285                 {
286                 fips_selftest_fail = 1;
287                 ret = 0;
288                 goto end;
289                 }
290             FIPS_rand_set_key(buf,32);
291             FIPS_rand_seed(buf+32,16);
292             }
293
294         /* now switch into FIPS mode */
295         fips_set_rand_check(FIPS_rand_method());
296         RAND_set_rand_method(FIPS_rand_method());
297         if(FIPS_selftest())
298             fips_set_mode(1);
299         else
300             {
301             fips_selftest_fail = 1;
302             ret = 0;
303             goto end;
304             }
305         ret = 1;
306         goto end;
307         }
308     fips_set_mode(0);
309     fips_selftest_fail = 0;
310     ret = 1;
311 end:
312     fips_clear_owning_thread();
313     fips_w_unlock();
314     return ret;
315     }
316
317 #if 0
318 /* here just to cause error codes to exist */
319 static void dummy()
320     {
321     FIPSerr(FIPS_F_HASH_FINAL,FIPS_F_NON_FIPS_METHOD);
322     FIPSerr(FIPS_F_HASH_FINAL,FIPS_R_FIPS_SELFTEST_FAILED);
323     }
324 #endif
325
326 void fips_w_lock(void)          { CRYPTO_w_lock(CRYPTO_LOCK_FIPS); }
327 void fips_w_unlock(void)        { CRYPTO_w_unlock(CRYPTO_LOCK_FIPS); }
328 void fips_r_lock(void)          { CRYPTO_r_lock(CRYPTO_LOCK_FIPS); }
329 void fips_r_unlock(void)        { CRYPTO_r_unlock(CRYPTO_LOCK_FIPS); }
330
331 static int fips_started = 0;
332 static unsigned long fips_thread = 0;
333
334 void fips_set_started(void)
335         {
336         fips_started = 1;
337         }
338
339 int fips_is_started(void)
340         {
341         return fips_started;
342         }
343
344 int fips_is_owning_thread(void)
345         {
346         int ret = 0;
347
348         if (fips_is_started())
349                 {
350                 CRYPTO_r_lock(CRYPTO_LOCK_FIPS2);
351                 if (fips_thread != 0 && fips_thread == CRYPTO_thread_id())
352                         ret = 1;
353                 CRYPTO_r_unlock(CRYPTO_LOCK_FIPS2);
354                 }
355         return ret;
356         }
357
358 int fips_set_owning_thread(void)
359         {
360         int ret = 0;
361
362         if (fips_is_started())
363                 {
364                 CRYPTO_w_lock(CRYPTO_LOCK_FIPS2);
365                 if (fips_thread == 0)
366                         {
367                         fips_thread = CRYPTO_thread_id();
368                         ret = 1;
369                         }
370                 CRYPTO_w_unlock(CRYPTO_LOCK_FIPS2);
371                 }
372         return ret;
373         }
374
375 int fips_clear_owning_thread(void)
376         {
377         int ret = 0;
378
379         if (fips_is_started())
380                 {
381                 CRYPTO_w_lock(CRYPTO_LOCK_FIPS2);
382                 if (fips_thread == CRYPTO_thread_id())
383                         {
384                         fips_thread = 0;
385                         ret = 1;
386                         }
387                 CRYPTO_w_unlock(CRYPTO_LOCK_FIPS2);
388                 }
389         return ret;
390         }
391
392 unsigned char *fips_signature_witness(void)
393         {
394         extern unsigned char FIPS_signature[];
395         return FIPS_signature;
396         }
397
398 /* Generalized public key test routine. Signs and verifies the data
399  * supplied in tbs using mesage digest md and setting option digest
400  * flags md_flags. If the 'kat' parameter is not NULL it will
401  * additionally check the signature matches it: a known answer test
402  * The string "fail_str" is used for identification purposes in case
403  * of failure.
404  */
405
406 int fips_pkey_signature_test(EVP_PKEY *pkey,
407                         const unsigned char *tbs, int tbslen,
408                         const unsigned char *kat, unsigned int katlen,
409                         const EVP_MD *digest, unsigned int md_flags,
410                         const char *fail_str)
411         {       
412         int ret = 0;
413         unsigned char sigtmp[256], *sig = sigtmp;
414         unsigned int siglen;
415         EVP_MD_CTX mctx;
416         EVP_MD_CTX_init(&mctx);
417
418         if ((pkey->type == EVP_PKEY_RSA)
419                 && (RSA_size(pkey->pkey.rsa) > sizeof(sigtmp)))
420                 {
421                 sig = OPENSSL_malloc(RSA_size(pkey->pkey.rsa));
422                 if (!sig)
423                         {
424                         FIPSerr(FIPS_F_FIPS_CHECK_PK_SIG,ERR_R_MALLOC_FAILURE);
425                         return 0;
426                         }
427                 }
428
429         if (tbslen == -1)
430                 tbslen = strlen((char *)tbs);
431
432         if (md_flags)
433                 M_EVP_MD_CTX_set_flags(&mctx, md_flags);
434
435         if (!EVP_SignInit_ex(&mctx, digest, NULL))
436                 goto error;
437         if (!EVP_SignUpdate(&mctx, tbs, tbslen))
438                 goto error;
439         if (!EVP_SignFinal(&mctx, sig, &siglen, pkey))
440                 goto error;
441
442         if (kat && ((siglen != katlen) || memcmp(kat, sig, katlen)))
443                 goto error;
444
445         if (!EVP_VerifyInit_ex(&mctx, digest, NULL))
446                 goto error;
447         if (!EVP_VerifyUpdate(&mctx, tbs, tbslen))
448                 goto error;
449         ret = EVP_VerifyFinal(&mctx, sig, siglen, pkey);
450
451         error:
452         if (sig != sigtmp)
453                 OPENSSL_free(sig);
454         EVP_MD_CTX_cleanup(&mctx);
455         if (ret != 1)
456                 {
457                 FIPSerr(FIPS_F_FIPS_PKEY_SIGNATURE_TEST,FIPS_R_TEST_FAILURE);
458                 if (fail_str)
459                         ERR_add_error_data(2, "Type=", fail_str);
460                 return 0;
461                 }
462         return 1;
463         }
464
465 /* Generalized symmetric cipher test routine. Encrypt data, verify result
466  * against known answer, decrypt and compare with original plaintext.
467  */
468
469 int fips_cipher_test(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
470                         const unsigned char *key,
471                         const unsigned char *iv,
472                         const unsigned char *plaintext,
473                         const unsigned char *ciphertext,
474                         int len)
475         {
476         unsigned char pltmp[FIPS_MAX_CIPHER_TEST_SIZE];
477         unsigned char citmp[FIPS_MAX_CIPHER_TEST_SIZE];
478         OPENSSL_assert(len <= FIPS_MAX_CIPHER_TEST_SIZE);
479         if (EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, 1) <= 0)
480                 return 0;
481         EVP_Cipher(ctx, citmp, plaintext, len);
482         if (memcmp(citmp, ciphertext, len))
483                 return 0;
484         if (EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, 0) <= 0)
485                 return 0;
486         EVP_Cipher(ctx, pltmp, citmp, len);
487         if (memcmp(pltmp, plaintext, len))
488                 return 0;
489         return 1;
490         }
491
492
493 #endif