1193645Ssimon/* ==================================================================== 2193645Ssimon * Copyright (c) 2005 The OpenSSL Project. Rights for redistribution 3193645Ssimon * and usage in source and binary forms are granted according to the 4193645Ssimon * OpenSSL license. 5193645Ssimon */ 6193645Ssimon 7193645Ssimon#include <stdio.h> 8193645Ssimon#include <stdlib.h> 9193645Ssimon#include <string.h> 10193645Ssimon#if defined(__unix) || defined(__unix__) 11296465Sdelphij# include <unistd.h> 12193645Ssimon#endif 13193645Ssimon 14193645Ssimon#ifndef FINGERPRINT_PREMAIN_DSO_LOAD 15193645Ssimon 16296465Sdelphij# if defined(__GNUC__) && __GNUC__>=2 17296465Sdelphijvoid FINGERPRINT_premain(void) __attribute__ ((constructor)); 18296465Sdelphij /* 19296465Sdelphij * Most commonly this results in pointer to premain to be dropped to .ctors 20296465Sdelphij * segment, which is traversed by GCC crtbegin.o upon program startup. 21296465Sdelphij * Except on a.out OpenBSD where it results in _GLOBAL_$I$premain() 22296465Sdelphij * {premain();} being auto-generated by compiler... But one way or another 23296465Sdelphij * this is believed to cover *all* GCC targets. 24296465Sdelphij */ 25296465Sdelphij# elif defined(_MSC_VER) 26296465Sdelphij# ifdef _WINDLL 27296465Sdelphij__declspec(dllexport) /* this is essentially cosmetics... */ 28296465Sdelphij# endif 29296465Sdelphijvoid FINGERPRINT_premain(void); 30296465Sdelphijstatic int premain_wrapper(void) 31296465Sdelphij{ 32296465Sdelphij FINGERPRINT_premain(); 33296465Sdelphij return 0; 34296465Sdelphij} 35296465Sdelphij 36296465Sdelphij# ifdef _WIN64 37296465Sdelphij# pragma section(".CRT$XCU",read) 38296465Sdelphij__declspec(allocate(".CRT$XCU")) 39296465Sdelphij# else 40296465Sdelphij# pragma data_seg(".CRT$XCU") 41296465Sdelphij# endif 42296465Sdelphijstatic int (*p) (void) = premain_wrapper; 43296465Sdelphij /* 44296465Sdelphij * This results in pointer to premain to appear in .CRT segment, which is 45296465Sdelphij * traversed by Visual C run-time initialization code. This applies to both 46296465Sdelphij * Win32 and [all flavors of] Win64. 47296465Sdelphij */ 48296465Sdelphij# pragma data_seg() 49296465Sdelphij# elif defined(__SUNPRO_C) 50296465Sdelphijvoid FINGERPRINT_premain(void); 51296465Sdelphij# pragma init(FINGERPRINT_premain) 52193645Ssimon /* This results in a call to premain to appear in .init segment. */ 53296465Sdelphij# elif defined(__DECC) && (defined(__VMS) || defined(VMS)) 54296465Sdelphijvoid FINGERPRINT_premain(void); 55296465Sdelphij# pragma __nostandard 56296465Sdelphijglobaldef { 57296465Sdelphij"LIB$INITIALIZ"} readonly _align(LONGWORD) 58296465Sdelphijint spare[8] = { 0 }; 59193645Ssimon 60296465Sdelphijglobaldef { 61296465Sdelphij"LIB$INITIALIZE"} readonly _align(LONGWORD) 62193645Ssimon 63296465Sdelphijvoid (*x_FINGERPRINT_premain) (void) = FINGERPRINT_premain; 64296465Sdelphij /* Refer to LIB$INITIALIZE to ensure it exists in the image. */ 65296465Sdelphijint lib$initialize(); 66296465Sdelphijglobaldef int (*lib_init_ref) () = lib$initialize; 67296465Sdelphij# pragma __standard 68296465Sdelphij# elif 0 69296465SdelphijThe rest has to be taken care of through command line:-Wl, -init, 70296465Sdelphij FINGERPRINT_premain on OSF1 and IRIX - Wl, +init, 71296465Sdelphij FINGERPRINT_premain on HP - UX - Wl, 72296465Sdelphij -binitfini:FINGERPRINT_premain on AIX On ELF platforms this results in a 73296465Sdelphij call to premain to appear in.init segment ... 74296465Sdelphij# endif 75296465Sdelphij# ifndef HMAC_SHA1_SIG 76296465Sdelphij# define HMAC_SHA1_SIG "?have to make sure this string is unique" 77296465Sdelphij# endif 78193645Ssimonstatic const unsigned char FINGERPRINT_ascii_value[40] = HMAC_SHA1_SIG; 79193645Ssimon 80296465Sdelphij# define atox(c) ((c)>='a'?((c)-'a'+10):((c)>='A'?(c)-'A'+10:(c)-'0')) 81193645Ssimon 82296465Sdelphijextern const void *FIPS_text_start(), *FIPS_text_end(); 83193645Ssimonextern const unsigned char FIPS_rodata_start[], FIPS_rodata_end[]; 84296465Sdelphijextern unsigned char FIPS_signature[20]; 85296465Sdelphijextern unsigned int FIPS_incore_fingerprint(unsigned char *, unsigned int); 86193645Ssimon 87193645Ssimon/* 88193645Ssimon * As name suggests this code is executed prior main(). We use this 89193645Ssimon * opportunity to fingerprint sequestered code in virtual address 90193645Ssimon * space of target application. 91193645Ssimon */ 92193645Ssimonvoid FINGERPRINT_premain(void) 93296465Sdelphij{ 94296465Sdelphij unsigned char sig[sizeof(FIPS_signature)]; 95296465Sdelphij const unsigned char *volatile p = FINGERPRINT_ascii_value; 96296465Sdelphij unsigned int len = sizeof(sig), i; 97193645Ssimon 98193645Ssimon /* "volatilization" is done to disengage unwanted optimization... */ 99296465Sdelphij if (*((volatile unsigned char *)p) == '?') { 100296465Sdelphij if (FIPS_text_start() == NULL) { 101296465Sdelphij fprintf(stderr, "FIPS_text_start() returns NULL\n"); 102296465Sdelphij _exit(1); 103296465Sdelphij } 104296465Sdelphij# if defined(DEBUG_FINGERPRINT_PREMAIN) 105296465Sdelphij fprintf(stderr, ".text:%p+%d=%p\n", FIPS_text_start(), 106296465Sdelphij (int)((size_t)FIPS_text_end() - (size_t)FIPS_text_start()), 107296465Sdelphij FIPS_text_end()); 108296465Sdelphij fprintf(stderr, ".rodata:%p+%d=%p\n", FIPS_rodata_start, 109296465Sdelphij (int)((size_t)FIPS_rodata_end - (size_t)FIPS_rodata_start), 110296465Sdelphij FIPS_rodata_end); 111296465Sdelphij# endif 112193645Ssimon 113296465Sdelphij len = FIPS_incore_fingerprint(sig, sizeof(sig)); 114193645Ssimon 115296465Sdelphij if (len != sizeof(sig)) { 116296465Sdelphij fprintf(stderr, "fingerprint length mismatch: %u\n", len); 117296465Sdelphij _exit(1); 118296465Sdelphij } 119193645Ssimon 120296465Sdelphij for (i = 0; i < len; i++) 121296465Sdelphij printf("%02x", sig[i]); 122296465Sdelphij printf("\n"); 123296465Sdelphij fflush(stdout); 124296465Sdelphij _exit(0); 125296465Sdelphij } else if (FIPS_signature[0] == '\0') 126296465Sdelphij do { 127296465Sdelphij for (i = 0; i < sizeof(FIPS_signature); i++, p += 2) 128296465Sdelphij FIPS_signature[i] = (atox(p[0]) << 4) | atox(p[1]); 129193645Ssimon 130296465Sdelphij# if defined(DEBUG_FINGERPRINT_PREMAIN) 131296465Sdelphij if (getenv("OPENSSL_FIPS") == NULL) 132296465Sdelphij break; 133193645Ssimon 134296465Sdelphij len = FIPS_incore_fingerprint(sig, sizeof(sig)); 135193645Ssimon 136296465Sdelphij if (memcmp(FIPS_signature, sig, sizeof(FIPS_signature))) { 137296465Sdelphij fprintf(stderr, 138296465Sdelphij "FINGERPRINT_premain: FIPS_signature mismatch\n"); 139296465Sdelphij _exit(1); 140296465Sdelphij } 141296465Sdelphij# endif 142296465Sdelphij } while (0); 143193645Ssimon} 144193645Ssimon 145193645Ssimon#else 146193645Ssimon 147296465Sdelphij# include <openssl/bio.h> 148296465Sdelphij# include <openssl/dso.h> 149296465Sdelphij# include <openssl/err.h> 150193645Ssimon 151296465Sdelphijint main(int argc, char *argv[]) 152296465Sdelphij{ 153296465Sdelphij DSO *dso; 154296465Sdelphij DSO_FUNC_TYPE func; 155296465Sdelphij BIO *bio_err; 156193645Ssimon 157296465Sdelphij if (argc < 2) { 158296465Sdelphij fprintf(stderr, "usage: %s libcrypto.dso\n", argv[0]); 159296465Sdelphij return 1; 160193645Ssimon } 161193645Ssimon 162296465Sdelphij if ((bio_err = BIO_new(BIO_s_file())) == NULL) { 163296465Sdelphij fprintf(stderr, "unable to allocate BIO\n"); 164296465Sdelphij return 1; 165193645Ssimon } 166296465Sdelphij BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); 167193645Ssimon ERR_load_crypto_strings(); 168193645Ssimon 169296465Sdelphij dso = DSO_load(NULL, argv[1], NULL, DSO_FLAG_NO_NAME_TRANSLATION); 170296465Sdelphij if (dso == NULL) { 171296465Sdelphij ERR_print_errors(bio_err); 172296465Sdelphij return 1; 173193645Ssimon } 174193645Ssimon 175296465Sdelphij /* 176296465Sdelphij * This is not normally reached, because FINGERPRINT_premain should have 177296465Sdelphij * executed and terminated application already upon DSO_load... 178296465Sdelphij */ 179296465Sdelphij func = DSO_bind_func(dso, "FINGERPRINT_premain"); 180296465Sdelphij if (func == NULL) { 181296465Sdelphij ERR_print_errors(bio_err); 182296465Sdelphij return 1; 183193645Ssimon } 184193645Ssimon 185296465Sdelphij (*func) (); 186193645Ssimon 187296465Sdelphij return 0; 188193645Ssimon} 189193645Ssimon 190193645Ssimon#endif 191