823a042f504df68669bbe940c49337a45a71981f
[openssl.git] / fips / fips.c
1 /* ====================================================================
2  * Copyright (c) 2011 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/crypto.h>
53 #include <openssl/rand.h>
54 #include <openssl/fips_rand.h>
55 #include <openssl/err.h>
56 #include <openssl/bio.h>
57 #include <openssl/hmac.h>
58 #include <openssl/rsa.h>
59 #include <openssl/dsa.h>
60 #include <openssl/ecdsa.h>
61 #include <string.h>
62 #include <limits.h>
63 #include "fips_locl.h"
64
65 #ifdef OPENSSL_FIPS
66
67 #include <openssl/fips.h>
68
69 #ifndef PATH_MAX
70 #define PATH_MAX 1024
71 #endif
72
73 static int fips_selftest_fail = 0;
74 static int fips_mode = 0;
75 static int fips_started = 0;
76
77 static int fips_is_owning_thread(void);
78 static int fips_set_owning_thread(void);
79 static int fips_clear_owning_thread(void);
80 static unsigned char *fips_signature_witness(void);
81
82 #define fips_w_lock()   CRYPTO_w_lock(CRYPTO_LOCK_FIPS)
83 #define fips_w_unlock() CRYPTO_w_unlock(CRYPTO_LOCK_FIPS)
84 #define fips_r_lock()   CRYPTO_r_lock(CRYPTO_LOCK_FIPS)
85 #define fips_r_unlock() CRYPTO_r_unlock(CRYPTO_LOCK_FIPS)
86
87 static void fips_set_mode(int onoff)
88         {
89         int owning_thread = fips_is_owning_thread();
90
91         if (fips_started)
92                 {
93                 if (!owning_thread) fips_w_lock();
94                 fips_mode = onoff;
95                 if (!owning_thread) fips_w_unlock();
96                 }
97         }
98
99 int FIPS_module_mode(void)
100         {
101         int ret = 0;
102         int owning_thread = fips_is_owning_thread();
103
104         if (fips_started)
105                 {
106                 if (!owning_thread) fips_r_lock();
107                 ret = fips_mode;
108                 if (!owning_thread) fips_r_unlock();
109                 }
110         return ret;
111         }
112
113 int FIPS_selftest_failed(void)
114     {
115     int ret = 0;
116     if (fips_started)
117         {
118         int owning_thread = fips_is_owning_thread();
119
120         if (!owning_thread) fips_r_lock();
121         ret = fips_selftest_fail;
122         if (!owning_thread) fips_r_unlock();
123         }
124     return ret;
125     }
126
127 /* Selftest failure fatal exit routine. This will be called
128  * during *any* cryptographic operation. It has the minimum
129  * overhead possible to avoid too big a performance hit.
130  */
131
132 void FIPS_selftest_check(void)
133     {
134     if (fips_selftest_fail)
135         {
136         OpenSSLDie(__FILE__,__LINE__, "FATAL FIPS SELFTEST FAILURE");
137         }
138     }
139
140 void fips_set_selftest_fail(void)
141     {
142     fips_selftest_fail = 1;
143     }
144
145 extern const void         *FIPS_text_start(),  *FIPS_text_end();
146 extern const unsigned char FIPS_rodata_start[], FIPS_rodata_end[];
147 unsigned char              FIPS_signature [20] = { 0 };
148 static const char          FIPS_hmac_key[]="etaonrishdlcupfm";
149
150 unsigned int FIPS_incore_fingerprint(unsigned char *sig,unsigned int len)
151     {
152     const unsigned char *p1 = FIPS_text_start();
153     const unsigned char *p2 = FIPS_text_end();
154     const unsigned char *p3 = FIPS_rodata_start;
155     const unsigned char *p4 = FIPS_rodata_end;
156     HMAC_CTX c;
157
158     HMAC_CTX_init(&c);
159     HMAC_Init(&c,FIPS_hmac_key,strlen(FIPS_hmac_key),EVP_sha1());
160
161     /* detect overlapping regions */
162     if (p1<=p3 && p2>=p3)
163         p3=p1, p4=p2>p4?p2:p4, p1=NULL, p2=NULL;
164     else if (p3<=p1 && p4>=p1)
165         p3=p3, p4=p2>p4?p2:p4, p1=NULL, p2=NULL;
166
167     if (p1)
168         HMAC_Update(&c,p1,(size_t)p2-(size_t)p1);
169
170     if (FIPS_signature>=p3 && FIPS_signature<p4)
171         {
172         /* "punch" hole */
173         HMAC_Update(&c,p3,(size_t)FIPS_signature-(size_t)p3);
174         p3 = FIPS_signature+sizeof(FIPS_signature);
175         if (p3<p4)
176             HMAC_Update(&c,p3,(size_t)p4-(size_t)p3);
177         }
178     else
179         HMAC_Update(&c,p3,(size_t)p4-(size_t)p3);
180
181     if (!fips_post_corrupt(FIPS_TEST_INTEGRITY, 0, NULL))
182         HMAC_Update(&c, (unsigned char *)FIPS_hmac_key, 1);
183
184     HMAC_Final(&c,sig,&len);
185     HMAC_CTX_cleanup(&c);
186
187     return len;
188     }
189
190 int FIPS_check_incore_fingerprint(void)
191     {
192     unsigned char sig[EVP_MAX_MD_SIZE];
193     unsigned int len;
194     int rv = 0;
195 #if defined(__sgi) && (defined(__mips) || defined(mips))
196     extern int __dso_displacement[];
197 #else
198     extern int OPENSSL_NONPIC_relocated;
199 #endif
200
201     if (!fips_post_started(FIPS_TEST_INTEGRITY, 0, NULL))
202         return 1;
203
204     if (FIPS_text_start()==NULL)
205         {
206         FIPSerr(FIPS_F_FIPS_CHECK_INCORE_FINGERPRINT,FIPS_R_UNSUPPORTED_PLATFORM);
207         goto err;
208         }
209
210     len=FIPS_incore_fingerprint(sig,sizeof(sig));
211
212     if (len!=sizeof(FIPS_signature) ||
213         memcmp(FIPS_signature,sig,sizeof(FIPS_signature)))
214         {
215         if (FIPS_signature>=FIPS_rodata_start && FIPS_signature<FIPS_rodata_end)
216             FIPSerr(FIPS_F_FIPS_CHECK_INCORE_FINGERPRINT,FIPS_R_FINGERPRINT_DOES_NOT_MATCH_SEGMENT_ALIASING);
217 #if defined(__sgi) && (defined(__mips) || defined(mips))
218         else if (__dso_displacement!=NULL)
219 #else
220         else if (OPENSSL_NONPIC_relocated)
221 #endif
222             FIPSerr(FIPS_F_FIPS_CHECK_INCORE_FINGERPRINT,FIPS_R_FINGERPRINT_DOES_NOT_MATCH_NONPIC_RELOCATED);
223         else
224             FIPSerr(FIPS_F_FIPS_CHECK_INCORE_FINGERPRINT,FIPS_R_FINGERPRINT_DOES_NOT_MATCH);
225 #ifdef OPENSSL_FIPS_DEBUGGER
226         rv = 1;
227 #endif
228         goto err;
229         }
230     rv = 1;
231     err:
232     if (rv == 0)
233         fips_post_failed(FIPS_TEST_INTEGRITY, 0, NULL);
234     else
235         if (!fips_post_success(FIPS_TEST_INTEGRITY, 0, NULL))
236                 return 0;
237     return rv;
238     }
239
240 int FIPS_module_mode_set(int onoff)
241     {
242     int ret = 0;
243
244     fips_w_lock();
245     fips_started = 1;
246     fips_set_owning_thread();
247
248     if(onoff)
249         {
250
251         fips_selftest_fail = 0;
252
253         /* Don't go into FIPS mode twice, just so we can do automagic
254            seeding */
255         if(FIPS_module_mode())
256             {
257             FIPSerr(FIPS_F_FIPS_MODULE_MODE_SET,FIPS_R_FIPS_MODE_ALREADY_SET);
258             fips_selftest_fail = 1;
259             ret = 0;
260             goto end;
261             }
262
263 #ifdef OPENSSL_IA32_SSE2
264         if ((OPENSSL_ia32cap & (1<<25|1<<26)) != (1<<25|1<<26))
265             {
266             FIPSerr(FIPS_F_FIPS_MODULE_MODE_SET,FIPS_R_UNSUPPORTED_PLATFORM);
267             fips_selftest_fail = 1;
268             ret = 0;
269             goto end;
270             }
271 #endif
272
273         if(fips_signature_witness() != FIPS_signature)
274             {
275             FIPSerr(FIPS_F_FIPS_MODULE_MODE_SET,FIPS_R_CONTRADICTING_EVIDENCE);
276             fips_selftest_fail = 1;
277             ret = 0;
278             goto end;
279             }
280
281         if(FIPS_selftest())
282             fips_set_mode(onoff);
283         else
284             {
285             fips_selftest_fail = 1;
286             ret = 0;
287             goto end;
288             }
289         ret = 1;
290         goto end;
291         }
292     fips_set_mode(0);
293     fips_selftest_fail = 0;
294     ret = 1;
295 end:
296     fips_clear_owning_thread();
297     fips_w_unlock();
298     return ret;
299     }
300
301 static CRYPTO_THREADID fips_thread;
302 static int fips_thread_set = 0;
303
304 static int fips_is_owning_thread(void)
305         {
306         int ret = 0;
307
308         if (fips_started)
309                 {
310                 CRYPTO_r_lock(CRYPTO_LOCK_FIPS2);
311                 if (fips_thread_set)
312                         {
313                         CRYPTO_THREADID cur;
314                         CRYPTO_THREADID_current(&cur);
315                         if (!CRYPTO_THREADID_cmp(&cur, &fips_thread))
316                                 ret = 1;
317                         }
318                 CRYPTO_r_unlock(CRYPTO_LOCK_FIPS2);
319                 }
320         return ret;
321         }
322
323 int fips_set_owning_thread(void)
324         {
325         int ret = 0;
326
327         if (fips_started)
328                 {
329                 CRYPTO_w_lock(CRYPTO_LOCK_FIPS2);
330                 if (!fips_thread_set)
331                         {
332                         CRYPTO_THREADID_current(&fips_thread);
333                         ret = 1;
334                         fips_thread_set = 1;
335                         }
336                 CRYPTO_w_unlock(CRYPTO_LOCK_FIPS2);
337                 }
338         return ret;
339         }
340
341 int fips_clear_owning_thread(void)
342         {
343         int ret = 0;
344
345         if (fips_started)
346                 {
347                 CRYPTO_w_lock(CRYPTO_LOCK_FIPS2);
348                 if (fips_thread_set)
349                         {
350                         CRYPTO_THREADID cur;
351                         CRYPTO_THREADID_current(&cur);
352                         if (!CRYPTO_THREADID_cmp(&cur, &fips_thread))
353                                 fips_thread_set = 0;
354                         }
355                 CRYPTO_w_unlock(CRYPTO_LOCK_FIPS2);
356                 }
357         return ret;
358         }
359
360 unsigned char *fips_signature_witness(void)
361         {
362         extern unsigned char FIPS_signature[];
363         return FIPS_signature;
364         }
365
366 unsigned long FIPS_module_version(void)
367         {
368         return FIPS_MODULE_VERSION_NUMBER;
369         }
370
371 const char *FIPS_module_version_text(void)
372         {
373         return FIPS_MODULE_VERSION_TEXT;
374         }
375
376 #if 0
377 /* The purpose of this is to ensure the error code exists and the function
378  * name is to keep the error checking script quiet
379  */
380 void hash_final(void)
381         {
382         FIPSerr(FIPS_F_HASH_FINAL,FIPS_R_NON_FIPS_METHOD);
383         }
384 #endif
385
386
387 #endif