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