typo
[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     HMAC_CTX_init(&c);
164     HMAC_Init(&c,FIPS_hmac_key,strlen(FIPS_hmac_key),EVP_sha1());
165
166     /* detect overlapping regions */
167     if (p1<=p3 && p2>=p3)
168         p3=p1, p4=p2>p4?p2:p4, p1=NULL, p2=NULL;
169     else if (p3<=p1 && p4>=p1)
170         p3=p3, p4=p2>p4?p2:p4, p1=NULL, p2=NULL;
171
172     if (p1)
173         HMAC_Update(&c,p1,(size_t)p2-(size_t)p1);
174
175     if (FIPS_signature>=p3 && FIPS_signature<p4)
176         {
177         /* "punch" hole */
178         HMAC_Update(&c,p3,(size_t)FIPS_signature-(size_t)p3);
179         p3 = FIPS_signature+sizeof(FIPS_signature);
180         if (p3<p4)
181             HMAC_Update(&c,p3,(size_t)p4-(size_t)p3);
182         }
183     else
184         HMAC_Update(&c,p3,(size_t)p4-(size_t)p3);
185
186     if (!fips_post_corrupt(FIPS_TEST_INTEGRITY, 0, NULL))
187         HMAC_Update(&c, (unsigned char *)FIPS_hmac_key, 1);
188
189     HMAC_Final(&c,sig,&len);
190     HMAC_CTX_cleanup(&c);
191
192     return len;
193     }
194
195 int FIPS_check_incore_fingerprint(void)
196     {
197     unsigned char sig[EVP_MAX_MD_SIZE];
198     unsigned int len;
199     int rv = 0;
200 #if defined(__sgi) && (defined(__mips) || defined(mips))
201     extern int __dso_displacement[];
202 #else
203     extern int OPENSSL_NONPIC_relocated;
204 #endif
205
206     if (!fips_post_started(FIPS_TEST_INTEGRITY, 0, NULL))
207         return 1;
208
209     if (FIPS_text_start()==NULL)
210         {
211         FIPSerr(FIPS_F_FIPS_CHECK_INCORE_FINGERPRINT,FIPS_R_UNSUPPORTED_PLATFORM);
212         goto err;
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_INCORE_FINGERPRINT,FIPS_R_FINGERPRINT_DOES_NOT_MATCH_SEGMENT_ALIASING);
222 #if defined(__sgi) && (defined(__mips) || defined(mips))
223         else if (__dso_displacement!=NULL)
224 #else
225         else if (OPENSSL_NONPIC_relocated)
226 #endif
227             FIPSerr(FIPS_F_FIPS_CHECK_INCORE_FINGERPRINT,FIPS_R_FINGERPRINT_DOES_NOT_MATCH_NONPIC_RELOCATED);
228         else
229             FIPSerr(FIPS_F_FIPS_CHECK_INCORE_FINGERPRINT,FIPS_R_FINGERPRINT_DOES_NOT_MATCH);
230 #ifdef OPENSSL_FIPS_DEBUGGER
231         rv = 1;
232 #endif
233         goto err;
234         }
235     rv = 1;
236     err:
237     if (rv == 0)
238         fips_post_failed(FIPS_TEST_INTEGRITY, 0, NULL);
239     else
240         if (!fips_post_success(FIPS_TEST_INTEGRITY, 0, NULL))
241                 return 0;
242     return rv;
243     }
244
245 static int fips_asc_check(const unsigned char *sig, const char *asc_sig)
246     {
247     char tsig[20];
248     const char *p;
249     int i;
250     if (strlen(asc_sig) != 40)
251         return 0;
252     for (i = 0, p = asc_sig; i < 20; i++, p += 2)
253         tsig[i] = (atox(p[0]) << 4) | atox(p[1]);
254     if (memcmp(tsig, sig, 20))
255         return 0;
256     return 1;
257     }
258
259 static int fips_check_auth(const char *auth)
260     {
261     unsigned char auth_hmac[20];
262     unsigned int hmac_len;
263     if (fips_auth_fail)
264         return 0;
265     if (strlen(auth) < FIPS_AUTH_MIN_LEN)
266         return 0;
267     if (!HMAC(EVP_sha1(), FIPS_AUTH_KEY, strlen(FIPS_AUTH_KEY),
268                 (unsigned char *)auth, strlen(auth), auth_hmac, &hmac_len))
269         return 0;
270     if (hmac_len != sizeof(auth_hmac))
271         return 0;
272
273     if (fips_asc_check(auth_hmac, FIPS_AUTH_CRYPTO_OFFICER))
274         return 1;
275
276     if (fips_asc_check(auth_hmac, FIPS_AUTH_CRYPTO_USER))
277         return 1;
278
279     return 0;
280     }
281         
282     
283
284 int FIPS_module_mode_set(int onoff, const char *auth)
285     {
286     int ret = 0;
287
288     fips_w_lock();
289     fips_started = 1;
290     fips_set_owning_thread();
291
292     if(onoff)
293         {
294
295         fips_selftest_fail = 0;
296         if (!fips_check_auth(auth))
297             {
298             fips_auth_fail = 1;
299             fips_selftest_fail = 1;
300             FIPSerr(FIPS_F_FIPS_MODULE_MODE_SET,FIPS_R_AUTHENTICATION_FAILURE);
301             return 0;
302             }
303
304         /* Don't go into FIPS mode twice, just so we can do automagic
305            seeding */
306         if(FIPS_module_mode())
307             {
308             FIPSerr(FIPS_F_FIPS_MODULE_MODE_SET,FIPS_R_FIPS_MODE_ALREADY_SET);
309             fips_selftest_fail = 1;
310             ret = 0;
311             goto end;
312             }
313
314 #ifdef OPENSSL_IA32_SSE2
315         {
316         extern unsigned int OPENSSL_ia32cap_P[2];
317         if ((OPENSSL_ia32cap_P[0] & (1<<25|1<<26)) != (1<<25|1<<26))
318             {
319             FIPSerr(FIPS_F_FIPS_MODULE_MODE_SET,FIPS_R_UNSUPPORTED_PLATFORM);
320             fips_selftest_fail = 1;
321             ret = 0;
322             goto end;
323             }
324         OPENSSL_ia32cap_P[0] |= (1<<28);        /* set "shared cache"   */
325         OPENSSL_ia32cap_P[1] &= ~(1<<(60-32));  /* clear AVX            */
326         }
327 #endif
328
329         if(fips_signature_witness() != FIPS_signature)
330             {
331             FIPSerr(FIPS_F_FIPS_MODULE_MODE_SET,FIPS_R_CONTRADICTING_EVIDENCE);
332             fips_selftest_fail = 1;
333             ret = 0;
334             goto end;
335             }
336
337         if(FIPS_selftest())
338             fips_set_mode(onoff);
339         else
340             {
341             fips_selftest_fail = 1;
342             ret = 0;
343             goto end;
344             }
345         ret = 1;
346         goto end;
347         }
348     fips_set_mode(0);
349     fips_selftest_fail = 0;
350     ret = 1;
351 end:
352     fips_clear_owning_thread();
353     fips_w_unlock();
354     return ret;
355     }
356
357 static CRYPTO_THREADID fips_thread;
358 static int fips_thread_set = 0;
359
360 static int fips_is_owning_thread(void)
361         {
362         int ret = 0;
363
364         if (fips_started)
365                 {
366                 CRYPTO_r_lock(CRYPTO_LOCK_FIPS2);
367                 if (fips_thread_set)
368                         {
369                         CRYPTO_THREADID cur;
370                         CRYPTO_THREADID_current(&cur);
371                         if (!CRYPTO_THREADID_cmp(&cur, &fips_thread))
372                                 ret = 1;
373                         }
374                 CRYPTO_r_unlock(CRYPTO_LOCK_FIPS2);
375                 }
376         return ret;
377         }
378
379 int fips_set_owning_thread(void)
380         {
381         int ret = 0;
382
383         if (fips_started)
384                 {
385                 CRYPTO_w_lock(CRYPTO_LOCK_FIPS2);
386                 if (!fips_thread_set)
387                         {
388                         CRYPTO_THREADID_current(&fips_thread);
389                         ret = 1;
390                         fips_thread_set = 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 unsigned long FIPS_module_version(void)
423         {
424         return FIPS_MODULE_VERSION_NUMBER;
425         }
426
427 const char *FIPS_module_version_text(void)
428         {
429         return FIPS_MODULE_VERSION_TEXT;
430         }
431
432 #if 0
433 /* The purpose of this is to ensure the error code exists and the function
434  * name is to keep the error checking script quiet
435  */
436 void hash_final(void)
437         {
438         FIPSerr(FIPS_F_HASH_FINAL,FIPS_R_NON_FIPS_METHOD);
439         }
440 #endif
441
442
443 #endif