e_rc4_hmac_md5.c: last commit was inappropriate for non-x86[_64] platforms.
[openssl.git] / fips / fips.c
index ef9c0bddaabbc650c231c6e755e368e5eeadcea9..36ac8d1b0c18650dfd82d75f64523bc5537c65ef 100644 (file)
@@ -61,6 +61,7 @@
 #include <string.h>
 #include <limits.h>
 #include "fips_locl.h"
+#include "fips_auth.h"
 
 #ifdef OPENSSL_FIPS
 
 #define PATH_MAX 1024
 #endif
 
+#define atox(c) ((c)>='a'?((c)-'a'+10):((c)>='A'?(c)-'A'+10:(c)-'0'))
+
 static int fips_selftest_fail = 0;
+static int fips_auth_fail = 0;
 static int fips_mode = 0;
 static int fips_started = 0;
 
@@ -145,6 +149,7 @@ void fips_set_selftest_fail(void)
 extern const void         *FIPS_text_start(),  *FIPS_text_end();
 extern const unsigned char FIPS_rodata_start[], FIPS_rodata_end[];
 unsigned char              FIPS_signature [20] = { 0 };
+__fips_constseg
 static const char          FIPS_hmac_key[]="etaonrishdlcupfm";
 
 unsigned int FIPS_incore_fingerprint(unsigned char *sig,unsigned int len)
@@ -237,10 +242,47 @@ int FIPS_check_incore_fingerprint(void)
     return rv;
     }
 
-int FIPS_module_mode_set(int onoff)
+static int fips_asc_check(const unsigned char *sig, const char *asc_sig)
+    {
+    char tsig[20];
+    const char *p;
+    int i;
+    if (strlen(asc_sig) != 40)
+       return 0;
+    for (i = 0, p = asc_sig; i < 20; i++, p += 2)
+       tsig[i] = (atox(p[0]) << 4) | atox(p[1]);
+    if (memcmp(tsig, sig, 20))
+       return 0;
+    return 1;
+    }
+
+static int fips_check_auth(const char *auth)
+    {
+    unsigned char auth_hmac[20];
+    unsigned int hmac_len;
+    if (fips_auth_fail)
+       return 0;
+    if (strlen(auth) < FIPS_AUTH_MIN_LEN)
+       return 0;
+    if (!HMAC(EVP_sha1(), FIPS_AUTH_KEY, strlen(FIPS_AUTH_KEY),
+               (unsigned char *)auth, strlen(auth), auth_hmac, &hmac_len))
+       return 0;
+    if (hmac_len != sizeof(auth_hmac))
+       return 0;
+
+    if (fips_asc_check(auth_hmac, FIPS_AUTH_CRYPTO_OFFICER))
+       return 1;
+
+    if (fips_asc_check(auth_hmac, FIPS_AUTH_CRYPTO_USER))
+       return 1;
+
+    return 0;
+    }
+       
+    
+
+int FIPS_module_mode_set(int onoff, const char *auth)
     {
-    int fips_set_owning_thread();
-    int fips_clear_owning_thread();
     int ret = 0;
 
     fips_w_lock();
@@ -251,6 +293,13 @@ int FIPS_module_mode_set(int onoff)
        {
 
        fips_selftest_fail = 0;
+       if (!fips_check_auth(auth))
+           {
+           fips_auth_fail = 1;
+           fips_selftest_fail = 1;
+           FIPSerr(FIPS_F_FIPS_MODULE_MODE_SET,FIPS_R_AUTHENTICATION_FAILURE);
+           return 0;
+           }
 
        /* Don't go into FIPS mode twice, just so we can do automagic
           seeding */
@@ -263,13 +312,18 @@ int FIPS_module_mode_set(int onoff)
            }
 
 #ifdef OPENSSL_IA32_SSE2
-       if ((OPENSSL_ia32cap & (1<<25|1<<26)) != (1<<25|1<<26))
+       {
+       extern unsigned int OPENSSL_ia32cap_P[2];
+       if ((OPENSSL_ia32cap_P[0] & (1<<25|1<<26)) != (1<<25|1<<26))
            {
            FIPSerr(FIPS_F_FIPS_MODULE_MODE_SET,FIPS_R_UNSUPPORTED_PLATFORM);
            fips_selftest_fail = 1;
            ret = 0;
            goto end;
            }
+       OPENSSL_ia32cap_P[0] |= (1<<28);        /* set "shared cache"   */
+       OPENSSL_ia32cap_P[1] &= ~(1<<(60-32));  /* clear AVX            */
+       }
 #endif
 
        if(fips_signature_witness() != FIPS_signature)