1 /* ====================================================================
2 * Copyright (c) 2005 The OpenSSL Project. Rights for redistribution
3 * and usage in source and binary forms are granted according to the
10 #if defined(__unix) || defined(__unix__)
14 #ifndef FINGERPRINT_PREMAIN_DSO_LOAD
16 # if defined(__GNUC__) && __GNUC__>=2
17 void FINGERPRINT_premain(void) __attribute__ ((constructor));
19 * Most commonly this results in pointer to premain to be dropped to .ctors
20 * segment, which is traversed by GCC crtbegin.o upon program startup.
21 * Except on a.out OpenBSD where it results in _GLOBAL_$I$premain()
22 * {premain();} being auto-generated by compiler... But one way or another
23 * this is believed to cover *all* GCC targets.
25 # elif defined(_MSC_VER)
27 __declspec(dllexport) /* this is essentially cosmetics... */
29 void FINGERPRINT_premain(void);
30 static int premain_wrapper(void)
32 FINGERPRINT_premain();
37 # pragma section(".CRT$XCU",read)
38 __declspec(allocate(".CRT$XCU"))
40 # pragma data_seg(".CRT$XCU")
42 static int (*p) (void) = premain_wrapper;
44 * This results in pointer to premain to appear in .CRT segment, which is
45 * traversed by Visual C run-time initialization code. This applies to both
46 * Win32 and [all flavors of] Win64.
49 # elif defined(__SUNPRO_C)
50 void FINGERPRINT_premain(void);
51 # pragma init(FINGERPRINT_premain)
52 /* This results in a call to premain to appear in .init segment. */
53 # elif defined(__DECC) && (defined(__VMS) || defined(VMS))
54 void FINGERPRINT_premain(void);
57 "LIB$INITIALIZ"} readonly _align(LONGWORD)
61 "LIB$INITIALIZE"} readonly _align(LONGWORD)
63 void (*x_FINGERPRINT_premain) (void) = FINGERPRINT_premain;
64 /* Refer to LIB$INITIALIZE to ensure it exists in the image. */
66 globaldef int (*lib_init_ref) () = lib$initialize;
69 The rest has to be taken care of through command line:-Wl, -init,
70 FINGERPRINT_premain on OSF1 and IRIX - Wl, +init,
71 FINGERPRINT_premain on HP - UX - Wl,
72 -binitfini:FINGERPRINT_premain on AIX On ELF platforms this results in a
73 call to premain to appear in.init segment ...
75 # ifndef HMAC_SHA1_SIG
76 # define HMAC_SHA1_SIG "?have to make sure this string is unique"
78 static const unsigned char FINGERPRINT_ascii_value[40] = HMAC_SHA1_SIG;
80 # define atox(c) ((c)>='a'?((c)-'a'+10):((c)>='A'?(c)-'A'+10:(c)-'0'))
82 extern const void *FIPS_text_start(), *FIPS_text_end();
83 extern const unsigned char FIPS_rodata_start[], FIPS_rodata_end[];
84 extern unsigned char FIPS_signature[20];
85 extern unsigned int FIPS_incore_fingerprint(unsigned char *, unsigned int);
88 * As name suggests this code is executed prior main(). We use this
89 * opportunity to fingerprint sequestered code in virtual address
90 * space of target application.
92 void FINGERPRINT_premain(void)
94 unsigned char sig[sizeof(FIPS_signature)];
95 const unsigned char *volatile p = FINGERPRINT_ascii_value;
96 unsigned int len = sizeof(sig), i;
98 /* "volatilization" is done to disengage unwanted optimization... */
99 if (*((volatile unsigned char *)p) == '?') {
100 if (FIPS_text_start() == NULL) {
101 fprintf(stderr, "FIPS_text_start() returns NULL\n");
104 # if defined(DEBUG_FINGERPRINT_PREMAIN)
105 fprintf(stderr, ".text:%p+%d=%p\n", FIPS_text_start(),
106 (int)((size_t)FIPS_text_end() - (size_t)FIPS_text_start()),
108 fprintf(stderr, ".rodata:%p+%d=%p\n", FIPS_rodata_start,
109 (int)((size_t)FIPS_rodata_end - (size_t)FIPS_rodata_start),
113 len = FIPS_incore_fingerprint(sig, sizeof(sig));
115 if (len != sizeof(sig)) {
116 fprintf(stderr, "fingerprint length mismatch: %u\n", len);
120 for (i = 0; i < len; i++)
121 printf("%02x", sig[i]);
125 } else if (FIPS_signature[0] == '\0')
127 for (i = 0; i < sizeof(FIPS_signature); i++, p += 2)
128 FIPS_signature[i] = (atox(p[0]) << 4) | atox(p[1]);
130 # if defined(DEBUG_FINGERPRINT_PREMAIN)
131 if (getenv("OPENSSL_FIPS") == NULL)
134 len = FIPS_incore_fingerprint(sig, sizeof(sig));
136 if (memcmp(FIPS_signature, sig, sizeof(FIPS_signature))) {
138 "FINGERPRINT_premain: FIPS_signature mismatch\n");
147 # include <openssl/bio.h>
148 # include <openssl/dso.h>
149 # include <openssl/err.h>
151 int main(int argc, char *argv[])
158 fprintf(stderr, "usage: %s libcrypto.dso\n", argv[0]);
162 if ((bio_err = BIO_new(BIO_s_file())) == NULL) {
163 fprintf(stderr, "unable to allocate BIO\n");
166 BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT);
167 ERR_load_crypto_strings();
169 dso = DSO_load(NULL, argv[1], NULL, DSO_FLAG_NO_NAME_TRANSLATION);
171 ERR_print_errors(bio_err);
176 * This is not normally reached, because FINGERPRINT_premain should have
177 * executed and terminated application already upon DSO_load...
179 func = DSO_bind_func(dso, "FINGERPRINT_premain");
181 ERR_print_errors(bio_err);