OLD | NEW |
| (Empty) |
1 /* ==================================================================== | |
2 * Copyright (c) 2005 The OpenSSL Project. Rights for redistribution | |
3 * and usage in source and binary forms are granted according to the | |
4 * OpenSSL license. | |
5 */ | |
6 | |
7 #include <stdio.h> | |
8 #include <stdlib.h> | |
9 #include <string.h> | |
10 #if defined(__unix) || defined(__unix__) | |
11 #include <unistd.h> | |
12 #endif | |
13 | |
14 #ifndef FINGERPRINT_PREMAIN_DSO_LOAD | |
15 | |
16 #if defined(__GNUC__) && __GNUC__>=2 | |
17 void FINGERPRINT_premain(void) __attribute__((constructor)); | |
18 /* Most commonly this results in pointer to premain to be dropped | |
19 * to .ctors segment, which is traversed by GCC crtbegin.o upon | |
20 * program startup. Except on a.out OpenBSD where it results in | |
21 * _GLOBAL_$I$premain() {premain();} being auto-generated by | |
22 * compiler... But one way or another this is believed to cover | |
23 * *all* GCC targets. */ | |
24 #elif defined(_MSC_VER) | |
25 # ifdef _WINDLL | |
26 __declspec(dllexport) /* this is essentially cosmetics... */ | |
27 # endif | |
28 void FINGERPRINT_premain(void); | |
29 static int premain_wrapper(void) { FINGERPRINT_premain(); return 0; } | |
30 # ifdef _WIN64 | |
31 # pragma section(".CRT$XCU",read) | |
32 __declspec(allocate(".CRT$XCU")) | |
33 # else | |
34 # pragma data_seg(".CRT$XCU") | |
35 # endif | |
36 static int (*p)(void) = premain_wrapper; | |
37 /* This results in pointer to premain to appear in .CRT segment, | |
38 * which is traversed by Visual C run-time initialization code. | |
39 * This applies to both Win32 and [all flavors of] Win64. */ | |
40 # pragma data_seg() | |
41 #elif defined(__SUNPRO_C) | |
42 void FINGERPRINT_premain(void); | |
43 # pragma init(FINGERPRINT_premain) | |
44 /* This results in a call to premain to appear in .init segment. */ | |
45 #elif defined(__DECC) && (defined(__VMS) || defined(VMS)) | |
46 void FINGERPRINT_premain(void); | |
47 # pragma __nostandard | |
48 globaldef { "LIB$INITIALIZ" } readonly _align (LONGWORD) | |
49 int spare[8] = {0}; | |
50 globaldef { "LIB$INITIALIZE" } readonly _align (LONGWORD) | |
51 void (*x_FINGERPRINT_premain)(void) = FINGERPRINT_premain; | |
52 /* Refer to LIB$INITIALIZE to ensure it exists in the image. */ | |
53 int lib$initialize(); | |
54 globaldef int (*lib_init_ref)() = lib$initialize; | |
55 # pragma __standard | |
56 #elif 0 | |
57 The rest has to be taken care of through command line: | |
58 | |
59 -Wl,-init,FINGERPRINT_premain on OSF1 and IRIX | |
60 -Wl,+init,FINGERPRINT_premain on HP-UX | |
61 -Wl,-binitfini:FINGERPRINT_premain on AIX | |
62 | |
63 On ELF platforms this results in a call to premain to appear in | |
64 .init segment... | |
65 #endif | |
66 | |
67 #ifndef HMAC_SHA1_SIG | |
68 #define HMAC_SHA1_SIG "?have to make sure this string is unique" | |
69 #endif | |
70 | |
71 static const unsigned char FINGERPRINT_ascii_value[40] = HMAC_SHA1_SIG; | |
72 | |
73 #define atox(c) ((c)>='a'?((c)-'a'+10):((c)>='A'?(c)-'A'+10:(c)-'0')) | |
74 | |
75 extern const void *FIPS_text_start(), *FIPS_text_end(); | |
76 extern const unsigned char FIPS_rodata_start[], FIPS_rodata_end[]; | |
77 extern unsigned char FIPS_signature[20]; | |
78 extern unsigned int FIPS_incore_fingerprint(unsigned char *,unsigned int)
; | |
79 | |
80 /* | |
81 * As name suggests this code is executed prior main(). We use this | |
82 * opportunity to fingerprint sequestered code in virtual address | |
83 * space of target application. | |
84 */ | |
85 void FINGERPRINT_premain(void) | |
86 { unsigned char sig[sizeof(FIPS_signature)]; | |
87 const unsigned char * volatile p=FINGERPRINT_ascii_value; | |
88 unsigned int len=sizeof(sig),i; | |
89 | |
90 /* "volatilization" is done to disengage unwanted optimization... */ | |
91 if (*((volatile unsigned char *)p)=='?') | |
92 { if (FIPS_text_start()==NULL) | |
93 { fprintf(stderr,"FIPS_text_start() returns NULL\n"); | |
94 _exit(1); | |
95 } | |
96 #if defined(DEBUG_FINGERPRINT_PREMAIN) | |
97 fprintf(stderr,".text:%p+%d=%p\n",FIPS_text_start(), | |
98 (int)((size_t)FIPS_text_end()-(size_t)FIPS_text_start()), | |
99 FIPS_text_end()); | |
100 fprintf(stderr,".rodata:%p+%d=%p\n",FIPS_rodata_start, | |
101 (int)((size_t)FIPS_rodata_end-(size_t)FIPS_rodata_start), | |
102 FIPS_rodata_end); | |
103 #endif | |
104 | |
105 len=FIPS_incore_fingerprint(sig,sizeof(sig)); | |
106 | |
107 if (len!=sizeof(sig)) | |
108 { fprintf(stderr,"fingerprint length mismatch: %u\n",len); | |
109 _exit(1); | |
110 } | |
111 | |
112 for (i=0;i<len;i++) printf("%02x",sig[i]); | |
113 printf("\n"); | |
114 fflush(stdout); | |
115 _exit(0); | |
116 } | |
117 else if (FIPS_signature[0]=='\0') do | |
118 { for (i=0;i<sizeof(FIPS_signature);i++,p+=2) | |
119 FIPS_signature[i] = (atox(p[0])<<4)|atox(p[1]); | |
120 | |
121 #if defined(DEBUG_FINGERPRINT_PREMAIN) | |
122 if (getenv("OPENSSL_FIPS")==NULL) break; | |
123 | |
124 len=FIPS_incore_fingerprint(sig,sizeof(sig)); | |
125 | |
126 if (memcmp(FIPS_signature,sig,sizeof(FIPS_signature))) | |
127 { fprintf(stderr,"FINGERPRINT_premain: FIPS_signature mismatch\n"); | |
128 _exit(1); | |
129 } | |
130 #endif | |
131 } while(0); | |
132 } | |
133 | |
134 #else | |
135 | |
136 #include <openssl/bio.h> | |
137 #include <openssl/dso.h> | |
138 #include <openssl/err.h> | |
139 | |
140 int main(int argc,char *argv[]) | |
141 { DSO *dso; | |
142 DSO_FUNC_TYPE func; | |
143 BIO *bio_err; | |
144 | |
145 if (argc < 2) | |
146 { fprintf (stderr,"usage: %s libcrypto.dso\n",argv[0]); | |
147 return 1; | |
148 } | |
149 | |
150 if ((bio_err=BIO_new(BIO_s_file())) == NULL) | |
151 { fprintf (stderr,"unable to allocate BIO\n"); | |
152 return 1; | |
153 } | |
154 BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT); | |
155 ERR_load_crypto_strings(); | |
156 | |
157 dso = DSO_load(NULL,argv[1],NULL,DSO_FLAG_NO_NAME_TRANSLATION); | |
158 if (dso == NULL) | |
159 { ERR_print_errors(bio_err); | |
160 return 1; | |
161 } | |
162 | |
163 /* This is not normally reached, because FINGERPRINT_premain should | |
164 * have executed and terminated application already upon DSO_load... */ | |
165 func = DSO_bind_func(dso,"FINGERPRINT_premain"); | |
166 if (func == NULL) | |
167 { ERR_print_errors(bio_err); | |
168 return 1; | |
169 } | |
170 | |
171 (*func)(); | |
172 | |
173 return 0; | |
174 } | |
175 | |
176 #endif | |
OLD | NEW |