Update pairwise consistency checks to use SHA-256.
[openssl.git] / fips / 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 #define OPENSSL_FIPSAPI
51
52 #include <openssl/rand.h>
53 #include <openssl/fips_rand.h>
54 #include <openssl/err.h>
55 #include <openssl/bio.h>
56 #include <openssl/hmac.h>
57 #include <openssl/rsa.h>
58 #include <openssl/dsa.h>
59 #include <string.h>
60 #include <limits.h>
61 #include "fips_locl.h"
62
63 #ifdef OPENSSL_FIPS
64
65 #include <openssl/fips.h>
66
67 #ifndef PATH_MAX
68 #define PATH_MAX 1024
69 #endif
70
71 static int fips_selftest_fail;
72 static int fips_mode;
73 static int fips_started = 0;
74 static const void *fips_rand_check;
75
76 static int fips_is_owning_thread(void);
77 static int fips_set_owning_thread(void);
78 static int fips_clear_owning_thread(void);
79 static unsigned char *fips_signature_witness(void);
80
81 static void fips_w_lock(void)   { CRYPTO_w_lock(CRYPTO_LOCK_FIPS); }
82 static void fips_w_unlock(void) { CRYPTO_w_unlock(CRYPTO_LOCK_FIPS); }
83 static void fips_r_lock(void)   { CRYPTO_r_lock(CRYPTO_LOCK_FIPS); }
84 static void fips_r_unlock(void) { CRYPTO_r_unlock(CRYPTO_LOCK_FIPS); }
85
86 static void fips_set_mode(int onoff)
87         {
88         int owning_thread = fips_is_owning_thread();
89
90         if (fips_started)
91                 {
92                 if (!owning_thread) fips_w_lock();
93                 fips_mode = onoff;
94                 if (!owning_thread) fips_w_unlock();
95                 }
96         }
97
98 static void fips_set_rand_check(const void *rand_check)
99         {
100         int owning_thread = fips_is_owning_thread();
101
102         if (fips_started)
103                 {
104                 if (!owning_thread) fips_w_lock();
105                 fips_rand_check = rand_check;
106                 if (!owning_thread) fips_w_unlock();
107                 }
108         }
109
110 int FIPS_mode(void)
111         {
112         int ret = 0;
113         int owning_thread = fips_is_owning_thread();
114
115         if (fips_started)
116                 {
117                 if (!owning_thread) fips_r_lock();
118                 ret = fips_mode;
119                 if (!owning_thread) fips_r_unlock();
120                 }
121         return ret;
122         }
123
124 const void *FIPS_rand_check(void)
125         {
126         const void *ret = 0;
127         int owning_thread = fips_is_owning_thread();
128
129         if (fips_started)
130                 {
131                 if (!owning_thread) fips_r_lock();
132                 ret = fips_rand_check;
133                 if (!owning_thread) fips_r_unlock();
134                 }
135         return ret;
136         }
137
138 int FIPS_selftest_failed(void)
139     {
140     int ret = 0;
141     if (fips_started)
142         {
143         int owning_thread = fips_is_owning_thread();
144
145         if (!owning_thread) fips_r_lock();
146         ret = fips_selftest_fail;
147         if (!owning_thread) fips_r_unlock();
148         }
149     return ret;
150     }
151
152 /* Selftest failure fatal exit routine. This will be called
153  * during *any* cryptographic operation. It has the minimum
154  * overhead possible to avoid too big a performance hit.
155  */
156
157 void FIPS_selftest_check(void)
158     {
159     if (fips_selftest_fail)
160         {
161         OpenSSLDie(__FILE__,__LINE__, "FATAL FIPS SELFTEST FAILURE");
162         }
163     }
164
165 void fips_set_selftest_fail(void)
166     {
167     fips_selftest_fail = 1;
168     }
169
170 int FIPS_selftest(void)
171     {
172
173     return FIPS_selftest_sha1()
174         && FIPS_selftest_hmac()
175         && FIPS_selftest_aes()
176         && FIPS_selftest_des()
177         && FIPS_selftest_rsa()
178         && FIPS_selftest_dsa();
179     }
180
181 extern const void         *FIPS_text_start(),  *FIPS_text_end();
182 extern const unsigned char FIPS_rodata_start[], FIPS_rodata_end[];
183 unsigned char              FIPS_signature [20] = { 0 };
184 static const char          FIPS_hmac_key[]="etaonrishdlcupfm";
185
186 unsigned int FIPS_incore_fingerprint(unsigned char *sig,unsigned int len)
187     {
188     const unsigned char *p1 = FIPS_text_start();
189     const unsigned char *p2 = FIPS_text_end();
190     const unsigned char *p3 = FIPS_rodata_start;
191     const unsigned char *p4 = FIPS_rodata_end;
192     HMAC_CTX c;
193
194     HMAC_CTX_init(&c);
195     HMAC_Init(&c,FIPS_hmac_key,strlen(FIPS_hmac_key),EVP_sha1());
196
197     /* detect overlapping regions */
198     if (p1<=p3 && p2>=p3)
199         p3=p1, p4=p2>p4?p2:p4, p1=NULL, p2=NULL;
200     else if (p3<=p1 && p4>=p1)
201         p3=p3, p4=p2>p4?p2:p4, p1=NULL, p2=NULL;
202
203     if (p1)
204         HMAC_Update(&c,p1,(size_t)p2-(size_t)p1);
205
206     if (FIPS_signature>=p3 && FIPS_signature<p4)
207         {
208         /* "punch" hole */
209         HMAC_Update(&c,p3,(size_t)FIPS_signature-(size_t)p3);
210         p3 = FIPS_signature+sizeof(FIPS_signature);
211         if (p3<p4)
212             HMAC_Update(&c,p3,(size_t)p4-(size_t)p3);
213         }
214     else
215         HMAC_Update(&c,p3,(size_t)p4-(size_t)p3);
216
217     HMAC_Final(&c,sig,&len);
218     HMAC_CTX_cleanup(&c);
219
220     return len;
221     }
222
223 int FIPS_check_incore_fingerprint(void)
224     {
225     unsigned char sig[EVP_MAX_MD_SIZE];
226     unsigned int len;
227 #if defined(__sgi) && (defined(__mips) || defined(mips))
228     extern int __dso_displacement[];
229 #else
230     extern int OPENSSL_NONPIC_relocated;
231 #endif
232
233     if (FIPS_text_start()==NULL)
234         {
235         FIPSerr(FIPS_F_FIPS_CHECK_INCORE_FINGERPRINT,FIPS_R_UNSUPPORTED_PLATFORM);
236         return 0;
237         }
238
239     len=FIPS_incore_fingerprint (sig,sizeof(sig));
240
241     if (len!=sizeof(FIPS_signature) ||
242         memcmp(FIPS_signature,sig,sizeof(FIPS_signature)))
243         {
244         if (FIPS_signature>=FIPS_rodata_start && FIPS_signature<FIPS_rodata_end)
245             FIPSerr(FIPS_F_FIPS_CHECK_INCORE_FINGERPRINT,FIPS_R_FINGERPRINT_DOES_NOT_MATCH_SEGMENT_ALIASING);
246 #if defined(__sgi) && (defined(__mips) || defined(mips))
247         else if (__dso_displacement!=NULL)
248 #else
249         else if (OPENSSL_NONPIC_relocated)
250 #endif
251             FIPSerr(FIPS_F_FIPS_CHECK_INCORE_FINGERPRINT,FIPS_R_FINGERPRINT_DOES_NOT_MATCH_NONPIC_RELOCATED);
252         else
253             FIPSerr(FIPS_F_FIPS_CHECK_INCORE_FINGERPRINT,FIPS_R_FINGERPRINT_DOES_NOT_MATCH);
254 #ifdef OPENSSL_FIPS_DEBUGGER
255         return 1;
256 #else
257         return 0;
258 #endif
259         }
260     return 1;
261     }
262
263 int FIPS_mode_set(int onoff)
264     {
265     int fips_set_owning_thread();
266     int fips_clear_owning_thread();
267     int ret = 0;
268
269     fips_w_lock();
270     fips_started = 1;
271     fips_set_owning_thread();
272
273     if(onoff)
274         {
275         unsigned char buf[48];
276
277         fips_selftest_fail = 0;
278
279         /* Don't go into FIPS mode twice, just so we can do automagic
280            seeding */
281         if(FIPS_mode())
282             {
283             FIPSerr(FIPS_F_FIPS_MODE_SET,FIPS_R_FIPS_MODE_ALREADY_SET);
284             fips_selftest_fail = 1;
285             ret = 0;
286             goto end;
287             }
288
289 #ifdef OPENSSL_IA32_SSE2
290         if ((OPENSSL_ia32cap & (1<<25|1<<26)) != (1<<25|1<<26))
291             {
292             FIPSerr(FIPS_F_FIPS_MODE_SET,FIPS_R_UNSUPPORTED_PLATFORM);
293             fips_selftest_fail = 1;
294             ret = 0;
295             goto end;
296             }
297 #endif
298
299         if(fips_signature_witness() != FIPS_signature)
300             {
301             FIPSerr(FIPS_F_FIPS_MODE_SET,FIPS_R_CONTRADICTING_EVIDENCE);
302             fips_selftest_fail = 1;
303             ret = 0;
304             goto end;
305             }
306
307         if(!FIPS_check_incore_fingerprint())
308             {
309             fips_selftest_fail = 1;
310             ret = 0;
311             goto end;
312             }
313
314         /* Perform RNG KAT before seeding */
315         if (!FIPS_selftest_rng())
316             {
317             fips_selftest_fail = 1;
318             ret = 0;
319             goto end;
320             }
321
322         /* automagically seed PRNG if not already seeded */
323         if(!FIPS_rand_status())
324             {
325             if(RAND_bytes(buf,sizeof buf) <= 0)
326                 {
327                 fips_selftest_fail = 1;
328                 ret = 0;
329                 goto end;
330                 }
331             FIPS_rand_set_key(buf,32);
332             FIPS_rand_seed(buf+32,16);
333             }
334
335         /* now switch into FIPS mode */
336         fips_set_rand_check(FIPS_rand_method());
337         RAND_set_rand_method(FIPS_rand_method());
338         if(FIPS_selftest())
339             fips_set_mode(1);
340         else
341             {
342             fips_selftest_fail = 1;
343             ret = 0;
344             goto end;
345             }
346         ret = 1;
347         goto end;
348         }
349     fips_set_mode(0);
350     fips_selftest_fail = 0;
351     ret = 1;
352 end:
353     fips_clear_owning_thread();
354     fips_w_unlock();
355     return ret;
356     }
357
358 static CRYPTO_THREADID fips_thread;
359 static int fips_thread_set = 0;
360
361 static int fips_is_owning_thread(void)
362         {
363         int ret = 0;
364
365         if (fips_started)
366                 {
367                 CRYPTO_r_lock(CRYPTO_LOCK_FIPS2);
368                 if (fips_thread_set)
369                         {
370                         CRYPTO_THREADID cur;
371                         CRYPTO_THREADID_current(&cur);
372                         if (!CRYPTO_THREADID_cmp(&cur, &fips_thread))
373                                 ret = 1;
374                         }
375                 CRYPTO_r_unlock(CRYPTO_LOCK_FIPS2);
376                 }
377         return ret;
378         }
379
380 int fips_set_owning_thread(void)
381         {
382         int ret = 0;
383
384         if (fips_started)
385                 {
386                 CRYPTO_w_lock(CRYPTO_LOCK_FIPS2);
387                 if (!fips_thread_set)
388                         {
389                         CRYPTO_THREADID_current(&fips_thread);
390                         ret = 1;
391                         }
392                 CRYPTO_w_unlock(CRYPTO_LOCK_FIPS2);
393                 }
394         return ret;
395         }
396
397 int fips_clear_owning_thread(void)
398         {
399         int ret = 0;
400
401         if (fips_started)
402                 {
403                 CRYPTO_w_lock(CRYPTO_LOCK_FIPS2);
404                 if (fips_thread_set)
405                         {
406                         CRYPTO_THREADID cur;
407                         CRYPTO_THREADID_current(&cur);
408                         if (!CRYPTO_THREADID_cmp(&cur, &fips_thread))
409                                 fips_thread_set = 0;
410                         }
411                 CRYPTO_w_unlock(CRYPTO_LOCK_FIPS2);
412                 }
413         return ret;
414         }
415
416 unsigned char *fips_signature_witness(void)
417         {
418         extern unsigned char FIPS_signature[];
419         return FIPS_signature;
420         }
421
422 /* Generalized public key test routine. Signs and verifies the data
423  * supplied in tbs using mesage digest md and setting RSA padding mode
424  * pad_mode. If the 'kat' parameter is not NULL it will
425  * additionally check the signature matches it: a known answer test
426  * The string "fail_str" is used for identification purposes in case
427  * of failure.
428  */
429
430 int fips_pkey_signature_test(EVP_PKEY *pkey,
431                         const unsigned char *tbs, int tbslen,
432                         const unsigned char *kat, unsigned int katlen,
433                         const EVP_MD *digest, int pad_mode,
434                         const char *fail_str)
435         {       
436         int ret = 0;
437         unsigned char sigtmp[256], *sig = sigtmp;
438         unsigned int siglen;
439         DSA_SIG *dsig = NULL;
440         EVP_MD_CTX mctx;
441         FIPS_md_ctx_init(&mctx);
442
443         if ((pkey->type == EVP_PKEY_RSA)
444                 && ((size_t)RSA_size(pkey->pkey.rsa) > sizeof(sigtmp)))
445                 {
446                 sig = OPENSSL_malloc(RSA_size(pkey->pkey.rsa));
447                 if (!sig)
448                         {
449                         FIPSerr(FIPS_F_FIPS_PKEY_SIGNATURE_TEST,ERR_R_MALLOC_FAILURE);
450                         return 0;
451                         }
452                 }
453
454         if (tbslen == -1)
455                 tbslen = strlen((char *)tbs);
456
457         if (digest == NULL)
458                 digest = EVP_sha256();
459
460         if (!FIPS_digestinit(&mctx, digest))
461                 goto error;
462         if (!FIPS_digestupdate(&mctx, tbs, tbslen))
463                 goto error;
464         if (pkey->type == EVP_PKEY_RSA)
465                 {
466                 if (!FIPS_rsa_sign_ctx(pkey->pkey.rsa, &mctx,
467                                         pad_mode, 0, NULL, sig, &siglen))
468                         goto error;
469                 }
470         else if (pkey->type == EVP_PKEY_DSA)
471                 {
472                 dsig = FIPS_dsa_sign_ctx(pkey->pkey.dsa, &mctx);
473                 if (!dsig)
474                         goto error;
475                 }
476 #if 0
477         else if (!EVP_SignFinal(&mctx, sig, &siglen, pkey))
478                 goto error;
479 #endif
480
481         if (kat && ((siglen != katlen) || memcmp(kat, sig, katlen)))
482                 goto error;
483
484         if (!FIPS_digestinit(&mctx, digest))
485                 goto error;
486         if (!FIPS_digestupdate(&mctx, tbs, tbslen))
487                 goto error;
488         if (pkey->type == EVP_PKEY_RSA)
489                 {
490                 ret = FIPS_rsa_verify_ctx(pkey->pkey.rsa, &mctx,
491                                                 pad_mode, 0, NULL, sig, siglen);
492                 }
493         else if (pkey->type == EVP_PKEY_DSA)
494                 {
495                 ret = FIPS_dsa_verify_ctx(pkey->pkey.dsa, &mctx, dsig);
496                 }
497 #if 0
498         else
499                 ret = EVP_VerifyFinal(&mctx, sig, siglen, pkey);
500 #endif
501
502         error:
503         if (dsig != NULL)
504                 FIPS_dsa_sig_free(dsig);
505         if (sig != sigtmp)
506                 OPENSSL_free(sig);
507         FIPS_md_ctx_cleanup(&mctx);
508         if (ret != 1)
509                 {
510                 FIPSerr(FIPS_F_FIPS_PKEY_SIGNATURE_TEST,FIPS_R_TEST_FAILURE);
511                 if (fail_str)
512                         FIPS_add_error_data(2, "Type=", fail_str);
513                 return 0;
514                 }
515         return 1;
516         }
517
518 /* Generalized symmetric cipher test routine. Encrypt data, verify result
519  * against known answer, decrypt and compare with original plaintext.
520  */
521
522 int fips_cipher_test(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
523                         const unsigned char *key,
524                         const unsigned char *iv,
525                         const unsigned char *plaintext,
526                         const unsigned char *ciphertext,
527                         int len)
528         {
529         unsigned char pltmp[FIPS_MAX_CIPHER_TEST_SIZE];
530         unsigned char citmp[FIPS_MAX_CIPHER_TEST_SIZE];
531         OPENSSL_assert(len <= FIPS_MAX_CIPHER_TEST_SIZE);
532         if (FIPS_cipherinit(ctx, cipher, key, iv, 1) <= 0)
533                 return 0;
534         FIPS_cipher(ctx, citmp, plaintext, len);
535         if (memcmp(citmp, ciphertext, len))
536                 return 0;
537         if (FIPS_cipherinit(ctx, cipher, key, iv, 0) <= 0)
538                 return 0;
539         FIPS_cipher(ctx, pltmp, citmp, len);
540         if (memcmp(pltmp, plaintext, len))
541                 return 0;
542         return 1;
543         }
544
545 #if 0
546 /* The purpose of this is to ensure the error code exists and the function
547  * name is to keep the error checking script quiet
548  */
549 void hash_final(void)
550         {
551         FIPSerr(FIPS_F_HASH_FINAL,FIPS_R_NON_FIPS_METHOD);
552         }
553 #endif
554
555
556 #endif