Enforce minimum key sizes in FIPS mode.
[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 #ifdef OPENSSL_IA32_SSE2
259         if ((OPENSSL_ia32cap & (1<<25|1<<26)) != (1<<25|1<<26))
260             {
261             FIPSerr(FIPS_F_FIPS_MODE_SET,FIPS_R_UNSUPPORTED_PLATFORM);
262             fips_selftest_fail = 1;
263             ret = 0;
264             goto end;
265             }
266 #endif
267
268         if(fips_signature_witness() != FIPS_signature)
269             {
270             FIPSerr(FIPS_F_FIPS_MODE_SET,FIPS_R_CONTRADICTING_EVIDENCE);
271             fips_selftest_fail = 1;
272             ret = 0;
273             goto end;
274             }
275
276         if(!FIPS_check_incore_fingerprint())
277             {
278             fips_selftest_fail = 1;
279             ret = 0;
280             goto end;
281             }
282
283         /* Perform RNG KAT before seeding */
284         if (!FIPS_selftest_rng())
285             {
286             fips_selftest_fail = 1;
287             ret = 0;
288             goto end;
289             }
290
291         /* automagically seed PRNG if not already seeded */
292         if(!FIPS_rand_status())
293             {
294             if(RAND_bytes(buf,sizeof buf) <= 0)
295                 {
296                 fips_selftest_fail = 1;
297                 ret = 0;
298                 goto end;
299                 }
300             FIPS_rand_set_key(buf,32);
301             FIPS_rand_seed(buf+32,16);
302             }
303
304         /* now switch into FIPS mode */
305         fips_set_rand_check(FIPS_rand_method());
306         RAND_set_rand_method(FIPS_rand_method());
307         if(FIPS_selftest())
308             fips_set_mode(1);
309         else
310             {
311             fips_selftest_fail = 1;
312             ret = 0;
313             goto end;
314             }
315         ret = 1;
316         goto end;
317         }
318     fips_set_mode(0);
319     fips_selftest_fail = 0;
320     ret = 1;
321 end:
322     fips_clear_owning_thread();
323     fips_w_unlock();
324     return ret;
325     }
326
327 #if 0
328 /* here just to cause error codes to exist */
329 static void dummy()
330     {
331     FIPSerr(FIPS_F_HASH_FINAL,FIPS_F_NON_FIPS_METHOD);
332     FIPSerr(FIPS_F_HASH_FINAL,FIPS_R_FIPS_SELFTEST_FAILED);
333     }
334 #endif
335
336 void fips_w_lock(void)          { CRYPTO_w_lock(CRYPTO_LOCK_FIPS); }
337 void fips_w_unlock(void)        { CRYPTO_w_unlock(CRYPTO_LOCK_FIPS); }
338 void fips_r_lock(void)          { CRYPTO_r_lock(CRYPTO_LOCK_FIPS); }
339 void fips_r_unlock(void)        { CRYPTO_r_unlock(CRYPTO_LOCK_FIPS); }
340
341 static int fips_started = 0;
342 static unsigned long fips_thread = 0;
343
344 void fips_set_started(void)
345         {
346         fips_started = 1;
347         }
348
349 int fips_is_started(void)
350         {
351         return fips_started;
352         }
353
354 int fips_is_owning_thread(void)
355         {
356         int ret = 0;
357
358         if (fips_is_started())
359                 {
360                 CRYPTO_r_lock(CRYPTO_LOCK_FIPS2);
361                 if (fips_thread != 0 && fips_thread == CRYPTO_thread_id())
362                         ret = 1;
363                 CRYPTO_r_unlock(CRYPTO_LOCK_FIPS2);
364                 }
365         return ret;
366         }
367
368 int fips_set_owning_thread(void)
369         {
370         int ret = 0;
371
372         if (fips_is_started())
373                 {
374                 CRYPTO_w_lock(CRYPTO_LOCK_FIPS2);
375                 if (fips_thread == 0)
376                         {
377                         fips_thread = CRYPTO_thread_id();
378                         ret = 1;
379                         }
380                 CRYPTO_w_unlock(CRYPTO_LOCK_FIPS2);
381                 }
382         return ret;
383         }
384
385 int fips_clear_owning_thread(void)
386         {
387         int ret = 0;
388
389         if (fips_is_started())
390                 {
391                 CRYPTO_w_lock(CRYPTO_LOCK_FIPS2);
392                 if (fips_thread == CRYPTO_thread_id())
393                         {
394                         fips_thread = 0;
395                         ret = 1;
396                         }
397                 CRYPTO_w_unlock(CRYPTO_LOCK_FIPS2);
398                 }
399         return ret;
400         }
401
402 unsigned char *fips_signature_witness(void)
403         {
404         extern unsigned char FIPS_signature[];
405         return FIPS_signature;
406         }
407
408 /* Generalized public key test routine. Signs and verifies the data
409  * supplied in tbs using mesage digest md and setting option digest
410  * flags md_flags. If the 'kat' parameter is not NULL it will
411  * additionally check the signature matches it: a known answer test
412  * The string "fail_str" is used for identification purposes in case
413  * of failure.
414  */
415
416 int fips_pkey_signature_test(EVP_PKEY *pkey,
417                         const unsigned char *tbs, int tbslen,
418                         const unsigned char *kat, unsigned int katlen,
419                         const EVP_MD *digest, unsigned int md_flags,
420                         const char *fail_str)
421         {       
422         int ret = 0;
423         unsigned char sigtmp[256], *sig = sigtmp;
424         unsigned int siglen;
425         EVP_MD_CTX mctx;
426         EVP_MD_CTX_init(&mctx);
427
428         if ((pkey->type == EVP_PKEY_RSA)
429                 && (RSA_size(pkey->pkey.rsa) > sizeof(sigtmp)))
430                 {
431                 sig = OPENSSL_malloc(RSA_size(pkey->pkey.rsa));
432                 if (!sig)
433                         {
434                         FIPSerr(FIPS_F_FIPS_CHECK_PK_SIG,ERR_R_MALLOC_FAILURE);
435                         return 0;
436                         }
437                 }
438
439         if (tbslen == -1)
440                 tbslen = strlen((char *)tbs);
441
442         if (md_flags)
443                 M_EVP_MD_CTX_set_flags(&mctx, md_flags);
444
445         if (!EVP_SignInit_ex(&mctx, digest, NULL))
446                 goto error;
447         if (!EVP_SignUpdate(&mctx, tbs, tbslen))
448                 goto error;
449         if (!EVP_SignFinal(&mctx, sig, &siglen, pkey))
450                 goto error;
451
452         if (kat && ((siglen != katlen) || memcmp(kat, sig, katlen)))
453                 goto error;
454
455         if (!EVP_VerifyInit_ex(&mctx, digest, NULL))
456                 goto error;
457         if (!EVP_VerifyUpdate(&mctx, tbs, tbslen))
458                 goto error;
459         ret = EVP_VerifyFinal(&mctx, sig, siglen, pkey);
460
461         error:
462         if (sig != sigtmp)
463                 OPENSSL_free(sig);
464         EVP_MD_CTX_cleanup(&mctx);
465         if (ret != 1)
466                 {
467                 FIPSerr(FIPS_F_FIPS_PKEY_SIGNATURE_TEST,FIPS_R_TEST_FAILURE);
468                 if (fail_str)
469                         ERR_add_error_data(2, "Type=", fail_str);
470                 return 0;
471                 }
472         return 1;
473         }
474
475 /* Generalized symmetric cipher test routine. Encrypt data, verify result
476  * against known answer, decrypt and compare with original plaintext.
477  */
478
479 int fips_cipher_test(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
480                         const unsigned char *key,
481                         const unsigned char *iv,
482                         const unsigned char *plaintext,
483                         const unsigned char *ciphertext,
484                         int len)
485         {
486         unsigned char pltmp[FIPS_MAX_CIPHER_TEST_SIZE];
487         unsigned char citmp[FIPS_MAX_CIPHER_TEST_SIZE];
488         OPENSSL_assert(len <= FIPS_MAX_CIPHER_TEST_SIZE);
489         if (EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, 1) <= 0)
490                 return 0;
491         EVP_Cipher(ctx, citmp, plaintext, len);
492         if (memcmp(citmp, ciphertext, len))
493                 return 0;
494         if (EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, 0) <= 0)
495                 return 0;
496         EVP_Cipher(ctx, pltmp, citmp, len);
497         if (memcmp(pltmp, plaintext, len))
498                 return 0;
499         return 1;
500         }
501
502
503 #endif