#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;
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)
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();
{
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 */
if(FIPS_module_mode())
{
- FIPSerr(FIPS_F_FIPS_MODE_SET,FIPS_R_FIPS_MODE_ALREADY_SET);
+ FIPSerr(FIPS_F_FIPS_MODULE_MODE_SET,FIPS_R_FIPS_MODE_ALREADY_SET);
fips_selftest_fail = 1;
ret = 0;
goto end;
}
#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_MODE_SET,FIPS_R_UNSUPPORTED_PLATFORM);
+ 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)
{
- FIPSerr(FIPS_F_FIPS_MODE_SET,FIPS_R_CONTRADICTING_EVIDENCE);
+ FIPSerr(FIPS_F_FIPS_MODULE_MODE_SET,FIPS_R_CONTRADICTING_EVIDENCE);
fips_selftest_fail = 1;
ret = 0;
goto end;
}
if(FIPS_selftest())
- fips_set_mode(1);
+ fips_set_mode(onoff);
else
{
fips_selftest_fail = 1;
return FIPS_signature;
}
+unsigned long FIPS_module_version(void)
+ {
+ return FIPS_MODULE_VERSION_NUMBER;
+ }
+
+const char *FIPS_module_version_text(void)
+ {
+ return FIPS_MODULE_VERSION_TEXT;
+ }
+
#if 0
/* The purpose of this is to ensure the error code exists and the function
* name is to keep the error checking script quiet