]> CyberLeo.Net >> Repos - FreeBSD/releng/9.3.git/blob - crypto/openssl/fips/fips_premain.c
Fix multiple OpenSSL vulnerabilities.
[FreeBSD/releng/9.3.git] / crypto / openssl / fips / fips_premain.c
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   /*
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.
24    */
25 # elif defined(_MSC_VER)
26 #  ifdef _WINDLL
27 __declspec(dllexport)           /* this is essentially cosmetics... */
28 #  endif
29 void FINGERPRINT_premain(void);
30 static int premain_wrapper(void)
31 {
32     FINGERPRINT_premain();
33     return 0;
34 }
35
36 #  ifdef _WIN64
37 #   pragma section(".CRT$XCU",read)
38 __declspec(allocate(".CRT$XCU"))
39 #  else
40 #   pragma data_seg(".CRT$XCU")
41 #  endif
42 static int (*p) (void) = premain_wrapper;
43   /*
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.
47    */
48 #  pragma data_seg()
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);
55 #  pragma __nostandard
56 globaldef {
57 "LIB$INITIALIZ"} readonly _align(LONGWORD)
58 int spare[8] = { 0 };
59
60 globaldef {
61 "LIB$INITIALIZE"} readonly _align(LONGWORD)
62
63 void (*x_FINGERPRINT_premain) (void) = FINGERPRINT_premain;
64   /* Refer to LIB$INITIALIZE to ensure it exists in the image. */
65 int lib$initialize();
66 globaldef int (*lib_init_ref) () = lib$initialize;
67 #  pragma __standard
68 # elif 0
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 ...
74 # endif
75 # ifndef HMAC_SHA1_SIG
76 #  define HMAC_SHA1_SIG "?have to make sure this string is unique"
77 # endif
78 static const unsigned char FINGERPRINT_ascii_value[40] = HMAC_SHA1_SIG;
79
80 # define atox(c) ((c)>='a'?((c)-'a'+10):((c)>='A'?(c)-'A'+10:(c)-'0'))
81
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);
86
87 /*
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.
91  */
92 void FINGERPRINT_premain(void)
93 {
94     unsigned char sig[sizeof(FIPS_signature)];
95     const unsigned char *volatile p = FINGERPRINT_ascii_value;
96     unsigned int len = sizeof(sig), i;
97
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");
102             _exit(1);
103         }
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()),
107                 FIPS_text_end());
108         fprintf(stderr, ".rodata:%p+%d=%p\n", FIPS_rodata_start,
109                 (int)((size_t)FIPS_rodata_end - (size_t)FIPS_rodata_start),
110                 FIPS_rodata_end);
111 # endif
112
113         len = FIPS_incore_fingerprint(sig, sizeof(sig));
114
115         if (len != sizeof(sig)) {
116             fprintf(stderr, "fingerprint length mismatch: %u\n", len);
117             _exit(1);
118         }
119
120         for (i = 0; i < len; i++)
121             printf("%02x", sig[i]);
122         printf("\n");
123         fflush(stdout);
124         _exit(0);
125     } else if (FIPS_signature[0] == '\0')
126         do {
127             for (i = 0; i < sizeof(FIPS_signature); i++, p += 2)
128                 FIPS_signature[i] = (atox(p[0]) << 4) | atox(p[1]);
129
130 # if defined(DEBUG_FINGERPRINT_PREMAIN)
131             if (getenv("OPENSSL_FIPS") == NULL)
132                 break;
133
134             len = FIPS_incore_fingerprint(sig, sizeof(sig));
135
136             if (memcmp(FIPS_signature, sig, sizeof(FIPS_signature))) {
137                 fprintf(stderr,
138                         "FINGERPRINT_premain: FIPS_signature mismatch\n");
139                 _exit(1);
140             }
141 # endif
142         } while (0);
143 }
144
145 #else
146
147 # include <openssl/bio.h>
148 # include <openssl/dso.h>
149 # include <openssl/err.h>
150
151 int main(int argc, char *argv[])
152 {
153     DSO *dso;
154     DSO_FUNC_TYPE func;
155     BIO *bio_err;
156
157     if (argc < 2) {
158         fprintf(stderr, "usage: %s libcrypto.dso\n", argv[0]);
159         return 1;
160     }
161
162     if ((bio_err = BIO_new(BIO_s_file())) == NULL) {
163         fprintf(stderr, "unable to allocate BIO\n");
164         return 1;
165     }
166     BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT);
167     ERR_load_crypto_strings();
168
169     dso = DSO_load(NULL, argv[1], NULL, DSO_FLAG_NO_NAME_TRANSLATION);
170     if (dso == NULL) {
171         ERR_print_errors(bio_err);
172         return 1;
173     }
174
175     /*
176      * This is not normally reached, because FINGERPRINT_premain should have
177      * executed and terminated application already upon DSO_load...
178      */
179     func = DSO_bind_func(dso, "FINGERPRINT_premain");
180     if (func == NULL) {
181         ERR_print_errors(bio_err);
182         return 1;
183     }
184
185     (*func) ();
186
187     return 0;
188 }
189
190 #endif