View source with raw comments or as raw
   1/*  Part of SWI-Prolog
   2
   3    Author:        Matt Lilley and Markus Triska
   4    WWW:           http://www.swi-prolog.org
   5    Copyright (c)  2004-2017, SWI-Prolog Foundation
   6                              VU University Amsterdam
   7    All rights reserved.
   8
   9    Redistribution and use in source and binary forms, with or without
  10    modification, are permitted provided that the following conditions
  11    are met:
  12
  13    1. Redistributions of source code must retain the above copyright
  14       notice, this list of conditions and the following disclaimer.
  15
  16    2. Redistributions in binary form must reproduce the above copyright
  17       notice, this list of conditions and the following disclaimer in
  18       the documentation and/or other materials provided with the
  19       distribution.
  20
  21    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24    FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25    COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  28    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  29    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  31    ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32    POSSIBILITY OF SUCH DAMAGE.
  33*/
  34
  35:- module(crypto,
  36          [ crypto_data_hash/3,         % +Data, -Hash, +Options
  37            crypto_file_hash/3,         % +File, -Hash, +Options
  38            crypto_context_new/2,       % -Context, +Options
  39            crypto_data_context/3,      % +Data, +C0, -C
  40            crypto_context_hash/2,      % +Context, -Hash
  41            crypto_open_hash_stream/3,  % +InStream, -HashStream, +Options
  42            crypto_stream_hash/2,       % +HashStream, -Hash
  43            ecdsa_sign/4,               % +Key, +Data, -Signature, +Options
  44            ecdsa_verify/4,             % +Key, +Data, +Signature, +Options
  45            evp_decrypt/6,              % +CipherText, +Algorithm, +Key, +IV, -PlainText, +Options
  46            evp_encrypt/6,              % +PlainText, +Algorithm, +Key, +IV, -CipherText, +Options
  47            hex_bytes/2,                % ?Hex, ?List
  48            rsa_private_decrypt/4,      % +Key, +Ciphertext, -Plaintext, +Enc
  49            rsa_private_encrypt/4,      % +Key, +Plaintext, -Ciphertext, +Enc
  50            rsa_public_decrypt/4,       % +Key, +Ciphertext, -Plaintext, +Enc
  51            rsa_public_encrypt/4,       % +Key, +Plaintext, -Ciphertext, +Enc
  52            rsa_sign/4,                 % +Key, +Data, -Signature, +Options
  53            rsa_verify/4                % +Key, +Data, +Signature, +Options
  54          ]).
  55:- use_module(library(option)).
  56
  57:- use_foreign_library(foreign(crypto4pl)).
  58
  59
  60/** <module> Cryptography and authentication library
  61
  62This library provides bindings  to  functionality   of  OpenSSL  that is
  63related to cryptography and authentication,   not  necessarily involving
  64connections, sockets or streams.
  65
  66The  hash functionality  of this  library subsumes  and extends  that of
  67`library(sha)`, `library(hash_stream)` and `library(md5)` by providing a
  68unified interface to all available digest algorithms.
  69
  70The underlying  OpenSSL library  (`libcrypto`) is dynamically  loaded if
  71_either_ `library(crypto)`  or `library(ssl)` are loaded.  Therefore, if
  72your application uses `library(ssl)`,  you can use `library(crypto)` for
  73hashing without increasing the memory  footprint of your application. In
  74other cases, the specialised hashing  libraries are more lightweight but
  75less general alternatives to `library(crypto)`.
  76
  77@author Matt Lilley
  78@author [Markus Triska](https://www.metalevel.at)
  79*/
  80
  81%%  crypto_data_hash(+Data, -Hash, +Options) is det
  82%
  83%   Hash is the hash of Data. The conversion is controlled
  84%   by Options:
  85%
  86%    * algorithm(+Algorithm)
  87%    One of =md5=, =sha1=, =sha224=, =sha256= (default), =sha384=,
  88%    =sha512=, =blake2s256= or =blake2b512=. The =BLAKE= digest
  89%    algorithms require OpenSSL 1.1.0 or greater.
  90%    * encoding(+Encoding)
  91%    If Data is a sequence of character _codes_, this must be
  92%    translated into a sequence of _bytes_, because that is what
  93%    the hashing requires.  The default encoding is =utf8=.  The
  94%    other meaningful value is =octet=, claiming that Data contains
  95%    raw bytes.
  96%    * hmac(+Key)
  97%    If this option is specified, a _hash-based message authentication
  98%    code_ (HMAC) is computed, using the specified Key which is either
  99%    an atom or string. Any of the available digest algorithms can be
 100%    used with this option. The cryptographic strength of the HMAC
 101%    depends on that of the chosen algorithm and also on the key. This
 102%    option requires OpenSSL 1.1.0 or greater.
 103%
 104%  @param Data is either an atom, string or code-list
 105%  @param Hash is an atom that represents the hash.
 106%
 107%  @see hex_bytes/2 for conversion between hashes and lists.
 108
 109crypto_data_hash(Data, Hash, Options) :-
 110    crypto_context_new(Context0, Options),
 111    crypto_data_context(Data, Context0, Context),
 112    crypto_context_hash(Context, Hash).
 113
 114%!  crypto_file_hash(+File, -Hash, +Options) is det.
 115%
 116%   True if  Hash is the hash  of the content of  File. For Options,
 117%   see crypto_data_hash/3.
 118
 119crypto_file_hash(File, Hash, Options) :-
 120    setup_call_cleanup(open(File, read, In, [type(binary)]),
 121                       crypto_stream_hash(In, Hash, Options),
 122                       close(In)).
 123
 124crypto_stream_hash(Stream, Hash, Options) :-
 125    crypto_context_new(Context0, Options),
 126    update_hash(Stream, Context0, Context),
 127    crypto_context_hash(Context, Hash).
 128
 129update_hash(In, Context0, Context) :-
 130    (   at_end_of_stream(In)
 131    ->  Context = Context0
 132    ;   read_pending_codes(In, Data, []),
 133        crypto_data_context(Data, Context0, Context1),
 134        update_hash(In, Context1, Context)
 135    ).
 136
 137
 138%!  crypto_context_new(-Context, +Options) is det.
 139%
 140%   Context is  unified with  the empty  context, taking  into account
 141%   Options.  The  context can be used  in crypto_data_context/3.  For
 142%   Options, see crypto_data_hash/3.
 143%
 144%   @param Context is an opaque pure  Prolog term that is subject to
 145%          garbage collection.
 146
 147%!  crypto_data_context(+Data, +Context0, -Context) is det
 148%
 149%   Context0 is an existing computation  context, and Context is the
 150%   new context  after hashing  Data in  addition to  the previously
 151%   hashed data.  Context0 may be  produced by a prior invocation of
 152%   either crypto_context_new/2 or crypto_data_context/3 itself.
 153%
 154%   This predicate allows a hash to be computed in chunks, which may
 155%   be important while working  with Metalink (RFC 5854), BitTorrent
 156%   or similar technologies, or simply with big files.
 157
 158crypto_data_context(Data, Context0, Context) :-
 159    '_crypto_context_copy'(Context0, Context),
 160    '_crypto_update_context'(Data, Context).
 161
 162
 163%!  crypto_context_hash(+Context, -Hash)
 164%
 165%   Obtain the  hash code of  Context. Hash is an  atom representing
 166%   the hash code  that is associated with the current  state of the
 167%   computation context Context.
 168
 169crypto_context_hash(Context, Hash) :-
 170    '_crypto_context_copy'(Context, Copy),
 171    '_crypto_context_hash'(Copy, List),
 172    hex_bytes(Hash, List).
 173
 174%!  crypto_open_hash_stream(+OrgStream, -HashStream, +Options) is det.
 175%
 176%   Open a filter stream on OrgStream  that maintains a hash. The hash
 177%   can be retrieved at any time using crypto_stream_hash/2. Available
 178%   Options in addition to those of crypto_data_hash/3 are:
 179%
 180%     - close_parent(+Bool)
 181%     If `true` (default), closing the filter stream also closes the
 182%     original (parent) stream.
 183
 184crypto_open_hash_stream(OrgStream, HashStream, Options) :-
 185    crypto_context_new(Context, Options),
 186    '_crypto_open_hash_stream'(OrgStream, HashStream, Context).
 187
 188
 189%!  crypto_stream_hash(+HashStream, -Hash) is det.
 190%
 191%   Unify  Hash with  a hash  for  the bytes  sent to  or read  from
 192%   HashStream.  Note  that  the  hash is  computed  on  the  stream
 193%   buffers. If the stream is an  output stream, it is first flushed
 194%   and the Digest  represents the hash at the  current location. If
 195%   the stream is an input stream  the Digest represents the hash of
 196%   the processed input including the already buffered data.
 197
 198crypto_stream_hash(Stream, Hash) :-
 199    '_crypto_stream_context'(Stream, Context),
 200    crypto_context_hash(Context, Hash).
 201
 202%!  ecdsa_sign(+Key, +Data, -Signature, +Options)
 203%
 204%   Create  an ECDSA  signature for  Data with  EC private  key Key.
 205%   Among the most  common cases is signing a hash  that was created
 206%   with crypto_data_hash/3 or other predicates of this library. For
 207%   this reason, the  default encoding (`hex`) assumes  that Data is
 208%   an atom,  string, character list  or code list  representing the
 209%   data in hexadecimal notation. See rsa_sign/4 for an example.
 210%
 211%   Options:
 212%
 213%     - encoding(+Encoding)
 214%     Encoding to use for Data.  Default is `hex`.  Alternatives
 215%     are `octet`, `utf8` and `text`.
 216
 217ecdsa_sign(private_key(ec(Private,Public0,Curve)), Data0, Signature, Options) :-
 218    option(encoding(Enc0), Options, hex),
 219    hex_encoding(Enc0, Data0, Enc, Data),
 220    hex_bytes(Public0, Public),
 221    '_crypto_ecdsa_sign'(ec(Private,Public,Curve), Data, Enc, Signature).
 222
 223hex_encoding(hex, Data0, octet, Data) :- !,
 224    hex_bytes(Data0, Data).
 225hex_encoding(Enc, Data, Enc, Data).
 226
 227%!  ecdsa_verify(+Key, +Data, +Signature, +Options) is semidet.
 228%
 229%   True iff Signature can be verified as the ECDSA signature for
 230%   Data, using the EC public key Key.
 231%
 232%   Options:
 233%
 234%     - encoding(+Encoding)
 235%     Encoding to use for Data.  Default is `hex`.  Alternatives
 236%     are `octet`, `utf8` and `text`.
 237
 238ecdsa_verify(public_key(ec(Private,Public0,Curve)), Data0, Signature0, Options) :-
 239    option(encoding(Enc0), Options, hex),
 240    hex_encoding(Enc0, Data0, Enc, Data),
 241    hex_bytes(Public0, Public),
 242    hex_bytes(Signature0, Signature),
 243    '_crypto_ecdsa_verify'(ec(Private,Public,Curve), Data, Enc, Signature).
 244
 245
 246%!  hex_bytes(?Hex, ?List) is det.
 247%
 248%   Relation between a hexadecimal sequence  and a list of bytes.  Hex
 249%   is  an atom,  string,  list  of characters  or  list  of codes  in
 250%   hexadecimal  encoding.   This  is  the  format  that  is  used  by
 251%   crypto_data_hash/3 and  related predicates to  represent _hashes_.
 252%   Bytes is a list of _integers_ between 0 and 255 that represent the
 253%   sequence as a  list of bytes.  At least one  of the arguments must
 254%   be instantiated. When converting List  _to_ Hex, an _atom_ is used
 255%   to represent the sequence of hexadecimal digits.
 256%
 257%   Example:
 258%
 259%   ==
 260%   ?- hex_bytes('501ACE', Bs).
 261%   Bs = [80, 26, 206].
 262%   ==
 263
 264hex_bytes(Hs, Bytes) :-
 265    (   ground(Hs) ->
 266        string_chars(Hs, Chars),
 267        (   phrase(hex_bytes(Chars), Bytes)
 268        ->  true
 269        ;   domain_error(hex_encoding, Hs)
 270        )
 271    ;   must_be(list(between(0,255)), Bytes),
 272        phrase(bytes_hex(Bytes), Chars),
 273        atom_chars(Hs, Chars)
 274    ).
 275
 276hex_bytes([]) --> [].
 277hex_bytes([H1,H2|Hs]) --> [Byte],
 278    { char_type(H1, xdigit(High)),
 279      char_type(H2, xdigit(Low)),
 280      Byte is High*16 + Low },
 281    hex_bytes(Hs).
 282
 283bytes_hex([]) --> [].
 284bytes_hex([B|Bs]) -->
 285    { High is B>>4,
 286      Low is B /\ 0xf,
 287      char_type(C0, xdigit(High)),
 288      char_type(C1, xdigit(Low))
 289    },
 290    [C0,C1],
 291    bytes_hex(Bs).
 292
 293%!  rsa_private_decrypt(+PrivateKey, +CipherText, -PlainText, +Options) is det.
 294%!  rsa_private_encrypt(+PrivateKey, +PlainText, -CipherText, +Options) is det.
 295%!  rsa_public_decrypt(+PublicKey, +CipherText, -PlainText, +Options) is det.
 296%!  rsa_public_encrypt(+PublicKey, +PlainText, -CipherText, +Options) is det.
 297%
 298%   RSA Public key encryption and   decryption  primitives. A string
 299%   can be safely communicated by first   encrypting it and have the
 300%   peer decrypt it with the matching  key and predicate. The length
 301%   of the string is limited by  the   key  length.
 302%
 303%   Options:
 304%
 305%     - encoding(+Encoding)
 306%     Encoding to use for Data.  Default is `utf8`.  Alternatives
 307%     are `utf8` and `octet`.
 308%
 309%     - padding(+PaddingScheme)
 310%     Padding scheme to use.  Default is `pkcs1`.  Alternatives
 311%     are `pkcs1_oaep`, `sslv23` and `none`. Note that `none` should
 312%     only be used if you implement cryptographically sound padding
 313%     modes in your application code as encrypting unpadded data with
 314%     RSA is insecure
 315%
 316%   @see load_private_key/3, load_public_key/2 can be use to load
 317%   keys from a file.  The predicate load_certificate/2 can be used
 318%   to obtain the public key from a certificate.
 319%
 320%   @error ssl_error(Code, LibName, FuncName, Reason)   is raised if
 321%   there is an error, e.g., if the text is too long for the key.
 322
 323%!  rsa_sign(+Key, +Data, -Signature, +Options) is det.
 324%
 325%   Create an RSA signature for Data with private key Key.  Options:
 326%
 327%     - type(+Type)
 328%     SHA algorithm used to compute the digest.  Values are
 329%     `sha1` (default), `sha224`, `sha256`, `sha384` or `sha512`.
 330%
 331%     - encoding(+Encoding)
 332%     Encoding to use for Data.  Default is `hex`.  Alternatives
 333%     are `octet`, `utf8` and `text`.
 334%
 335%   This predicate can be used to compute a =|sha256WithRSAEncryption|=
 336%   signature as follows:
 337%
 338%     ```
 339%     sha256_with_rsa(PemKeyFile, Password, Data, Signature) :-
 340%         Algorithm = sha256,
 341%         read_key(PemKeyFile, Password, Key),
 342%         crypto_data_hash(Data, Hash, [algorithm(Algorithm),
 343%                                       encoding(octet)]),
 344%         rsa_sign(Key, Hash, Signature, [type(Algorithm)]).
 345%
 346%     read_key(File, Password, Key) :-
 347%         setup_call_cleanup(
 348%             open(File, read, In, [type(binary)]),
 349%             load_private_key(In, Password, Key),
 350%             close(In)).
 351%     ```
 352%
 353%   Note that a hash that is computed by crypto_data_hash/3 can be
 354%   directly used in rsa_sign/4 as well as ecdsa_sign/4.
 355
 356rsa_sign(Key, Data0, Signature, Options) :-
 357    option(type(Type), Options, sha1),
 358    option(encoding(Enc0), Options, hex),
 359    hex_encoding(Enc0, Data0, Enc, Data),
 360    rsa_sign(Key, Type, Enc, Data, Signature).
 361
 362
 363%!  rsa_verify(+Key, +Data, +Signature, +Options) is semidet.
 364%
 365%   Verify an RSA signature for Data with public key Key.
 366%
 367%   Options:
 368%
 369%     - type(+Type)
 370%     SHA algorithm used to compute the digest.  Values are
 371%     `sha1` (default), `sha224`, `sha256`, `sha384` or `sha512`.
 372%
 373%     - encoding(+Encoding)
 374%     Encoding to use for Data.  Default is `hex`.  Alternatives
 375%     are `octet`, `utf8` and `text`.
 376
 377rsa_verify(Key, Data0, Signature0, Options) :-
 378    option(type(Type), Options, sha1),
 379    option(encoding(Enc0), Options, hex),
 380    hex_encoding(Enc0, Data0, Enc, Data),
 381    hex_bytes(Signature0, Signature),
 382    rsa_verify(Key, Type, Enc, Data, Signature).
 383
 384%!  evp_decrypt(+CipherText,
 385%!              +Algorithm,
 386%!              +Key,
 387%!              +IV,
 388%!              -PlainText,
 389%!              +Options).
 390%
 391%   Decrypt  the  given  CipherText,  using    the  symmetric  algorithm
 392%   Algorithm, key Key, and iv IV,   to  give PlainText. CipherText, Key
 393%   and IV should all be strings, and   PlainText is created as a string
 394%   as well. Algorithm should be an algorithm which your copy of OpenSSL
 395%   knows about. Examples are:
 396%
 397%       * aes-128-cbc
 398%       * aes-256-cbc
 399%       * des3
 400%
 401%   If the IV is not  needed  for   your  decryption  algorithm (such as
 402%   aes-128-ecb) then any string can be provided   as it will be ignored
 403%   by the underlying implementation
 404%
 405%   Options:
 406%
 407%     - encoding(+Encoding)
 408%     Encoding to use for Data.  Default is `utf8`.  Alternatives
 409%     are `utf8` and `octet`.
 410%
 411%     - padding(+PaddingScheme)
 412%     Padding scheme to use.  Default is `block`.  You can disable padding
 413%     by supplying
 414%     `none` here.
 415%
 416%   Example of aes-128-cbc encryption:
 417%
 418%     ```
 419%     ?- evp_encrypt("this is some input", 'aes-128-cbc', "sixteenbyteofkey",
 420%                    "sixteenbytesofiv", CipherText, []),
 421%        evp_decrypt(CipherText, 'aes-128-cbc',
 422%                    "sixteenbyteofkey", "sixteenbytesofiv",
 423%                    RecoveredText, []).
 424%     CipherText = <binary string>
 425%     RecoveredText = "this is some input".
 426%     ```
 427
 428%!  evp_encrypt(+PlainText,
 429%!              +Algorithm,
 430%!              +Key,
 431%!              +IV,
 432%!              -CipherTExt,
 433%!              +Options).
 434%
 435%   Encrypt  the  given  PlainText,  using    the   symmetric  algorithm
 436%   Algorithm,  key  Key,  and  iv   IV,    to   give   CipherText.  See
 437%   evp_decrypt/6.
 438
 439                 /*******************************
 440                 *          Sandboxing          *
 441                 *******************************/
 442
 443:- multifile sandbox:safe_primitive/1.
 444
 445sandbox:safe_primitive(crypto:crypto_data_hash(_,_,_)).
 446sandbox:safe_primitive(crypto:crypto_data_context(_,_,_)).
 447sandbox:safe_primitive(crypto:crypto_context_new(_,_)).
 448sandbox:safe_primitive(crypto:crypto_context_hash(_,_)).
 449
 450                 /*******************************
 451                 *           MESSAGES           *
 452                 *******************************/
 453
 454:- multifile
 455    prolog:error_message//1.
 456
 457prolog:error_message(ssl_error(ID, _Library, Function, Reason)) -->
 458    [ 'SSL(~w) ~w: ~w'-[ID, Function, Reason] ].