openssl/fips/fips_premain.c
Matt Caswell 40720ce3ca Run util/openssl-format-source -v -c .
Reviewed-by: Tim Hudson <tjh@openssl.org>
2015-01-22 09:52:55 +00:00

191 lines
5.7 KiB
C

/* ====================================================================
* Copyright (c) 2005 The OpenSSL Project. Rights for redistribution
* and usage in source and binary forms are granted according to the
* OpenSSL license.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(__unix) || defined(__unix__)
# include <unistd.h>
#endif
#ifndef FINGERPRINT_PREMAIN_DSO_LOAD
# if defined(__GNUC__) && __GNUC__>=2
void FINGERPRINT_premain(void) __attribute__ ((constructor));
/*
* Most commonly this results in pointer to premain to be dropped to .ctors
* segment, which is traversed by GCC crtbegin.o upon program startup.
* Except on a.out OpenBSD where it results in _GLOBAL_$I$premain()
* {premain();} being auto-generated by compiler... But one way or another
* this is believed to cover *all* GCC targets.
*/
# elif defined(_MSC_VER)
# ifdef _WINDLL
__declspec(dllexport) /* this is essentially cosmetics... */
# endif
void FINGERPRINT_premain(void);
static int premain_wrapper(void)
{
FINGERPRINT_premain();
return 0;
}
# ifdef _WIN64
# pragma section(".CRT$XCU",read)
__declspec(allocate(".CRT$XCU"))
# else
# pragma data_seg(".CRT$XCU")
# endif
static int (*p) (void) = premain_wrapper;
/*
* This results in pointer to premain to appear in .CRT segment, which is
* traversed by Visual C run-time initialization code. This applies to both
* Win32 and [all flavors of] Win64.
*/
# pragma data_seg()
# elif defined(__SUNPRO_C)
void FINGERPRINT_premain(void);
# pragma init(FINGERPRINT_premain)
/* This results in a call to premain to appear in .init segment. */
# elif defined(__DECC) && (defined(__VMS) || defined(VMS))
void FINGERPRINT_premain(void);
# pragma __nostandard
globaldef {
"LIB$INITIALIZ"} readonly _align(LONGWORD)
int spare[8] = { 0 };
globaldef {
"LIB$INITIALIZE"} readonly _align(LONGWORD)
void (*x_FINGERPRINT_premain) (void) = FINGERPRINT_premain;
/* Refer to LIB$INITIALIZE to ensure it exists in the image. */
int lib$initialize();
globaldef int (*lib_init_ref) () = lib$initialize;
# pragma __standard
# elif 0
The rest has to be taken care of through command line:-Wl, -init,
FINGERPRINT_premain on OSF1 and IRIX - Wl, +init,
FINGERPRINT_premain on HP - UX - Wl,
-binitfini:FINGERPRINT_premain on AIX On ELF platforms this results in a
call to premain to appear in.init segment ...
# endif
# ifndef HMAC_SHA1_SIG
# define HMAC_SHA1_SIG "?have to make sure this string is unique"
# endif
static const unsigned char FINGERPRINT_ascii_value[40] = HMAC_SHA1_SIG;
# define atox(c) ((c)>='a'?((c)-'a'+10):((c)>='A'?(c)-'A'+10:(c)-'0'))
extern const void *FIPS_text_start(), *FIPS_text_end();
extern const unsigned char FIPS_rodata_start[], FIPS_rodata_end[];
extern unsigned char FIPS_signature[20];
extern unsigned int FIPS_incore_fingerprint(unsigned char *, unsigned int);
/*
* As name suggests this code is executed prior main(). We use this
* opportunity to fingerprint sequestered code in virtual address
* space of target application.
*/
void FINGERPRINT_premain(void)
{
unsigned char sig[sizeof(FIPS_signature)];
const unsigned char *volatile p = FINGERPRINT_ascii_value;
unsigned int len = sizeof(sig), i;
/* "volatilization" is done to disengage unwanted optimization... */
if (*((volatile unsigned char *)p) == '?') {
if (FIPS_text_start() == NULL) {
fprintf(stderr, "FIPS_text_start() returns NULL\n");
_exit(1);
}
# if defined(DEBUG_FINGERPRINT_PREMAIN)
fprintf(stderr, ".text:%p+%d=%p\n", FIPS_text_start(),
(int)((size_t)FIPS_text_end() - (size_t)FIPS_text_start()),
FIPS_text_end());
fprintf(stderr, ".rodata:%p+%d=%p\n", FIPS_rodata_start,
(int)((size_t)FIPS_rodata_end - (size_t)FIPS_rodata_start),
FIPS_rodata_end);
# endif
len = FIPS_incore_fingerprint(sig, sizeof(sig));
if (len != sizeof(sig)) {
fprintf(stderr, "fingerprint length mismatch: %u\n", len);
_exit(1);
}
for (i = 0; i < len; i++)
printf("%02x", sig[i]);
printf("\n");
fflush(stdout);
_exit(0);
} else if (FIPS_signature[0] == '\0')
do {
for (i = 0; i < sizeof(FIPS_signature); i++, p += 2)
FIPS_signature[i] = (atox(p[0]) << 4) | atox(p[1]);
# if defined(DEBUG_FINGERPRINT_PREMAIN)
if (getenv("OPENSSL_FIPS") == NULL)
break;
len = FIPS_incore_fingerprint(sig, sizeof(sig));
if (memcmp(FIPS_signature, sig, sizeof(FIPS_signature))) {
fprintf(stderr,
"FINGERPRINT_premain: FIPS_signature mismatch\n");
_exit(1);
}
# endif
} while (0);
}
#else
# include <openssl/bio.h>
# include <openssl/dso.h>
# include <openssl/err.h>
int main(int argc, char *argv[])
{
DSO *dso;
DSO_FUNC_TYPE func;
BIO *bio_err;
if (argc < 2) {
fprintf(stderr, "usage: %s libcrypto.dso\n", argv[0]);
return 1;
}
if ((bio_err = BIO_new(BIO_s_file())) == NULL) {
fprintf(stderr, "unable to allocate BIO\n");
return 1;
}
BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT);
ERR_load_crypto_strings();
dso = DSO_load(NULL, argv[1], NULL, DSO_FLAG_NO_NAME_TRANSLATION);
if (dso == NULL) {
ERR_print_errors(bio_err);
return 1;
}
/*
* This is not normally reached, because FINGERPRINT_premain should have
* executed and terminated application already upon DSO_load...
*/
func = DSO_bind_func(dso, "FINGERPRINT_premain");
if (func == NULL) {
ERR_print_errors(bio_err);
return 1;
}
(*func) ();
return 0;
}
#endif