]> www.wagner.pp.ru Git - sites/home_page.git/blob - articles/openssl-mingw.html
Added article about openssl
[sites/home_page.git] / articles / openssl-mingw.html
1 <HTML><HEAD>
2 <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=koi8-r">
3 <TITLE>Building OpenSSL for Windows with Mingw32</TITLE>
4 <META NAME="DESCRIPTION" CONTENT="Summary of experience of building both
5 stable and development versions of OpenSSL for Windows"> </HEAD><BODY>
6 <H1>Building OpenSSL for Windows with Mingw32</H1>
7 <p>
8 If you want to get OpenSSL libraries (either .dll or static libraries),
9 usable by native Windows compilers, you can use entirely free GNU
10 compiler, downloadable from internet.
11 </p>
12 <p>
13 OpenSSL is written on plain old C, which means that as long as compilers
14 use common object file format, you can easily link object files and
15 static libraries, produced by one compiler, with another.
16 </p>
17 <p>
18 GNU MinGW32 compiler uses COFF object format, same as Microsoft Visual
19 studio. It just has different naming convention. Rename libssl.a,
20 produced with MinGW to ssl.lib, and you can use it in MSVC.
21 </p>
22 <H2>Build environments</H2>
23 <p>
24 OpenSSL distribution includes file mingw.bat to build dll version with
25 MinGW. Forget about it. It is outdated, unsupported and soon to be
26 removed.
27 </p>
28 <p>Better to use unix style configure-make-make install approach. For
29 this approach you'll need unix-like shell, perl and some utilities.
30 </p>
31 <p>There are three possible choices for the build environment:
32 </p>
33 <ol>
34 <li><p>Use minimal needed set of utilites. You'll need:</p>
35 <ul>
36 <li>mingw32 compiler from <a href="http://www.mingw.org">mingw.org</a>
37 <li>Minimal system (MSYS) from same site
38 <li>Win32 version of Perl from <a
39 href="http://www.activestate.com">ActiveState</a>
40 </ul><p>
41 This would take less than 100Mb on your disk and let your build lots of
42 interesting things other than OpenSSL.</p>
43 </li>
44 <li><p>Use Cygwin toolchain. Yes, you can build native win32 programs,
45 which don't depend on cygwin.dll with cygwin compiler.
46 You'll need cygwin perl, make, coreutils and all some packages from
47 cygwin  which have mingw in its name (from development section) You
48 don-t need C++ compiler, but, probably would like to use mingw zlib. 
49 </p><p>I
50 recommend to use this way only if you already have cygwin and
51 accustomized to use it.
52 </p>
53 </li>
54 <li><p>Compile all thing on nearby Linux/Unix machine using cross-compiler.
55 If you use Debian GNU/Linux, you need just to install packages mingw32,
56 mingw32-runtime and mingw32-binutils. You typically have make, perl and
57 coreutils on Linux system. On other Unixes you probably will need to
58 build mingw32 cross-compiler from gcc sources.
59 </p>
60 <p>
61 I wouldn't cover building and  installing cross-compiler here.
62 </p>
63 </li>
64 It is also possible to combine cygwin compiler and shell with
65 ActiveState perl, but I wouldn't recommend to do so.
66 <h2>Building static version</h2>
67 <p>
68 Download and unpack sources of openssl. It comes in the tar.gz archive.
69 Any build environment mentioned above includes <tt>tar</tt> program
70 which is used to unpack archives.
71 </p>
72 <p>
73 Open command window (or terminal window on Unix), make sure that
74 cygwin (or all of msys, mingw and ActiveState perl) directories are in
75 your  PATH (on Unix cross compiler automatically installed into PATH and
76 perl is already there), 
77 change into top-level  directory of unpacked source.
78 <p>
79 Open Configure script with text editor, find line
80 </p>
81 <pre>
82 $IsMK1MF=1 if ($target eq "mingw" &amp;&amp; $^O ne "cygwin" &amp;&amp; !is_msys());
83 </pre>
84 <p>
85 and comment it out (or delete altogether). If you are using Cygwin perl,
86 you can omit this step. Condition would be false anyway. But function
87 is_msys() might not work properly, and of course it wouldn't work when
88 cross-compiling for Unix.
89 </p>
90 <tt>Configure</tt> script. On *nix you can just start 
91 </p>
92 <pre>
93 ./Configure mingw
94 </pre>
95 <p>
96 With cygwin or ActiveState perl you'll have to feed this script to perl
97 </p>
98 <pre>
99 perl Configure mingw
100 </pre>
101 <p>
102 Soon you get message "Configured for mingw".
103 </p>
104 <p>
105 Now, you are ready to run make. In the cygwin or msys environment just
106 type make. On unix, if you type just  make, native compiler would be
107 invoked. You have to specify crosscompiler in the CC makefile variable:
108 </p>
109 <pre>
110  make CC=i586-mingw32msvc-gcc RANLIB=i585-mingw32msvc-ranlib
111 </pre>
112 <p>
113 With current stable (0.9.8d) verything should go fine until rehash
114 target would be invoked. With development branch (0.9.9) you can go into
115 some trouble - it is development version, it supposed to be buggy. See
116 <a href="#troubleshooting">Troubleshooting</a> section below for some
117 hints.
118 </p>
119 <p>
120 When make tells &quot;Doing certs&quot; it would probably complain about
121 'openssl' program not found in msys and about inability to run program
122 on Unix. You can safely ignore that for a while.
123 </p>
124 <p>
125 After build is finished you should have <tt>openssl.exe</tt> file in the
126 apps directory, and two library files <tt>libssl.a</tt> and
127 <tt>libcrypto.a</tt> in the toplevel directory.
128 </p>
129 <p>
130 If you are on native Win32 system, you may run test suite typing
131 </p>
132 <pre>
133 make test
134 </pre>
135 <p>
136 If you are doing build on Unix and want to run test, you have to find
137 windows system to do so. This system should have MSYS and perl
138 installed.
139 </p>
140 <h2>Doing shared build</h2>
141 <p>
142 You are probably not interesting in static build. Probably you want to
143 have OpenSSL dlls which can be used with some native Win32 application
144 such as <a href="http://www.miranda-im.org">Miranda IM</a>.
145 </p>
146 <p>
147 To achieve this, you have to add <b>shared</b> parameter to
148 <tt>Configure</tt>.
149 <pre>
150  perl Configure mingw shared
151 </pre>
152 <p>
153 But there bad thing happens:
154 </p>
155 <p>
156 everything is compiled, cryptoeay32-0.9.8.dll is built, but when it
157 comes to building something that depends on this dll (such as
158 ssleay32-0.9.8.dll), you get lot of complaints about unresolved symbols.
159 </p>
160 <p>
161 If you examine dll with dumpbin tool from MSVC you'll see that it
162 doesn't export anything.
163 </p>
164 <p>
165 Fix is quite simple:
166 </p>
167 <p>
168 Open Configure script with text editor, find line with mingw
169 configuration option:
170
171 <pre>
172 &quot;mingw&quot;,&quot;gcc:-mno-cygwin -DL_ENDIAN....
173 </pre>
174
175 Find  fragment which defines options for dll building (it lloks like
176 <pre>
177 :-mno-cygwin -shared:
178 </pre>
179 and add there <tt>-Wl,--export-all</tt>, so section would look like:
180 <pre>
181 :-mno-cygwin -Wl,--export-all -shared:
182 </pre>
183
184 Then rerun <tt>Configure mingw shared</tt> and make.
185 Anything should run fine except certificate rehash.
186 <H2>Defining openssl directory</H2> 
187 <p>
188 There is some things, which OpenSSL searches in the compiled-in
189 directory - configuration files and certificates. Path for openssl
190 directory can be seen by issuing a command:
191 </p>
192 <pre>
193 openssl version -d
194 </pre>
195 <p>
196 Typically, it is unix-style path <tt>/usr/local/ssl</tt>. It is evident
197 that there is little use of such path on Windows system. But it is not
198 absolutely useless - if you have just one logical drive in your Windows
199 machine, you can create there  <tt>c:\usr\local\ssl</tt> directory
200 there, and OpenSSL would find its configuration file as long as current
201 working directory of your OpenSSL application is on the C: drive.
202 </p>
203 <p>
204 But it is better to define actual path during Configure stage. This is
205 done via Configure option <tt>--openssldir</tt>.
206 </p>
207 <pre>
208  perl Configure mingw shared --openssldir=c:/OpenSSL
209 </pre>
210 <p>
211 There is another option - <tt>--prefix</tt> which is taken into account
212 during make install, and used for search for dynamically loadable engine
213 modules. But if you have working configuration file, you can always
214 write <tt>dynamic_path</tt> there.
215 </p>
216 <p>
217 There is a method to override location of configuration file.
218 You can specify exact filename (not just directory name, but filename)
219 in the <TT>OPENSSL_CONF</TT> environment variable.
220 </p>
221 <h2>Installing runtime modules of OpenSSL</h2>
222 <p>
223 There is no need to use <tt>make install</tt> under Windows.
224 You just cope <tt>openssl.exe</tt> and two dlls (in case of shared
225 build) into some dir in the your PATH. On Unix shared libraries go into
226 <i>prefix</i>/<tt>lib</tt> directory, and executable files into
227 <i>prefix</i>/<tt>bin</tt> and only bin has to be added to PATH.
228 So does standard OpenSSL installation procedure. 
229 </p>
230 <p>
231 On Windows application search for DLLs using the same PATH as system
232 uses to find executable files, but prepends directory where program
233 itself resides. So if you throw executable and the dlls into same
234 directory, it is guaranteed, that application would find those dlls.
235 </p>
236 <h2>Compiling 3rd party applications with OpenSSL</h2>
237 <p>
238 Typically, one compiles OpenSSL in order to use it in some programs.
239 This can be windows-only programs, such as Miranda IM, or ports of Unix
240 software such as PostgreSQL.
241 </p>
242 <p>
243 In both cases you need to have include files and import libraries for
244 DLLs available for you compiler. (you may choose to use static
245 libraries, but DLLs are better - they allow to quickly upgrade OpenSSL
246 in case of security update without recompiling all the applications).
247 </p>
248 <p>After you have built OpenSSL, there is include directory with openssl
249 subdirectory. Copy this subdirectory with all its content into include
250 directory of your compiler.
251 </p>
252 <p>
253 Then, copy libssl.dll.a and libcrypto.dll.a to the library directory of
254 your compiler.  Now you can use -lssl.dll -lcrypto.dll command line
255 options for you Mingw32 compiler to link with OpenSSL libraries.
256 </p>
257 <p>
258 Typically, windows applications expect something other than these names.
259 For instance, PostgreSQL build system expects these libraries to be
260 named libeay32.a for libcrypto and libssleay32.a for libssl. 
261 You can just rename libraries appropriately, or copy them (they are
262 quite small because contains just references to DLL, not actual code).
263 </p>
264 <p>
265 If you want to use openssl with Microsoft Visual Studio, you can just
266 rename libcrypto.dll.a into libeay32.lib, and libssl.dll.a into
267 ssleay32.lib. Microsoft .lib files are really ar archives and are
268 compatible with mingw static libraries.
269 </p>
270 <h2><a name="trobuleshooting">Troubleshouting development version of
271 OpenSSL</h2>
272 <h3>Case 1. ws2tcpip incompatible with winsock</h3>
273 <p>
274 With OpenSSL cvs of Oct-20-2006 I've encountered problems that
275 compilation fails with message "ws2tcpip.h is not compatible with
276 winsock.h".
277 </p>
278 <p>
279 Problem is that Windows has two versions of its TCPIP code winsock.h and
280 winsock2.h. If you want to use newer version, you have to use
281 winsock2.h. If your include winsock2.h, and then winsock.h everything is
282 good - winsock.h sees if you have included winsock2 and does nothing. So
283 you can use IPV6 functions declared in ws2tcpip.h etc. 
284 </p>
285 <p>
286 But windows.h file which comes with Mingw32 runtime includes winsock.h
287 for some constants and types. So, if you haven't included winsock2.h
288 prior to first inclusion of windows.h, and than want to include
289 ws2tcpip.h,  compilation fails.
290 </p>
291 <p>
292 OpenSSL includes winsock2.h and ws2tcpip.h via local include file
293 e_os.h. But  windows.h is included not only via this file, but also via
294 rand.h. So, if some code file includes rand.h (directly, or indirectly,
295 via engine.h for example), prior to e_os.h, you are in trouble.
296 </p>
297 <p>
298 Solution is simple - find out where offending file is included, and
299 add <tt>#include "e_os.h"</tt> on the previous line. I've found
300 three such files - <tt>ssl/ssl_sess.c</tt>, <tt>apps/apps.c</tt> and
301 <tt>test/randtest.c</tt>.
302 </p>
303 <p>Hopefully OpenSSL core team would fix this problem soon.
304 </p>
305 <h3>Case 2. Duplicate extern</h3>
306 <p>
307 I've also found than compilation fails on the file
308 <tt>engines/ccgost/gost_eng.c</tt> with message &quot;Duplicate
309 extern&quot;. Solution is very simple. Just remove offending 
310 <tt>__declspec(dllexport)</tt> declartions exactly where compiler
311 reports error.
312 </p>
313 <p>
314 Since I'm author of ccgost code, I can tell you exact story how this
315 error crawl into OpenSSL.
316 </p>
317 <p>
318 There is macros IMPLEMENT_DINAMIC_CHECK_FUNCTION and
319 IMPLEMENT_DYNAMIC_BIND_FUNCTION intended for use by engine writers.
320 </p>
321 <p>
322 Before June 2006 these macros don't have any win32 specific things.
323 Probably people just didn't use engines on Win32. So, we have to add
324 export declarations in order to OpenSSL to be able to load our engine on
325 Win32. 
326 </p>
327 <p>
328 Then we forget about it for a while and haven't tested development
329 version on Win32. 
330 </p>
331 <p>
332 Meanwhile core developers have added OPENSSL_EXPORT to definitions of
333 these macros (this happened on 0.9.8b in stable and nearly at the same
334 time in development branch). We've fixed it in our engine for stable
335 version (available at <a
336 href="http://www.cryptocom.ru/OpenSource/OpenSSL_eng.html">www.cryptocom.ru</a>,
337 but have forgotte to check development version. Then our engine was
338 accepted into development distribution, and nobody cares to test it
339 under Win32 until Oct 20.
340 </p>
341 </BODY>
342 </HTML>