927856672559bc426728e756dca37afe48055631
[platform/upstream/cmake.git] / Modules / FindOpenSSL.cmake
1 # Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2 # file Copyright.txt or https://cmake.org/licensing for details.
3
4 #[=======================================================================[.rst:
5 FindOpenSSL
6 -----------
7
8 Find the OpenSSL encryption library.
9
10 This module finds an installed OpenSSL library and determines its version.
11
12 .. versionadded:: 3.19
13   When a version is requested, it can be specified as a simple value or as a
14   range. For a detailed description of version range usage and capabilities,
15   refer to the :command:`find_package` command.
16
17 .. versionadded:: 3.18
18   Support for OpenSSL 3.0.
19
20 Optional COMPONENTS
21 ^^^^^^^^^^^^^^^^^^^
22
23 .. versionadded:: 3.12
24
25 This module supports two optional COMPONENTS: ``Crypto`` and ``SSL``.  Both
26 components have associated imported targets, as described below.
27
28 Imported Targets
29 ^^^^^^^^^^^^^^^^
30
31 .. versionadded:: 3.4
32
33 This module defines the following :prop_tgt:`IMPORTED` targets:
34
35 ``OpenSSL::SSL``
36   The OpenSSL ``ssl`` library, if found.
37 ``OpenSSL::Crypto``
38   The OpenSSL ``crypto`` library, if found.
39 ``OpenSSL::applink``
40   .. versionadded:: 3.18
41
42   The OpenSSL ``applink`` components that might be need to be compiled into
43   projects under MSVC. This target is available only if found OpenSSL version
44   is not less than 0.9.8. By linking this target the above OpenSSL targets can
45   be linked even if the project has different MSVC runtime configurations with
46   the above OpenSSL targets. This target has no effect on platforms other than
47   MSVC.
48
49 NOTE: Due to how ``INTERFACE_SOURCES`` are consumed by the consuming target,
50 unless you certainly know what you are doing, it is always preferred to link
51 ``OpenSSL::applink`` target as ``PRIVATE`` and to make sure that this target is
52 linked at most once for the whole dependency graph of any library or
53 executable:
54
55 .. code-block:: cmake
56
57    target_link_libraries(myTarget PRIVATE OpenSSL::applink)
58
59 Otherwise you would probably encounter unexpected random problems when building
60 and linking, as both the ISO C and the ISO C++ standard claims almost nothing
61 about what a link process should be.
62
63 Result Variables
64 ^^^^^^^^^^^^^^^^
65
66 This module will set the following variables in your project:
67
68 ``OPENSSL_FOUND``
69   System has the OpenSSL library. If no components are requested it only
70   requires the crypto library.
71 ``OPENSSL_INCLUDE_DIR``
72   The OpenSSL include directory.
73 ``OPENSSL_CRYPTO_LIBRARY``
74   The OpenSSL crypto library.
75 ``OPENSSL_CRYPTO_LIBRARIES``
76   The OpenSSL crypto library and its dependencies.
77 ``OPENSSL_SSL_LIBRARY``
78   The OpenSSL SSL library.
79 ``OPENSSL_SSL_LIBRARIES``
80   The OpenSSL SSL library and its dependencies.
81 ``OPENSSL_LIBRARIES``
82   All OpenSSL libraries and their dependencies.
83 ``OPENSSL_VERSION``
84   This is set to ``$major.$minor.$revision$patch`` (e.g. ``0.9.8s``).
85 ``OPENSSL_APPLINK_SOURCE``
86   The sources in the target ``OpenSSL::applink`` that is mentioned above. This
87   variable shall always be undefined if found openssl version is less than
88   0.9.8 or if platform is not MSVC.
89
90 Hints
91 ^^^^^
92
93 Set ``OPENSSL_ROOT_DIR`` to the root directory of an OpenSSL installation.
94
95 .. versionadded:: 3.4
96   Set ``OPENSSL_USE_STATIC_LIBS`` to ``TRUE`` to look for static libraries.
97
98 .. versionadded:: 3.5
99   Set ``OPENSSL_MSVC_STATIC_RT`` set ``TRUE`` to choose the MT version of the lib.
100 #]=======================================================================]
101
102 macro(_OpenSSL_test_and_find_dependencies ssl_library crypto_library)
103   if((CMAKE_SYSTEM_NAME STREQUAL "Linux") AND
104      (("${ssl_library}" MATCHES "\\${CMAKE_STATIC_LIBRARY_SUFFIX}$") OR
105       ("${crypto_library}" MATCHES "\\${CMAKE_STATIC_LIBRARY_SUFFIX}$")))
106     set(_OpenSSL_has_dependencies TRUE)
107     find_package(Threads)
108   else()
109     set(_OpenSSL_has_dependencies FALSE)
110   endif()
111 endmacro()
112
113 function(_OpenSSL_add_dependencies libraries_var)
114   if(CMAKE_THREAD_LIBS_INIT)
115     list(APPEND ${libraries_var} ${CMAKE_THREAD_LIBS_INIT})
116   endif()
117   list(APPEND ${libraries_var} ${CMAKE_DL_LIBS})
118   set(${libraries_var} ${${libraries_var}} PARENT_SCOPE)
119 endfunction()
120
121 function(_OpenSSL_target_add_dependencies target)
122   if(_OpenSSL_has_dependencies)
123     set_property( TARGET ${target} APPEND PROPERTY INTERFACE_LINK_LIBRARIES Threads::Threads )
124     set_property( TARGET ${target} APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${CMAKE_DL_LIBS} )
125   endif()
126   if(WIN32 AND OPENSSL_USE_STATIC_LIBS)
127     if(WINCE)
128       set_property( TARGET ${target} APPEND PROPERTY INTERFACE_LINK_LIBRARIES ws2 )
129     else()
130       set_property( TARGET ${target} APPEND PROPERTY INTERFACE_LINK_LIBRARIES ws2_32 )
131     endif()
132     set_property( TARGET ${target} APPEND PROPERTY INTERFACE_LINK_LIBRARIES crypt32 )
133   endif()
134 endfunction()
135
136 if (UNIX)
137   find_package(PkgConfig QUIET)
138   pkg_check_modules(_OPENSSL QUIET openssl)
139 endif ()
140
141 # Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES
142 if(OPENSSL_USE_STATIC_LIBS)
143   set(_openssl_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
144   if(WIN32)
145     set(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
146   else()
147     set(CMAKE_FIND_LIBRARY_SUFFIXES .a )
148   endif()
149 endif()
150
151 if(CMAKE_SYSTEM_NAME STREQUAL "QNX" AND
152   CMAKE_SYSTEM_VERSION VERSION_GREATER_EQUAL "7.0" AND CMAKE_SYSTEM_VERSION VERSION_LESS "7.1" AND
153   OpenSSL_FIND_VERSION VERSION_GREATER_EQUAL "1.1" AND OpenSSL_FIND_VERSION VERSION_LESS "1.2")
154   # QNX 7.0.x provides openssl 1.0.2 and 1.1.1 in parallel:
155   # * openssl 1.0.2: libcrypto.so.2 and libssl.so.2, headers under usr/include/openssl
156   # * openssl 1.1.1: libcrypto1_1.so.2.1 and libssl1_1.so.2.1, header under usr/include/openssl1_1
157   # See http://www.qnx.com/developers/articles/rel_6726_0.html
158   set(_OPENSSL_FIND_PATH_SUFFIX "openssl1_1")
159   set(_OPENSSL_NAME_POSTFIX "1_1")
160 else()
161   set(_OPENSSL_FIND_PATH_SUFFIX "include")
162 endif()
163
164 if (WIN32)
165   # http://www.slproweb.com/products/Win32OpenSSL.html
166   set(_OPENSSL_ROOT_HINTS
167     ${OPENSSL_ROOT_DIR}
168     "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (32-bit)_is1;Inno Setup: App Path]"
169     "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (64-bit)_is1;Inno Setup: App Path]"
170     ENV OPENSSL_ROOT_DIR
171     )
172
173   if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
174     set(_arch "Win64")
175     file(TO_CMAKE_PATH "$ENV{PROGRAMFILES}" _programfiles)
176   else()
177     set(_arch "Win32")
178     set(_progfiles_x86 "ProgramFiles(x86)")
179     if(NOT "$ENV{${_progfiles_x86}}" STREQUAL "")
180       # under windows 64 bit machine
181       file(TO_CMAKE_PATH "$ENV{${_progfiles_x86}}" _programfiles)
182     else()
183       # under windows 32 bit machine
184       file(TO_CMAKE_PATH "$ENV{ProgramFiles}" _programfiles)
185     endif()
186   endif()
187
188   set(_OPENSSL_ROOT_PATHS
189     "${_programfiles}/OpenSSL"
190     "${_programfiles}/OpenSSL-${_arch}"
191     "C:/OpenSSL/"
192     "C:/OpenSSL-${_arch}/"
193     )
194   unset(_programfiles)
195   unset(_arch)
196 else ()
197   set(_OPENSSL_ROOT_HINTS
198     ${OPENSSL_ROOT_DIR}
199     ENV OPENSSL_ROOT_DIR
200     )
201 endif ()
202
203 set(_OPENSSL_ROOT_HINTS_AND_PATHS
204     HINTS ${_OPENSSL_ROOT_HINTS}
205     PATHS ${_OPENSSL_ROOT_PATHS}
206     )
207
208 find_path(OPENSSL_INCLUDE_DIR
209   NAMES
210     openssl/ssl.h
211   ${_OPENSSL_ROOT_HINTS_AND_PATHS}
212   HINTS
213     ${_OPENSSL_INCLUDEDIR}
214     ${_OPENSSL_INCLUDE_DIRS}
215   PATH_SUFFIXES
216     ${_OPENSSL_FIND_PATH_SUFFIX}
217 )
218
219 if(WIN32 AND NOT CYGWIN)
220   if(MSVC)
221     # /MD and /MDd are the standard values - if someone wants to use
222     # others, the libnames have to change here too
223     # use also ssl and ssleay32 in debug as fallback for openssl < 0.9.8b
224     # enable OPENSSL_MSVC_STATIC_RT to get the libs build /MT (Multithreaded no-DLL)
225     # In Visual C++ naming convention each of these four kinds of Windows libraries has it's standard suffix:
226     #   * MD for dynamic-release
227     #   * MDd for dynamic-debug
228     #   * MT for static-release
229     #   * MTd for static-debug
230
231     # Implementation details:
232     # We are using the libraries located in the VC subdir instead of the parent directory even though :
233     # libeay32MD.lib is identical to ../libeay32.lib, and
234     # ssleay32MD.lib is identical to ../ssleay32.lib
235     # enable OPENSSL_USE_STATIC_LIBS to use the static libs located in lib/VC/static
236
237     if (OPENSSL_MSVC_STATIC_RT)
238       set(_OPENSSL_MSVC_RT_MODE "MT")
239     else ()
240       set(_OPENSSL_MSVC_RT_MODE "MD")
241     endif ()
242
243     # Since OpenSSL 1.1, lib names are like libcrypto32MTd.lib and libssl32MTd.lib
244     if( "${CMAKE_SIZEOF_VOID_P}" STREQUAL "8" )
245         set(_OPENSSL_MSVC_ARCH_SUFFIX "64")
246     else()
247         set(_OPENSSL_MSVC_ARCH_SUFFIX "32")
248     endif()
249
250     if(OPENSSL_USE_STATIC_LIBS)
251       set(_OPENSSL_STATIC_SUFFIX
252         "_static"
253       )
254       set(_OPENSSL_PATH_SUFFIXES
255         "lib/VC/static"
256         "VC/static"
257         "lib"
258         )
259     else()
260       set(_OPENSSL_STATIC_SUFFIX
261         ""
262       )
263       set(_OPENSSL_PATH_SUFFIXES
264         "lib/VC"
265         "VC"
266         "lib"
267         )
268     endif ()
269
270     find_library(LIB_EAY_DEBUG
271       NAMES
272         # When OpenSSL is built with default options, the static library name is suffixed with "_static".
273         # Looking the "libcrypto_static.lib" with a higher priority than "libcrypto.lib" which is the
274         # import library of "libcrypto.dll".
275         libcrypto${_OPENSSL_STATIC_SUFFIX}${_OPENSSL_MSVC_ARCH_SUFFIX}${_OPENSSL_MSVC_RT_MODE}d
276         libcrypto${_OPENSSL_STATIC_SUFFIX}${_OPENSSL_MSVC_RT_MODE}d
277         libcrypto${_OPENSSL_STATIC_SUFFIX}d
278         libeay32${_OPENSSL_STATIC_SUFFIX}${_OPENSSL_MSVC_RT_MODE}d
279         libeay32${_OPENSSL_STATIC_SUFFIX}d
280         crypto${_OPENSSL_STATIC_SUFFIX}d
281         # When OpenSSL is built with the "-static" option, only the static build is produced,
282         # and it is not suffixed with "_static".
283         libcrypto${_OPENSSL_MSVC_ARCH_SUFFIX}${_OPENSSL_MSVC_RT_MODE}d
284         libcrypto${_OPENSSL_MSVC_RT_MODE}d
285         libcryptod
286         libeay32${_OPENSSL_MSVC_RT_MODE}d
287         libeay32d
288         cryptod
289       NAMES_PER_DIR
290       ${_OPENSSL_ROOT_HINTS_AND_PATHS}
291       PATH_SUFFIXES
292         ${_OPENSSL_PATH_SUFFIXES}
293     )
294
295     find_library(LIB_EAY_RELEASE
296       NAMES
297         # When OpenSSL is built with default options, the static library name is suffixed with "_static".
298         # Looking the "libcrypto_static.lib" with a higher priority than "libcrypto.lib" which is the
299         # import library of "libcrypto.dll".
300         libcrypto${_OPENSSL_STATIC_SUFFIX}${_OPENSSL_MSVC_ARCH_SUFFIX}${_OPENSSL_MSVC_RT_MODE}
301         libcrypto${_OPENSSL_STATIC_SUFFIX}${_OPENSSL_MSVC_RT_MODE}
302         libcrypto${_OPENSSL_STATIC_SUFFIX}
303         libeay32${_OPENSSL_STATIC_SUFFIX}${_OPENSSL_MSVC_RT_MODE}
304         libeay32${_OPENSSL_STATIC_SUFFIX}
305         crypto${_OPENSSL_STATIC_SUFFIX}
306         # When OpenSSL is built with the "-static" option, only the static build is produced,
307         # and it is not suffixed with "_static".
308         libcrypto${_OPENSSL_MSVC_ARCH_SUFFIX}${_OPENSSL_MSVC_RT_MODE}
309         libcrypto${_OPENSSL_MSVC_RT_MODE}
310         libcrypto
311         libeay32${_OPENSSL_MSVC_RT_MODE}
312         libeay32
313         crypto
314       NAMES_PER_DIR
315       ${_OPENSSL_ROOT_HINTS_AND_PATHS}
316       PATH_SUFFIXES
317         ${_OPENSSL_PATH_SUFFIXES}
318     )
319
320     find_library(SSL_EAY_DEBUG
321       NAMES
322         # When OpenSSL is built with default options, the static library name is suffixed with "_static".
323         # Looking the "libssl_static.lib" with a higher priority than "libssl.lib" which is the
324         # import library of "libssl.dll".
325         libssl${_OPENSSL_STATIC_SUFFIX}${_OPENSSL_MSVC_ARCH_SUFFIX}${_OPENSSL_MSVC_RT_MODE}d
326         libssl${_OPENSSL_STATIC_SUFFIX}${_OPENSSL_MSVC_RT_MODE}d
327         libssl${_OPENSSL_STATIC_SUFFIX}d
328         ssleay32${_OPENSSL_STATIC_SUFFIX}${_OPENSSL_MSVC_RT_MODE}d
329         ssleay32${_OPENSSL_STATIC_SUFFIX}d
330         ssl${_OPENSSL_STATIC_SUFFIX}d
331         # When OpenSSL is built with the "-static" option, only the static build is produced,
332         # and it is not suffixed with "_static".
333         libssl${_OPENSSL_MSVC_ARCH_SUFFIX}${_OPENSSL_MSVC_RT_MODE}d
334         libssl${_OPENSSL_MSVC_RT_MODE}d
335         libssld
336         ssleay32${_OPENSSL_MSVC_RT_MODE}d
337         ssleay32d
338         ssld
339       NAMES_PER_DIR
340       ${_OPENSSL_ROOT_HINTS_AND_PATHS}
341       PATH_SUFFIXES
342         ${_OPENSSL_PATH_SUFFIXES}
343     )
344
345     find_library(SSL_EAY_RELEASE
346       NAMES
347         # When OpenSSL is built with default options, the static library name is suffixed with "_static".
348         # Looking the "libssl_static.lib" with a higher priority than "libssl.lib" which is the
349         # import library of "libssl.dll".
350         libssl${_OPENSSL_STATIC_SUFFIX}${_OPENSSL_MSVC_ARCH_SUFFIX}${_OPENSSL_MSVC_RT_MODE}
351         libssl${_OPENSSL_STATIC_SUFFIX}${_OPENSSL_MSVC_RT_MODE}
352         libssl${_OPENSSL_STATIC_SUFFIX}
353         ssleay32${_OPENSSL_STATIC_SUFFIX}${_OPENSSL_MSVC_RT_MODE}
354         ssleay32${_OPENSSL_STATIC_SUFFIX}
355         ssl${_OPENSSL_STATIC_SUFFIX}
356         # When OpenSSL is built with the "-static" option, only the static build is produced,
357         # and it is not suffixed with "_static".
358         libssl${_OPENSSL_MSVC_ARCH_SUFFIX}${_OPENSSL_MSVC_RT_MODE}
359         libssl${_OPENSSL_MSVC_RT_MODE}
360         libssl
361         ssleay32${_OPENSSL_MSVC_RT_MODE}
362         ssleay32
363         ssl
364       NAMES_PER_DIR
365       ${_OPENSSL_ROOT_HINTS_AND_PATHS}
366       PATH_SUFFIXES
367         ${_OPENSSL_PATH_SUFFIXES}
368     )
369
370     set(LIB_EAY_LIBRARY_DEBUG "${LIB_EAY_DEBUG}")
371     set(LIB_EAY_LIBRARY_RELEASE "${LIB_EAY_RELEASE}")
372     set(SSL_EAY_LIBRARY_DEBUG "${SSL_EAY_DEBUG}")
373     set(SSL_EAY_LIBRARY_RELEASE "${SSL_EAY_RELEASE}")
374
375     include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
376     select_library_configurations(LIB_EAY)
377     select_library_configurations(SSL_EAY)
378
379     mark_as_advanced(LIB_EAY_LIBRARY_DEBUG LIB_EAY_LIBRARY_RELEASE
380                      SSL_EAY_LIBRARY_DEBUG SSL_EAY_LIBRARY_RELEASE)
381     set(OPENSSL_SSL_LIBRARY ${SSL_EAY_LIBRARY} )
382     set(OPENSSL_CRYPTO_LIBRARY ${LIB_EAY_LIBRARY} )
383   elseif(MINGW)
384     # same player, for MinGW
385     set(LIB_EAY_NAMES crypto libeay32)
386     set(SSL_EAY_NAMES ssl ssleay32)
387     find_library(LIB_EAY
388       NAMES
389         ${LIB_EAY_NAMES}
390       NAMES_PER_DIR
391       ${_OPENSSL_ROOT_HINTS_AND_PATHS}
392       PATH_SUFFIXES
393         "lib/MinGW"
394         "lib"
395     )
396
397     find_library(SSL_EAY
398       NAMES
399         ${SSL_EAY_NAMES}
400       NAMES_PER_DIR
401       ${_OPENSSL_ROOT_HINTS_AND_PATHS}
402       PATH_SUFFIXES
403         "lib/MinGW"
404         "lib"
405     )
406
407     mark_as_advanced(SSL_EAY LIB_EAY)
408     set(OPENSSL_SSL_LIBRARY ${SSL_EAY} )
409     set(OPENSSL_CRYPTO_LIBRARY ${LIB_EAY} )
410     unset(LIB_EAY_NAMES)
411     unset(SSL_EAY_NAMES)
412   else()
413     # Not sure what to pick for -say- intel, let's use the toplevel ones and hope someone report issues:
414     find_library(LIB_EAY
415       NAMES
416         libcrypto
417         libeay32
418       NAMES_PER_DIR
419       ${_OPENSSL_ROOT_HINTS_AND_PATHS}
420       HINTS
421         ${_OPENSSL_LIBDIR}
422       PATH_SUFFIXES
423         lib
424     )
425
426     find_library(SSL_EAY
427       NAMES
428         libssl
429         ssleay32
430       NAMES_PER_DIR
431       ${_OPENSSL_ROOT_HINTS_AND_PATHS}
432       HINTS
433         ${_OPENSSL_LIBDIR}
434       PATH_SUFFIXES
435         lib
436     )
437
438     mark_as_advanced(SSL_EAY LIB_EAY)
439     set(OPENSSL_SSL_LIBRARY ${SSL_EAY} )
440     set(OPENSSL_CRYPTO_LIBRARY ${LIB_EAY} )
441   endif()
442 else()
443
444   find_library(OPENSSL_SSL_LIBRARY
445     NAMES
446       ssl${_OPENSSL_NAME_POSTFIX}
447       ssleay32
448       ssleay32MD
449     NAMES_PER_DIR
450     ${_OPENSSL_ROOT_HINTS_AND_PATHS}
451     HINTS
452       ${_OPENSSL_LIBDIR}
453       ${_OPENSSL_LIBRARY_DIRS}
454     PATH_SUFFIXES
455       lib lib64
456   )
457
458   find_library(OPENSSL_CRYPTO_LIBRARY
459     NAMES
460       crypto${_OPENSSL_NAME_POSTFIX}
461     NAMES_PER_DIR
462     ${_OPENSSL_ROOT_HINTS_AND_PATHS}
463     HINTS
464       ${_OPENSSL_LIBDIR}
465       ${_OPENSSL_LIBRARY_DIRS}
466     PATH_SUFFIXES
467       lib lib64
468   )
469
470   mark_as_advanced(OPENSSL_CRYPTO_LIBRARY OPENSSL_SSL_LIBRARY)
471
472 endif()
473
474 set(OPENSSL_SSL_LIBRARIES ${OPENSSL_SSL_LIBRARY})
475 set(OPENSSL_CRYPTO_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
476 set(OPENSSL_LIBRARIES ${OPENSSL_SSL_LIBRARIES} ${OPENSSL_CRYPTO_LIBRARIES} )
477 _OpenSSL_test_and_find_dependencies("${OPENSSL_SSL_LIBRARY}" "${OPENSSL_CRYPTO_LIBRARY}")
478 if(_OpenSSL_has_dependencies)
479   _OpenSSL_add_dependencies( OPENSSL_SSL_LIBRARIES )
480   _OpenSSL_add_dependencies( OPENSSL_CRYPTO_LIBRARIES )
481   _OpenSSL_add_dependencies( OPENSSL_LIBRARIES )
482 endif()
483
484 function(from_hex HEX DEC)
485   string(TOUPPER "${HEX}" HEX)
486   set(_res 0)
487   string(LENGTH "${HEX}" _strlen)
488
489   while (_strlen GREATER 0)
490     math(EXPR _res "${_res} * 16")
491     string(SUBSTRING "${HEX}" 0 1 NIBBLE)
492     string(SUBSTRING "${HEX}" 1 -1 HEX)
493     if (NIBBLE STREQUAL "A")
494       math(EXPR _res "${_res} + 10")
495     elseif (NIBBLE STREQUAL "B")
496       math(EXPR _res "${_res} + 11")
497     elseif (NIBBLE STREQUAL "C")
498       math(EXPR _res "${_res} + 12")
499     elseif (NIBBLE STREQUAL "D")
500       math(EXPR _res "${_res} + 13")
501     elseif (NIBBLE STREQUAL "E")
502       math(EXPR _res "${_res} + 14")
503     elseif (NIBBLE STREQUAL "F")
504       math(EXPR _res "${_res} + 15")
505     else()
506       math(EXPR _res "${_res} + ${NIBBLE}")
507     endif()
508
509     string(LENGTH "${HEX}" _strlen)
510   endwhile()
511
512   set(${DEC} ${_res} PARENT_SCOPE)
513 endfunction()
514
515 if(OPENSSL_INCLUDE_DIR AND EXISTS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h")
516   file(STRINGS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h" openssl_version_str
517        REGEX "^#[\t ]*define[\t ]+OPENSSL_VERSION_NUMBER[\t ]+0x([0-9a-fA-F])+.*")
518
519   if(openssl_version_str)
520     # The version number is encoded as 0xMNNFFPPS: major minor fix patch status
521     # The status gives if this is a developer or prerelease and is ignored here.
522     # Major, minor, and fix directly translate into the version numbers shown in
523     # the string. The patch field translates to the single character suffix that
524     # indicates the bug fix state, which 00 -> nothing, 01 -> a, 02 -> b and so
525     # on.
526
527     string(REGEX REPLACE "^.*OPENSSL_VERSION_NUMBER[\t ]+0x([0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F]).*$"
528            "\\1;\\2;\\3;\\4;\\5" OPENSSL_VERSION_LIST "${openssl_version_str}")
529     list(GET OPENSSL_VERSION_LIST 0 OPENSSL_VERSION_MAJOR)
530     list(GET OPENSSL_VERSION_LIST 1 OPENSSL_VERSION_MINOR)
531     from_hex("${OPENSSL_VERSION_MINOR}" OPENSSL_VERSION_MINOR)
532     list(GET OPENSSL_VERSION_LIST 2 OPENSSL_VERSION_FIX)
533     from_hex("${OPENSSL_VERSION_FIX}" OPENSSL_VERSION_FIX)
534     list(GET OPENSSL_VERSION_LIST 3 OPENSSL_VERSION_PATCH)
535
536     if (NOT OPENSSL_VERSION_PATCH STREQUAL "00")
537       from_hex("${OPENSSL_VERSION_PATCH}" _tmp)
538       # 96 is the ASCII code of 'a' minus 1
539       math(EXPR OPENSSL_VERSION_PATCH_ASCII "${_tmp} + 96")
540       unset(_tmp)
541       # Once anyone knows how OpenSSL would call the patch versions beyond 'z'
542       # this should be updated to handle that, too. This has not happened yet
543       # so it is simply ignored here for now.
544       string(ASCII "${OPENSSL_VERSION_PATCH_ASCII}" OPENSSL_VERSION_PATCH_STRING)
545     endif ()
546
547     set(OPENSSL_VERSION "${OPENSSL_VERSION_MAJOR}.${OPENSSL_VERSION_MINOR}.${OPENSSL_VERSION_FIX}${OPENSSL_VERSION_PATCH_STRING}")
548   else ()
549     # Since OpenSSL 3.0.0, the new version format is MAJOR.MINOR.PATCH and
550     # a new OPENSSL_VERSION_STR macro contains exactly that
551     file(STRINGS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h" OPENSSL_VERSION_STR
552          REGEX "^#[\t ]*define[\t ]+OPENSSL_VERSION_STR[\t ]+\"([0-9])+\\.([0-9])+\\.([0-9])+\".*")
553     string(REGEX REPLACE "^.*OPENSSL_VERSION_STR[\t ]+\"([0-9]+\\.[0-9]+\\.[0-9]+)\".*$"
554            "\\1" OPENSSL_VERSION_STR "${OPENSSL_VERSION_STR}")
555
556     set(OPENSSL_VERSION "${OPENSSL_VERSION_STR}")
557
558     # Setting OPENSSL_VERSION_MAJOR OPENSSL_VERSION_MINOR and OPENSSL_VERSION_FIX
559     string(REGEX MATCHALL "([0-9])+" OPENSSL_VERSION_NUMBER "${OPENSSL_VERSION}")
560     list(POP_FRONT OPENSSL_VERSION_NUMBER
561       OPENSSL_VERSION_MAJOR
562       OPENSSL_VERSION_MINOR
563       OPENSSL_VERSION_FIX)
564
565     unset(OPENSSL_VERSION_NUMBER)
566     unset(OPENSSL_VERSION_STR)
567   endif ()
568 endif ()
569
570 foreach(_comp IN LISTS OpenSSL_FIND_COMPONENTS)
571   if(_comp STREQUAL "Crypto")
572     if(EXISTS "${OPENSSL_INCLUDE_DIR}" AND
573         (EXISTS "${OPENSSL_CRYPTO_LIBRARY}" OR
574         EXISTS "${LIB_EAY_LIBRARY_DEBUG}" OR
575         EXISTS "${LIB_EAY_LIBRARY_RELEASE}")
576     )
577       set(OpenSSL_${_comp}_FOUND TRUE)
578     else()
579       set(OpenSSL_${_comp}_FOUND FALSE)
580     endif()
581   elseif(_comp STREQUAL "SSL")
582     if(EXISTS "${OPENSSL_INCLUDE_DIR}" AND
583         (EXISTS "${OPENSSL_SSL_LIBRARY}" OR
584         EXISTS "${SSL_EAY_LIBRARY_DEBUG}" OR
585         EXISTS "${SSL_EAY_LIBRARY_RELEASE}")
586     )
587       set(OpenSSL_${_comp}_FOUND TRUE)
588     else()
589       set(OpenSSL_${_comp}_FOUND FALSE)
590     endif()
591   else()
592     message(WARNING "${_comp} is not a valid OpenSSL component")
593     set(OpenSSL_${_comp}_FOUND FALSE)
594   endif()
595 endforeach()
596 unset(_comp)
597
598 include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
599 find_package_handle_standard_args(OpenSSL
600   REQUIRED_VARS
601     OPENSSL_CRYPTO_LIBRARY
602     OPENSSL_INCLUDE_DIR
603   VERSION_VAR
604     OPENSSL_VERSION
605   HANDLE_VERSION_RANGE
606   HANDLE_COMPONENTS
607   FAIL_MESSAGE
608     "Could NOT find OpenSSL, try to set the path to OpenSSL root folder in the system variable OPENSSL_ROOT_DIR"
609 )
610
611 mark_as_advanced(OPENSSL_INCLUDE_DIR)
612
613 if(OPENSSL_FOUND)
614   if(NOT TARGET OpenSSL::Crypto AND
615       (EXISTS "${OPENSSL_CRYPTO_LIBRARY}" OR
616         EXISTS "${LIB_EAY_LIBRARY_DEBUG}" OR
617         EXISTS "${LIB_EAY_LIBRARY_RELEASE}")
618       )
619     add_library(OpenSSL::Crypto UNKNOWN IMPORTED)
620     set_target_properties(OpenSSL::Crypto PROPERTIES
621       INTERFACE_INCLUDE_DIRECTORIES "${OPENSSL_INCLUDE_DIR}")
622     if(EXISTS "${OPENSSL_CRYPTO_LIBRARY}")
623       set_target_properties(OpenSSL::Crypto PROPERTIES
624         IMPORTED_LINK_INTERFACE_LANGUAGES "C"
625         IMPORTED_LOCATION "${OPENSSL_CRYPTO_LIBRARY}")
626     endif()
627     if(EXISTS "${LIB_EAY_LIBRARY_RELEASE}")
628       set_property(TARGET OpenSSL::Crypto APPEND PROPERTY
629         IMPORTED_CONFIGURATIONS RELEASE)
630       set_target_properties(OpenSSL::Crypto PROPERTIES
631         IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "C"
632         IMPORTED_LOCATION_RELEASE "${LIB_EAY_LIBRARY_RELEASE}")
633     endif()
634     if(EXISTS "${LIB_EAY_LIBRARY_DEBUG}")
635       set_property(TARGET OpenSSL::Crypto APPEND PROPERTY
636         IMPORTED_CONFIGURATIONS DEBUG)
637       set_target_properties(OpenSSL::Crypto PROPERTIES
638         IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "C"
639         IMPORTED_LOCATION_DEBUG "${LIB_EAY_LIBRARY_DEBUG}")
640     endif()
641     _OpenSSL_target_add_dependencies(OpenSSL::Crypto)
642   endif()
643
644   if(NOT TARGET OpenSSL::SSL AND
645       (EXISTS "${OPENSSL_SSL_LIBRARY}" OR
646         EXISTS "${SSL_EAY_LIBRARY_DEBUG}" OR
647         EXISTS "${SSL_EAY_LIBRARY_RELEASE}")
648       )
649     add_library(OpenSSL::SSL UNKNOWN IMPORTED)
650     set_target_properties(OpenSSL::SSL PROPERTIES
651       INTERFACE_INCLUDE_DIRECTORIES "${OPENSSL_INCLUDE_DIR}")
652     if(EXISTS "${OPENSSL_SSL_LIBRARY}")
653       set_target_properties(OpenSSL::SSL PROPERTIES
654         IMPORTED_LINK_INTERFACE_LANGUAGES "C"
655         IMPORTED_LOCATION "${OPENSSL_SSL_LIBRARY}")
656     endif()
657     if(EXISTS "${SSL_EAY_LIBRARY_RELEASE}")
658       set_property(TARGET OpenSSL::SSL APPEND PROPERTY
659         IMPORTED_CONFIGURATIONS RELEASE)
660       set_target_properties(OpenSSL::SSL PROPERTIES
661         IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "C"
662         IMPORTED_LOCATION_RELEASE "${SSL_EAY_LIBRARY_RELEASE}")
663     endif()
664     if(EXISTS "${SSL_EAY_LIBRARY_DEBUG}")
665       set_property(TARGET OpenSSL::SSL APPEND PROPERTY
666         IMPORTED_CONFIGURATIONS DEBUG)
667       set_target_properties(OpenSSL::SSL PROPERTIES
668         IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "C"
669         IMPORTED_LOCATION_DEBUG "${SSL_EAY_LIBRARY_DEBUG}")
670     endif()
671     if(TARGET OpenSSL::Crypto)
672       set_target_properties(OpenSSL::SSL PROPERTIES
673         INTERFACE_LINK_LIBRARIES OpenSSL::Crypto)
674     endif()
675     _OpenSSL_target_add_dependencies(OpenSSL::SSL)
676   endif()
677
678   if("${OPENSSL_VERSION_MAJOR}.${OPENSSL_VERSION_MINOR}.${OPENSSL_VERSION_FIX}" VERSION_GREATER_EQUAL "0.9.8")
679     if(MSVC)
680       if(EXISTS "${OPENSSL_INCLUDE_DIR}")
681         set(_OPENSSL_applink_paths PATHS ${OPENSSL_INCLUDE_DIR})
682       endif()
683       find_file(OPENSSL_APPLINK_SOURCE
684         NAMES
685           openssl/applink.c
686         ${_OPENSSL_applink_paths}
687         NO_DEFAULT_PATH)
688       if(OPENSSL_APPLINK_SOURCE)
689         set(_OPENSSL_applink_interface_srcs ${OPENSSL_APPLINK_SOURCE})
690       endif()
691     endif()
692     if(NOT TARGET OpenSSL::applink)
693       add_library(OpenSSL::applink INTERFACE IMPORTED)
694       set_property(TARGET OpenSSL::applink APPEND
695         PROPERTY INTERFACE_SOURCES
696           ${_OPENSSL_applink_interface_srcs})
697     endif()
698   endif()
699 endif()
700
701 # Restore the original find library ordering
702 if(OPENSSL_USE_STATIC_LIBS)
703   set(CMAKE_FIND_LIBRARY_SUFFIXES ${_openssl_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES})
704 endif()
705
706 unset(_OPENSSL_FIND_PATH_SUFFIX)
707 unset(_OPENSSL_NAME_POSTFIX)