/* ==================================================================== * Copyright (c) 2005 The OpenSSL Project. Rights for redistribution * and usage in source and binary forms are granted according to the * OpenSSL license. */ #include #include #include #if defined(__unix) || defined(__unix__) #include #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 #include #include 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