View source with formatted comments or as raw
    1/*  Part of SWI-Prolog
    2
    3    Author:        Jan van der Steen, Matt Lilley and Jan Wielemaker,
    4    E-mail:        J.Wielemaker@vu.nl
    5    WWW:           http://www.swi-prolog.org
    6    Copyright (c)  2004-2020, SWI-Prolog Foundation
    7                              VU University Amsterdam
    8                              CWI, Amsterdam
    9    All rights reserved.
   10
   11    Redistribution and use in source and binary forms, with or without
   12    modification, are permitted provided that the following conditions
   13    are met:
   14
   15    1. Redistributions of source code must retain the above copyright
   16       notice, this list of conditions and the following disclaimer.
   17
   18    2. Redistributions in binary form must reproduce the above copyright
   19       notice, this list of conditions and the following disclaimer in
   20       the documentation and/or other materials provided with the
   21       distribution.
   22
   23    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   24    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   25    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   26    FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
   27    COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   28    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   29    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   30    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   31    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   33    ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   34    POSSIBILITY OF SUCH DAMAGE.
   35*/
   36
   37:- module(ssl,
   38	  [ certificate_field/2,          % +Certificate, ?Field
   39	    load_certificate/2,           % +Stream, -Certificate
   40	    load_private_key/3,           % +Stream, +Password, -Key
   41            load_public_key/2,            % +Stream, -Key
   42	    load_crl/2,                   % +Stream, -Crl
   43	    write_certificate/3,          % +Stream, -X509, +Options
   44            system_root_certificates/1,   % -List
   45            cert_accept_any/5,            % +SSL, +ProblemCertificate,
   46                                          % +AllCertificates, +FirstCertificate,
   47                                          % +Error
   48            same_certificate/2,           % +CertificateA, +CertificateB
   49            ssl_context/3,                % +Role, -Config, :Options
   50            ssl_add_certificate_key/4,    % +Config, +Cert, +Key, -Config
   51            ssl_set_options/3,            % +Config0, -Config, +Options
   52            ssl_property/2,               % +Config, ?Property
   53            ssl_negotiate/5,              % +Config, +PlainRead, +PlainWrite,
   54                                          %          -SSLRead,   -SSLWrite
   55            ssl_peer_certificate/2,       % +Stream, -Certificate
   56            ssl_peer_certificate_chain/2, % +Stream, -Certificates
   57            ssl_session/2,                % +Stream, -Session
   58	    ssl_secure_ciphers/1,         % -Ciphers,
   59	    verify_certificate/3,         % +X509, +AuxiliaryCertificates, +TrustedCertificates
   60	    verify_certificate_issuer/2,  % +Certificate, +IssuerCertificate
   61
   62            ssl_upgrade_legacy_options/2  % +OptionsIn, -OptionsOut
   63          ]).   64:- autoload(library(option),[select_option/4,select_option/3]).   65:- use_module(library(settings),[setting/4,setting/2]).   66
   67:- use_module(library(crypto), []).     % force initialization of libcrypto
   68
   69:- use_foreign_library(foreign(ssl4pl)).   70
   71:- meta_predicate
   72    ssl_context(+, -, :),
   73    ssl_set_options(+, -, :).   74
   75:- predicate_options(ssl_context/3, 3,
   76                     [ host(atom),
   77                       port(integer),
   78                       cacerts(list),
   79                       certificate_file(atom),
   80                       key_file(atom),
   81                       certificate_key_pairs(any),
   82                       password(any),
   83                       cipher_list(any),
   84                       ecdh_curve(any),
   85                       pem_password_hook(callable),
   86                       cacert_file(any),
   87                       crl(any),
   88                       require_crl(boolean),
   89                       cert_verify_hook(callable),
   90                       peer_cert(boolean),
   91                       close_parent(boolean),
   92                       close_notify(boolean),
   93                       sni_hook(callable),
   94                       alpn_protocols(any),
   95                       alpn_protocol_hook(callable)
   96                     ]).   97
   98/** <module> Secure Socket Layer (SSL) library
   99
  100An SSL server and client can be built with the (abstracted)
  101predicate calls from the table below.  The `tcp_` predicates
  102are provided by library(socket).  The predicate ssl_context/3
  103defines properties of the SSL connection, while ssl_negotiate/5
  104establishes the SSL connection based on the wire streams created
  105by the TCP predicates and the context.
  106
  107        | *The SSL Server*      | *The SSL Client*      |
  108        | ssl_context/3         | ssl_context/3         |
  109        | tcp_socket/1          |                       |
  110        | tcp_accept/3          | tcp_connect/3         |
  111        | tcp_open_socket/3     | stream_pair/3         |
  112        | ssl_negotiate/5       | ssl_negotiate/5       |
  113
  114The library is abstracted to communication over streams, and is not
  115reliant on those streams being directly attached to sockets. The `tcp_`
  116calls here are simply the most common way to use the library. Other
  117two-way communication channels such as (named), pipes can just as
  118easily be used.
  119
  120@see library(socket), library(http/http_open), library(crypto)
  121*/
  122
  123:- setting(secure_ciphers, atom,
  124           'EECDH+AESGCM:EDH+AESGCM:EECDH+AES256:EDH+AES256:EECDH+CHACHA20:EDH+CHACHA20',
  125           "Default set of ciphers considered secure").  126
  127%!  ssl_context(+Role, -SSL, :Options) is det.
  128%
  129%   Create an  SSL context.  The context  defines several properties
  130%   of  the   SSL  connection  such  as   involved  keys,  preferred
  131%   encryption, and passwords. After  establishing a context, an SSL
  132%   connection can be negotiated  using ssl_negotiate/5, turning two
  133%   arbitrary  plain Prolog  streams into  encrypted streams.   This
  134%   predicate processes the options below.
  135%
  136%     * host(+HostName)
  137%     For the client, the host to which it connects. This option
  138%     _should_ be specified when Role is `client`. Otherwise,
  139%     certificate verification may fail when negotiating a
  140%     secure connection.
  141%     * certificate_file(+FileName)
  142%     Specify where the certificate file can be found. This can be the
  143%     same as the key_file(+FileName) option.  A server _must_ have at
  144%     least one certificate before clients can connect. A client
  145%     _must_ have a certificate only if the server demands the client
  146%     to identify itself with a client certificate using the
  147%     peer_cert(true) option. If a certificate is provided, it is
  148%     necessary to also provide a matching _private key_ via the
  149%     key_file/1 option. To configure multiple certificates, use the
  150%     option certificate_key_pairs/1 instead. Alternatively, use
  151%     ssl_add_certificate_key/4 to add certificates and keys to an
  152%     existing context.
  153%     * key_file(+FileName)
  154%     Specify where the private key that matches the certificate can
  155%     be found.  If the key is encrypted with a password, this must
  156%     be supplied using the password(+Text) or
  157%     =|pem_password_hook(:Goal)|= option.
  158%     * certificate_key_pairs(+Pairs)
  159%     Alternative method for specifying certificates and keys. The
  160%     argument is a list of _pairs_ of the form Certificate-Key,
  161%     where each component is a string or an atom that holds,
  162%     respectively, the PEM-encoded certificate and key. To each
  163%     certificate, further certificates of the chain can be
  164%     appended. Multiple types of certificates can be present at
  165%     the same time to enable different ciphers. Using multiple
  166%     certificate types with completely independent certificate
  167%     chains requires OpenSSL 1.0.2 or greater.
  168%     * password(+Text)
  169%     Specify the password the private key is protected with (if
  170%     any). If you do not want to store the password you can also
  171%     specify an application defined handler to return the password
  172%     (see next option).  Text is either an atom or string.  Using
  173%     a string is preferred as strings are volatile and local
  174%     resources.
  175%     * pem_password_hook(:Goal)
  176%     In case a password is required to access the private key the
  177%     supplied predicate will be called to fetch it. The hook is
  178%     called as call(Goal, +SSL, -Password) and typically unifies
  179%     `Password` with a _string_ containing the password.
  180%     * require_crl(+Boolean)
  181%     If true (default is false), then all certificates will be
  182%     considered invalid unless they can be verified as not being
  183%     revoked. You can do this explicity by passing a list of CRL
  184%     filenames via the crl/1 option, or by doing it yourself in
  185%     the cert_verify_hook. If you specify require_crl(true) and
  186%     provide neither of these options, verification will necessarily
  187%     fail
  188%     * crl(+ListOfFileNames)
  189%     Provide a list of filenames of PEM-encoded CRLs that will be
  190%     given to the context to attempt to establish that a chain of
  191%     certificates is not revoked. You must also set require_crl(true)
  192%     if you want CRLs to actually be checked by OpenSSL.
  193%     * cacert_file(+FileName)
  194%     Deprecated. Use cacerts/1 instead.
  195%     Specify a file containing certificate keys of _trusted_
  196%     certificates. The peer is trusted if its certificate is
  197%     signed (ultimately) by one of the provided certificates. Using
  198%     the FileName `system(root_certificates)` uses a list of
  199%     trusted root certificates as provided by the OS. See
  200%     system_root_certificates/1 for details.
  201%     * cacerts(+ListOfCATerms)
  202%     Specify a list of sources of _trusted_ certificates.
  203%     Each element in the list should be one of the following:
  204%        * file(Filename): A file containing one or more PEM-encoded
  205%          certificates
  206%        * certificate(Blob): A certificate blob
  207%        * system(root_certificates): A special term which refers to
  208%          the certificates trusted by the host OS.
  209%
  210%     Additional verification of the peer certificate as well as
  211%     accepting certificates that are not trusted by the given set
  212%     can be realised using the hook
  213%     cert_verify_hook(:Goal).
  214%     * cert_verify_hook(:Goal)
  215%     The predicate ssl_negotiate/5 calls Goal as follows:
  216%
  217%       ==
  218%       call(Goal, +SSL,
  219%            +ProblemCertificate, +AllCertificates, +FirstCertificate,
  220%            +Error)
  221%       ==
  222%
  223%     In case the certificate was verified by one of the provided
  224%     certifications from the `cacert_file` option, Error is unified
  225%     with the atom `verified`. Otherwise it contains the error
  226%     string passed from OpenSSL. Access will be granted iff the
  227%     predicate succeeds. See load_certificate/2 for a description
  228%     of the certificate terms. See cert_accept_any/5 for a dummy
  229%     implementation that accepts any certificate.
  230%     * cipher_list(+Atom)
  231%     Specify a cipher preference list (one or more cipher strings
  232%     separated by colons, commas or spaces). See ssl_secure_ciphers/1.
  233%     * ecdh_curve(+Atom)
  234%     Specify a curve for ECDHE ciphers. If this option is not
  235%     specified, the OpenSSL default parameters are used.  With
  236%     OpenSSL prior to 1.1.0, `prime256v1` is used by default.
  237%     * peer_cert(+Boolean)
  238%     Trigger the request of our peer's certificate while
  239%     establishing the SSL layer. This option is automatically
  240%     turned on in a client SSL socket.  It can be used in a server
  241%     to ask the client to identify itself using an SSL certificate.
  242%     * close_parent(+Boolean)
  243%     If `true`, close the raw streams if the SSL streams are closed.
  244%     Default is `false`.
  245%     * close_notify(+Boolean)
  246%     If `true` (default is `false`), the server sends TLS
  247%     `close_notify` when closing the connection. In addition,
  248%     this mitigates _truncation attacks_ for both client and
  249%     server role: If EOF is encountered without having received a
  250%     TLS shutdown, an exception is raised. Well-designed
  251%     protocols are self-terminating, and this attack is therefore
  252%     very rarely a concern.
  253%     * min_protocol_version(+Atom)
  254%     Set the _minimum_ protocol version that can be negotiated.
  255%     Atom is one of `sslv3`, `tlsv1`, `tlsv1_1`, `tlsv1_2` and
  256%     `tlsv1_3`. This option is available with OpenSSL 1.1.0 and
  257%     later, and should be used instead of `disable_ssl_methods/1`.
  258%     * max_protocol_version(+Atom)
  259%     Set the _maximum_ protocol version that can be negotiated.
  260%     Atom is one of `sslv3`, `tlsv1`, `tlsv1_1`, `tlsv1_2` and
  261%     `tlsv1_3`. This option is available with OpenSSL 1.1.0 and
  262%     later, and should be used instead of `disable_ssl_methods/1`.
  263%     * disable_ssl_methods(+List)
  264%     A list of methods to disable. Unsupported methods will be
  265%     ignored. Methods include `sslv2`, `sslv3`, `sslv23`,
  266%     `tlsv1`, `tlsv1_1` and `tlsv1_2`. This option is deprecated
  267%     starting with OpenSSL 1.1.0. Use min_protocol_version/1 and
  268%     max_protocol_version/1 instead.
  269%     * ssl_method(+Method)
  270%     Specify the explicit Method to use when negotiating. For
  271%     allowed values, see the list for `disable_ssl_methods` above.
  272%     Using this option is discouraged. When using OpenSSL 1.1.0
  273%     or later, this option is ignored, and a version-flexible method
  274%     is used to negotiate the connection. Using version-specific
  275%     methods is deprecated in recent OpenSSL versions, and this
  276%     option will become obsolete and ignored in the future.
  277%     * sni_hook(:Goal)
  278%     This option provides Server Name Indication (SNI) for SSL
  279%     servers. This means that depending on the host to which a
  280%     client connects, different options (certificates etc.) can
  281%     be used for the server. This TLS extension allows you to host
  282%     different domains using the same IP address and physical
  283%     machine. When a TLS connection is negotiated with a client
  284%     that has provided a host name via SNI, the hook is called as
  285%     follows:
  286%
  287%     ==
  288%     call(Goal, +SSL0, +HostName, -SSL)
  289%     ==
  290%
  291%     Given the current context SSL0, and the host name of the
  292%     client request, the predicate computes SSL which is used as
  293%     the context for negotiating the connection. The first solution
  294%     is used.  If the predicate fails, the default options are
  295%     used, which are those of the encompassing ssl_context/3
  296%     call. In that case, if no default certificate and key are
  297%     specified, the client connection is rejected.
  298%     * alpn_protocols(+ListOfProtoIdentifiers)
  299%     Provide a list of acceptable ALPN protocol identifiers as atoms.
  300%     ALPN support requires OpenSSL 1.0.2 or greater.
  301%     * alpn_protocol_hook(:Goal)
  302%     This options provides a callback for a server context to use to
  303%     select an ALPN protocol. It will be called as follows:
  304%
  305%     ===
  306%     call(Goal, +SSLCtx0, +ListOfClientProtocols, -SSLCtx1, -SelectedProtocol)
  307%     ===
  308%
  309%     If this option is unset and the `alpn_protocols/1` option is
  310%     set, then the first common protocol between client & server will
  311%     be selected.
  312%
  313%   @arg Role is one of `server` or `client` and denotes whether the
  314%   SSL  instance  will  have  a  server   or  client  role  in  the
  315%   established connection.
  316%   @arg SSL is a SWI-Prolog _blob_ of type `ssl_context`, i.e., the
  317%   type-test for an SSL context is `blob(SSL, ssl_context)`.
  318
  319ssl_context(Role, SSL, Module:Options) :-
  320    select_option(ssl_method(Method), Options, O1, sslv23),
  321    ssl_upgrade_legacy_options(O1, O2),
  322    (   select_option(cacerts(_), O2, _)
  323    ->  O3 = O2
  324    ;   O3 = [cacerts([system(root_certificates)])|O2]
  325    ),
  326    '_ssl_context'(Role, SSL, Module:O3, Method).
  327
  328%!  ssl_upgrade_legacy_options(+OptionsIn, -Options) is det.
  329%
  330%   Handle deprecated cacert_file(Spec) option and  map   it  to the new
  331%   cacerts(+List) option.
  332
  333ssl_upgrade_legacy_options(O1, O4) :-
  334    select_option(cacert_file(CACertFile), O1, O2),
  335    !,
  336    print_message(warning, deprecated(ssl_option(cacert_file(CACertFile)))),
  337    (   atom(CACertFile)
  338    ->  Term = file(CACertFile)
  339    ;   Term = CACertFile                % e.g., system(root_certificates)
  340    ),
  341    select_option(cacerts(CACerts), O2, O3, []),
  342    ssl_upgrade_legacy_options([cacerts([Term|CACerts])|O3], O4).
  343ssl_upgrade_legacy_options(Options, Options).
  344
  345
  346%!  ssl_add_certificate_key(+SSL0, +Certificate, +Key, -SSL)
  347%
  348%   Add an additional certificate/key pair to SSL0, yielding SSL.
  349%   Certificate and Key are either strings or atoms that hold the
  350%   PEM-encoded certificate plus certificate chain and private key,
  351%   respectively. Using strings is preferred for security reasons.
  352%
  353%   This predicate allows dual-stack RSA and ECDSA servers (for
  354%   example), and is an alternative for using the
  355%   `certificate_key_pairs/1` option. As of OpenSSL 1.0.2, multiple
  356%   certificate types with completely independent certificate chains
  357%   are supported. If a certificate of the same type is added
  358%   repeatedly to a context, the result is undefined. Currently, up to
  359%   12 additional certificates of different types are admissible.
  360
  361ssl_add_certificate_key(SSL0, Cert, Key, SSL) :-
  362    ssl_copy_context(SSL0, SSL),
  363    '_ssl_add_certificate_key'(SSL, Cert, Key).
  364
  365%!  ssl_set_options(+SSL0, -SSL, +Options)
  366%
  367%   SSL is the same as SSL0, except for the options specified in
  368%   Options.  The following options are supported: close_notify/1,
  369%   close_parent/1, host/1, peer_cert/1, ecdh_curve/1,
  370%   min_protocol_version/1, max_protocol_version/1,
  371%   disable_ssl_methods/1, sni_hook/1, cert_verify_hook/1,
  372%   alpn_protocols/1, and alpn_protocol_hook/1. See ssl_context/3 for
  373%   more information about these options. This predicate allows you to
  374%   tweak existing SSL contexts, which can be useful in hooks when
  375%   creating servers with the HTTP infrastructure.
  376
  377ssl_set_options(SSL0, SSL, Options) :-
  378    ssl_copy_context(SSL0, SSL),
  379    '_ssl_set_options'(SSL, Options).
  380
  381%!  ssl_property(+SSL, ?Property) is semidet.
  382%
  383%   True when Property is a property of SSL. Defined properties are:
  384%
  385%     - close_parent(?Bool)
  386%
  387%   @tbd This version is a very   minimal  implementation of the generic
  388%   property interface. Future versions  will   add  more properties and
  389%   non-determinism.
  390
  391%!  ssl_negotiate(+SSL,
  392%!                +PlainRead, +PlainWrite,
  393%!                -SSLRead, -SSLWrite) is det.
  394%
  395%   Once a connection is established and a read/write stream pair is
  396%   available, (PlainRead and PlainWrite),  this   predicate  can be
  397%   called to negotiate an SSL  session   over  the  streams. If the
  398%   negotiation is successful, SSLRead and SSLWrite are returned.
  399%
  400%   After a successful handshake and finishing the communication the
  401%   user  must  close  SSLRead  and   SSLWrite,  for  example  using
  402%   call_cleanup(close(SSLWrite),  close(SSLRead)).  If    the   SSL
  403%   _context_   (created   with   ssl_context/3   has   the   option
  404%   close_parent(true)  (default  `false`),  closing    SSLRead  and
  405%   SSLWrite also closes  the  original   PlainRead  and  PlainWrite
  406%   streams. Otherwise these must be closed explicitly by the user.
  407%
  408%   @error ssl_error(Code, LibName, FuncName, Reason) is raised
  409%   if the negotiation fails. The streams PlainRead and PlainWrite
  410%   are *not* closed, but an unknown amount of data may have been
  411%   read and written.
  412
  413%!  ssl_peer_certificate(+Stream, -Certificate) is semidet.
  414%
  415%   True if the peer certificate  is   provided  (this is always the
  416%   case for a client connection) and   Certificate unifies with the
  417%   peer certificate. The example below  uses   this  to  obtain the
  418%   _Common Name_ of the peer  after   establishing  an https client
  419%   connection:
  420%
  421%     ==
  422%       http_open(HTTPS_url, In, []),
  423%       ssl_peer_certificate(In, Cert),
  424%       memberchk(subject(Subject), Cert),
  425%       memberchk('CN' = CommonName), Subject)
  426%     ==
  427
  428%!  ssl_peer_certificate_chain(+Stream, -Certificates) is det.
  429%
  430%   Certificates  is the  certificate  chain provided  by the  peer,
  431%   represented as a list of certificates.
  432
  433%!  ssl_session(+Stream, -Session) is det.
  434%
  435%   Retrieves (debugging) properties from the SSL context associated
  436%   with Stream. If Stream  is  not   an  SSL  stream, the predicate
  437%   raises  a  domain  error.  Session  is  a  list  of  properties,
  438%   containing the members described below.   Except  for `Version`,
  439%   all information are byte arrays that   are represented as Prolog
  440%   strings holding characters in the range 0..255.
  441%
  442%     * ssl_version(Version)
  443%     The negotiated version of the session as an integer.
  444%     * cipher(Cipher)
  445%     The negotiated cipher for this connection.
  446%     * session_key(Key)
  447%     The key material used in SSLv2 connections (if present).
  448%     * master_key(Key)
  449%     The key material comprising the master secret. This is
  450%     generated from the server_random, client_random and pre-master
  451%     key.
  452%     * client_random(Random)
  453%     The random data selected by the client during handshaking.
  454%     * server_random(Random)
  455%     The random data selected by the server during handshaking.
  456%     * session_id(SessionId)
  457%     The SSLv3 session ID. Note that if ECDHE is being used (which
  458%     is the default for newer versions of OpenSSL), this data will
  459%     not actually be sent to the server.
  460%     * alpn_protocol(Protocol)
  461%     The negotiated ALPN protocol, if supported. If no protocol was
  462%     negotiated, this will be an empty string.
  463
  464%!  load_certificate(+Stream, -Certificate) is det.
  465%
  466%   Loads a certificate from a PEM- or DER-encoded stream, returning
  467%   a certificate. The fields of the certificate can be inspected
  468%   using certificate_field(+Certificate, ?Field).
  469%
  470%   Note that the OpenSSL `CA.pl`  utility creates certificates that
  471%   have a human readable textual representation in front of the PEM
  472%   representation. You can  use  the  following   to  skip  to  the
  473%   certificate if you know it is a PEM certificate:
  474%
  475%     ==
  476%     skip_to_pem_cert(In) :-
  477%           repeat,
  478%           (   peek_char(In, '-')
  479%           ->  !
  480%           ;   skip(In, 0'\n),
  481%               at_end_of_stream(In), !
  482%           ).
  483%     ==
  484
  485%!  write_certificate(+Stream, +Certificate, +Options) is det.
  486%
  487%   Writes a certificate to the stream Stream. Options is reserved
  488%   for future use.
  489
  490%!  load_crl(+Stream, -CRL) is det.
  491%
  492%   Loads a CRL from a PEM- or  DER-encoded stream, returning a term
  493%   containing  terms  hash/1,   signature/1,    issuer_name/1   and
  494%   revocations/1,  which  is  a  list   of  revoked/2  terms.  Each
  495%   revoked/2 term is of the form revoked(+Serial, DateOfRevocation)
  496
  497%!  system_root_certificates(-List) is det.
  498%
  499%   List is a list of trusted root   certificates as provided by the
  500%   OS. This is the list used by ssl_context/3 when using the option
  501%   `system(root_certificates)`.  The list is obtained using an OS
  502%   specific process.  The current implementation is as follows:
  503%
  504%       - On Windows, CertOpenSystemStore() is used to import
  505%         the `"ROOT"` certificates from the OS.
  506%       - On MacOSX, the trusted keys are loaded from the
  507%         _SystemRootCertificates_ key chain.  The Apple API
  508%         for this requires the SSL interface to be compiled
  509%         with an XCode compiler, i.e., *not* with native gcc.
  510%       - Otherwise, certificates are loaded from a file defined
  511%         by the Prolog flag `system_cacert_filename`.  The initial
  512%         value of this flag is operating system dependent.  For
  513%         security reasons, the flag can only be set prior to using
  514%         the SSL library.  For example:
  515%
  516%           ==
  517%           :- use_module(library(ssl)).
  518%           :- set_prolog_flag(system_cacert_filename,
  519%                              '/home/jan/ssl/ca-bundle.crt').
  520%           ==
  521
  522%!  load_private_key(+Stream, +Password, -PrivateKey) is det.
  523%
  524%   Load  a private  key PrivateKey  from the  given stream  Stream,
  525%   using Password to decrypt the key  if it is encrypted. Note that
  526%   the  password  is  currently   only  supported  for  PEM  files.
  527%   DER-encoded keys which are password protected will not load. The
  528%   key must be an RSA or EC key. DH and DSA keys are not supported,
  529%   and PrivateKey will  be bound to an atom (dh_key  or dsa_key) if
  530%   you  try and  load such  a  key.  Otherwise  PrivateKey will  be
  531%   unified with private_key(KeyTerm) where KeyTerm is an rsa/8 term
  532%   representing an RSA key, or ec/3 for EC keys.
  533
  534%!  load_public_key(+Stream, -PublicKey) is det.
  535%
  536%   Load  a  public key  PublicKey  from  the given  stream  Stream.
  537%   Supports loading both DER- and PEM-encoded keys. The key must be
  538%   an  RSA or  EC  key. DH  and  DSA keys  are  not supported,  and
  539%   PublicKey will  be bound to an  atom (dh_key or dsa_key)  if you
  540%   try and  load such  a key. Otherwise  PublicKey will  be unified
  541%   with  public_key(KeyTerm)   where  KeyTerm  is  an   rsa/8  term
  542%   representing an RSA key, or ec/3 for EC keys.
  543
  544
  545%!  cert_accept_any(+SSL,
  546%!                  +ProblemCertificate, +AllCertificates, +FirstCertificate,
  547%!                  +Error) is det.
  548%
  549%   Implementation  for  the  hook   `cert_verify_hook(:Hook)`  that
  550%   accepts _any_ certificate. This is   intended for http_open/3 if
  551%   no certificate verification is desired as illustrated below.
  552%
  553%     ==
  554%       http_open('https:/...', In,
  555%                 [ cert_verify_hook(cert_accept_any)
  556%                 ])
  557%     ==
  558
  559%!  same_certificate(+CertificateA,
  560%!                   +CertificateB).
  561%
  562%   True if CertificateA is logically the same as CertificateB, even if
  563%   they are stored in different blobs
  564
  565%!  verify_certificate_issuer(+Certificate,
  566%!			      +Issuer).
  567%
  568%   True if Certificate is a certificate which was issued by the
  569%   certificate Issuer.
  570
  571%!  verify_certificate(+Certificate,
  572%!		       +AuxiliaryCertificates,
  573%!		       +TrustedCertificates).
  574%
  575%   True if it is possible to build a chain of trust from Certificate to
  576%   one of the certificates in TrustedCertificates, optionally using the
  577%   (untrusted) certificates in AuxiliaryCertificates to complete the
  578%   chain.
  579%   To use the system built-in trust store, specify the special term
  580%   system(root_certificates) for TrustedCertificates.
  581
  582%!  certificate_field(+Certificate,
  583%!		      ?Field) is nondet.
  584%
  585%   Retrieve the field matching Field from Certificate. May be
  586%   one of the following:
  587%     * subject/1 to retrieve the subject
  588%     * issuer/1  to retrieve the issuer's subject
  589%     * version/1  to retrieve the version
  590%     * serial/1  to retrieve the serial number
  591%     * not_before/1 to retrieve the start date
  592%     * not_after/1  to retrieve the expiry date
  593%     * public_key/1 to retrieve the public key
  594%     * crls/1 to retrieve a list of the CRLs
  595%     * sans/1 to retrieve a list of the Subject Alternative Names
  596%     * signature/1 to retrieve the certificate signature
  597%     * signature_algorithm/1 to retrieve the signing algorithm
  598%     * hash/1 to retrieve the certificate hash
  599%     * to_be_signed/1 to retrieve the data on the certificate which
  600%        must be signed
  601
  602
  603
  604cert_accept_any(_SSL,
  605                _ProblemCertificate, _AllCertificates, _FirstCertificate,
  606                _Error).
  607
  608%!  ssl_secure_ciphers(-Ciphers:atom) is det.
  609%
  610%   Ciphers is a  secure cipher preference list that can  be used in the
  611%   cipher_list/1 option of ssl_context/3.
  612%
  613%   Secure ciphers must guarantee forward secrecy, and must mitigate all
  614%   known critical attacks.  As of  2018, using these ciphers allows you
  615%   to obtain grade A on  https://www.ssllabs.com. For A+, you must also
  616%   enable HTTP Strict  Transport Security (HSTS) by  sending a suitable
  617%   header field in replies.
  618%
  619%   Note that obsolete ciphers *must* be   disabled  to reliably prevent
  620%   protocol downgrade attacks.
  621%
  622%   The Ciphers list is read from   the setting `ssl:secure_ciphers` and
  623%   can be controlled using  set_setting/2   and  other  predicates from
  624%   library(settings).
  625%
  626%   *BEWARE*: This list must be changed when attacks on these ciphers
  627%             become known! Keep an eye on this setting and adapt it
  628%             as necessary in the future.
  629
  630ssl_secure_ciphers(Cs) :-
  631    setting(secure_ciphers, Cs).
  632
  633
  634                 /*******************************
  635                 *           MESSAGES           *
  636                 *******************************/
  637
  638:- multifile
  639    prolog:error_message//1,
  640    prolog:deprecated//1.  641
  642prolog:error_message(ssl_error(ID, _Library, Function, Reason)) -->
  643    [ 'SSL(~w) ~w: ~w'-[ID, Function, Reason] ].
  644prolog:deprecated(ssl_option(cacert_file(CACertFile))) -->
  645    [ 'SSL: cacert_file(~q) has need deprecated.'-[CACertFile],
  646      'Please use the option cacerts(List) instead'
  647    ]