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