File openssl-fips__0300_run_selftests_if_hmac_files_present.diff of Package compat-openssl098.703
diff -rNU 50 ../openssl-0.9.8j-o/crypto/o_init.c ./crypto/o_init.c
--- ../openssl-0.9.8j-o/crypto/o_init.c 2012-07-10 02:06:00.000000000 +0200
+++ ./crypto/o_init.c 2012-07-10 03:01:34.000000000 +0200
@@ -29,96 +29,128 @@
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
#include <e_os.h>
#include <openssl/err.h>
#ifdef OPENSSL_FIPS
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <openssl/fips.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#define FIPS_MODE_SWITCH_FILE "/proc/sys/crypto/fips_enabled"
static void init_fips_mode(void)
{
char buf[2] = "0";
int fd;
-
+
+ /* Check if we have already been initialized by FIPS_mode_set(1)
+ * called directly from the app. If this was the case, calling
+ * FIPS_mode_set(1) a second time will lead to a failure
+ * in fips/fips.c:486, so we better avoid that with this mimic
+ * to switch via kernel cmdline and/or environment without the
+ * app knowing.
+ *
+ * Note that if we are in fips mode already, there is no need to
+ * run through the self-tests (further down) either.
+ *
+ */
+
+ if(FIPS_mode())
+ return;
+
+ /* The following must be without the app knowing. Including the
+ * forced self-test if the .hmac files are present, marking the
+ * complete installation of the module.
+ *
+ */
+
if (getenv("OPENSSL_FORCE_FIPS_MODE") != NULL)
{
buf[0] = '1';
}
else if ((fd = open(FIPS_MODE_SWITCH_FILE, O_RDONLY)) >= 0)
{
while (read(fd, buf, sizeof(buf)) < 0 && errno == EINTR);
close(fd);
}
/* Failure reading the fips mode switch file means just not
- * switching into FIPS mode. We would break too many things
- * otherwise.
+ * switching into FIPS mode.
+ *
+ * If we don't switch into FIPS mode, we MUST run the self-tests
+ * anyway, provided that the module is installed completely.
+ * This will check if the .hmac files for the integrity check
+ * in fips/fips.c:FIPSCHECK_verify() exist. If so, the selftests
+ * are executed, if no .hmac files are present, the selftests are
+ * aborted gracefully.
+ *
*/
if (buf[0] == '1')
{
FIPS_mode_set(1);
}
+ else
+ {
+ FIPS_mode_set(0);
+ }
}
#endif
/* Perform any essential OpenSSL initialization operations.
* Currently only sets FIPS callbacks
*/
void OPENSSL_init(void)
{
#ifdef OPENSSL_FIPS
static int done = 0;
if (!done)
{
int_ERR_lib_init();
#ifdef CRYPTO_MDEBUG
CRYPTO_malloc_debug_init();
#endif
init_fips_mode();
int_EVP_MD_init_engine_callbacks();
int_EVP_CIPHER_init_engine_callbacks();
int_RAND_init_engine_callbacks();
done = 1;
}
#endif
}
diff -rNU 50 ../openssl-0.9.8j-o/fips/fips.c ./fips/fips.c
--- ../openssl-0.9.8j-o/fips/fips.c 2012-07-10 02:06:00.000000000 +0200
+++ ./fips/fips.c 2012-07-10 02:06:21.000000000 +0200
@@ -346,253 +346,304 @@
static const char hmackey[] = "ppaksykemnsecgtsttplmamstKMEs";
static int
compute_file_hmac(const char *path, void **buf, size_t *hmaclen)
{
FILE *f = NULL;
int rv = -1;
unsigned char rbuf[READ_BUFFER_LENGTH];
size_t len;
unsigned int hlen;
HMAC_CTX c;
HMAC_CTX_init(&c);
f = fopen(path, "r");
if (f == NULL) {
goto end;
}
HMAC_Init(&c, hmackey, sizeof(hmackey)-1, EVP_sha256());
while ((len=fread(rbuf, 1, sizeof(rbuf), f)) != 0) {
HMAC_Update(&c, rbuf, len);
}
len = sizeof(rbuf);
/* reuse rbuf for hmac */
HMAC_Final(&c, rbuf, &hlen);
*buf = malloc(hlen);
if (*buf == NULL) {
goto end;
}
*hmaclen = hlen;
memcpy(*buf, rbuf, hlen);
rv = 0;
end:
HMAC_CTX_cleanup(&c);
if (f)
fclose(f);
return rv;
}
static int
-FIPSCHECK_verify(const char *libname, const char *symbolname)
+FIPSCHECK_verify(const char *libname, const char *symbolname, int check_hmac_file_open_only)
{
char path[PATH_MAX+1];
int rv;
FILE *hf;
char *hmacpath, *p;
char *hmac = NULL;
size_t n;
rv = get_library_path(libname, symbolname, path, sizeof(path));
if (rv < 0)
return 0;
hmacpath = make_hmac_path(path);
if ( hmacpath == NULL )
return 0;
hf = fopen(hmacpath, "r");
if (hf == NULL) {
free(hmacpath);
return 0;
}
+ if (check_hmac_file_open_only == 1) {
+ fclose(hf);
+ free(hmacpath);
+ return 1;
+ }
+
if (getline(&hmac, &n, hf) > 0) {
void *buf;
size_t hmaclen;
char *hex;
if ((p=strchr(hmac, '\n')) != NULL)
*p = '\0';
if (compute_file_hmac(path, &buf, &hmaclen) < 0) {
rv = -4;
goto end;
}
if ((hex=bin2hex(buf, hmaclen)) == NULL) {
free(buf);
rv = -5;
goto end;
}
if (strcmp(hex, hmac) != 0) {
rv = -1;
}
free(buf);
free(hex);
}
end:
free(hmac);
free(hmacpath);
fclose(hf);
if (rv < 0)
return 0;
/* check successful */
return 1;
}
#endif
int FIPS_mode_set(int onoff)
{
int fips_set_owning_thread();
int fips_clear_owning_thread();
int ret = 0;
fips_w_lock();
fips_set_started();
fips_set_owning_thread();
if(onoff)
{
unsigned char buf[48];
fips_selftest_fail = 0;
/* Don't go into FIPS mode twice, just so we can do automagic
seeding */
if(FIPS_mode())
{
FIPSerr(FIPS_F_FIPS_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))
{
FIPSerr(FIPS_F_FIPS_MODE_SET,FIPS_R_UNSUPPORTED_PLATFORM);
fips_selftest_fail = 1;
ret = 0;
goto end;
}
#endif
- if(!FIPSCHECK_verify("libcrypto.so.0.9.8","FIPS_mode_set"))
+ if(!FIPSCHECK_verify("libcrypto.so.0.9.8","FIPS_mode_set", 0 ))
{
FIPSerr(FIPS_F_FIPS_MODE_SET,FIPS_R_FINGERPRINT_DOES_NOT_MATCH);
fips_selftest_fail = 1;
ret = 0;
goto end;
}
- if(!FIPSCHECK_verify("libssl.so.0.9.8","SSL_CTX_new"))
+ if(!FIPSCHECK_verify("libssl.so.0.9.8","SSL_CTX_new", 0 ))
{
FIPSerr(FIPS_F_FIPS_MODE_SET,FIPS_R_FINGERPRINT_DOES_NOT_MATCH);
fips_selftest_fail = 1;
ret = 0;
goto end;
}
/* Perform RNG KAT before seeding */
if (!FIPS_selftest_rng())
{
fips_selftest_fail = 1;
ret = 0;
goto end;
}
/* now switch into FIPS mode */
fips_set_rand_check(FIPS_rand_method());
RAND_set_rand_method(FIPS_rand_method());
/* automagically seed PRNG if not already seeded */
if(!FIPS_rand_status())
{
RAND_poll();
if (!FIPS_rand_status())
{
fips_selftest_fail = 1;
ret = 0;
goto end;
}
}
if(FIPS_selftest())
fips_set_mode(1);
else
{
fips_selftest_fail = 1;
ret = 0;
goto end;
}
ret = 1;
goto end;
- }
+ } else {
+ /*
+ * onoff == 0, we need to do the self-tests.
+ *
+ * check if the .hmac files are there. If not, then abort
+ * running the self-tests gracefully.
+ *
+ */
+ if( FIPSCHECK_verify("libcrypto.so.0.9.8","FIPS_mode_set", 1) &&
+ FIPSCHECK_verify("libssl.so.0.9.8","SSL_CTX_new", 1) ) {
+
+/* hmac files are present. */
+
+ if(!FIPSCHECK_verify("libcrypto.so.0.9.8","FIPS_mode_set", 0 ))
+ {
+ FIPSerr(FIPS_F_FIPS_MODE_SET,FIPS_R_FINGERPRINT_DOES_NOT_MATCH);
+ fips_selftest_fail = 1;
+ ret = 0;
+ goto end;
+ }
+
+ if(!FIPSCHECK_verify("libssl.so.0.9.8","SSL_CTX_new", 0 ))
+ {
+ FIPSerr(FIPS_F_FIPS_MODE_SET,FIPS_R_FINGERPRINT_DOES_NOT_MATCH);
+ fips_selftest_fail = 1;
+ ret = 0;
+ goto end;
+ }
+
+ /* Perform RNG KAT */
+ if (!FIPS_selftest_rng())
+ {
+ fips_selftest_fail = 1;
+ ret = 0;
+ goto end;
+ }
+
+ if( ! FIPS_selftest())
+ {
+ fips_selftest_fail = 1;
+ ret = 0;
+ goto end;
+ }
+ }
+ } /* onoff == 0 */
+
fips_set_mode(0);
fips_selftest_fail = 0;
ret = 1;
end:
fips_clear_owning_thread();
fips_w_unlock();
return ret;
}
void fips_w_lock(void) { CRYPTO_w_lock(CRYPTO_LOCK_FIPS); }
void fips_w_unlock(void) { CRYPTO_w_unlock(CRYPTO_LOCK_FIPS); }
void fips_r_lock(void) { CRYPTO_r_lock(CRYPTO_LOCK_FIPS); }
void fips_r_unlock(void) { CRYPTO_r_unlock(CRYPTO_LOCK_FIPS); }
static int fips_started = 0;
static unsigned long fips_thread = 0;
void fips_set_started(void)
{
fips_started = 1;
}
int fips_is_started(void)
{
return fips_started;
}
int fips_is_owning_thread(void)
{
int ret = 0;
if (fips_is_started())
{
CRYPTO_r_lock(CRYPTO_LOCK_FIPS2);
if (fips_thread != 0 && fips_thread == CRYPTO_thread_id())
ret = 1;
CRYPTO_r_unlock(CRYPTO_LOCK_FIPS2);
}
return ret;
}
int fips_set_owning_thread(void)
{
int ret = 0;
if (fips_is_started())
{
CRYPTO_w_lock(CRYPTO_LOCK_FIPS2);
if (fips_thread == 0)
{