diff options
author | Hans Nilsson <[email protected]> | 2018-09-13 12:15:40 +0200 |
---|---|---|
committer | Hans Nilsson <[email protected]> | 2018-09-13 12:15:40 +0200 |
commit | 9df71f46b41e34b0be5cd561533e2b3d3948dc57 (patch) | |
tree | db88bf06418a5b7cccd467fc86697144d3397094 /lib/crypto | |
parent | 6d665a8296999822e4d516343d0e21ed62e70b37 (diff) | |
parent | df39504bc6f9b106a20959b969b258db327261a5 (diff) | |
download | otp-9df71f46b41e34b0be5cd561533e2b3d3948dc57.tar.gz otp-9df71f46b41e34b0be5cd561533e2b3d3948dc57.tar.bz2 otp-9df71f46b41e34b0be5cd561533e2b3d3948dc57.zip |
Merge branch 'hans/crypto/doc/OTP-15134' into maint
* hans/crypto/doc/OTP-15134:
ssh: Use exported crypto types
public_key: Generate refman from types and specs
public_key: Rework -type and -spec Check existing specs with code and documentation and adjust. Prepare for doc generation
public_key: Setup for doc generation
public_key: Remove special type signature for one test
crypto: Add missing documentation for enable_fips_mode/1
crypto: Generate refman from types and specs and fix links in engine chapter for generated crypto module refman
crypto: Rework -type and -spec Check code and documentation and write -type/-spec or adjust existing. Prepare for doc generation
crypto: Setup for doc generation
crypto: A user's guide chapter on algorithm details Such as keylengths, blocksizes and IV lengths are hard to find otherwise
Diffstat (limited to 'lib/crypto')
-rw-r--r-- | lib/crypto/doc/specs/.gitignore | 1 | ||||
-rw-r--r-- | lib/crypto/doc/src/Makefile | 9 | ||||
-rw-r--r-- | lib/crypto/doc/src/algorithm_details.xml | 290 | ||||
-rw-r--r-- | lib/crypto/doc/src/crypto.xml | 1125 | ||||
-rw-r--r-- | lib/crypto/doc/src/engine_keys.xml | 2 | ||||
-rw-r--r-- | lib/crypto/doc/src/specs.xml | 4 | ||||
-rw-r--r-- | lib/crypto/doc/src/usersguide.xml | 1 | ||||
-rw-r--r-- | lib/crypto/src/crypto.erl | 980 |
8 files changed, 1546 insertions, 866 deletions
diff --git a/lib/crypto/doc/specs/.gitignore b/lib/crypto/doc/specs/.gitignore new file mode 100644 index 0000000000..322eebcb06 --- /dev/null +++ b/lib/crypto/doc/specs/.gitignore @@ -0,0 +1 @@ +specs_*.xml diff --git a/lib/crypto/doc/src/Makefile b/lib/crypto/doc/src/Makefile index 2148062e78..cbcafb7375 100644 --- a/lib/crypto/doc/src/Makefile +++ b/lib/crypto/doc/src/Makefile @@ -39,7 +39,7 @@ XML_REF3_FILES = crypto.xml XML_REF6_FILES = crypto_app.xml XML_PART_FILES = usersguide.xml -XML_CHAPTER_FILES = notes.xml licenses.xml fips.xml engine_load.xml engine_keys.xml +XML_CHAPTER_FILES = notes.xml licenses.xml fips.xml engine_load.xml engine_keys.xml algorithm_details.xml BOOK_FILES = book.xml @@ -62,11 +62,17 @@ HTML_REF_MAN_FILE = $(HTMLDIR)/index.html TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf +SPECS_FILES = $(XML_REF3_FILES:%.xml=$(SPECDIR)/specs_%.xml) + +TOP_SPECS_FILE = specs.xml + # ---------------------------------------------------- # FLAGS # ---------------------------------------------------- XML_FLAGS += +#in ssh it looks like this: SPECS_FLAGS = -I../../../public_key/include -I../../../public_key/src -I../../.. + # ---------------------------------------------------- # Targets # ---------------------------------------------------- @@ -93,6 +99,7 @@ clean clean_docs clean_tex: rm -f $(MAN3DIR)/* rm -f $(MAN6DIR)/* rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo) + rm -f $(SPECS_FILES) rm -f errs core *~ # ---------------------------------------------------- diff --git a/lib/crypto/doc/src/algorithm_details.xml b/lib/crypto/doc/src/algorithm_details.xml new file mode 100644 index 0000000000..088f5e8e97 --- /dev/null +++ b/lib/crypto/doc/src/algorithm_details.xml @@ -0,0 +1,290 @@ +<?xml version="1.0" encoding="utf-8" ?> +<!DOCTYPE chapter SYSTEM "chapter.dtd"> + +<chapter> + <header> + <copyright> + <year>2014</year><year>2017</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + The contents of this file are subject to the Erlang Public License, + Version 1.1, (the "License"); you may not use this file except in + compliance with the License. You should have received a copy of the + Erlang Public License along with this software. If not, it can be + retrieved online at http://www.erlang.org/. + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and limitations + under the License. + + </legalnotice> + + <title>Algorithm Details</title> + <prepared>Hans Nilsson</prepared> + <docno></docno> + <date>2018-08-22</date> + <rev>A</rev> + <file>algorithm_details.xml</file> + </header> + <p> + This chapter describes details of algorithms in the crypto application. + </p> + <p>The tables only documents the supported cryptos and key lengths. The user should not draw any conclusion + on security from the supplied tables. + </p> + + <section> + <title>Ciphers</title> + <section> + <title>Block Ciphers</title> + <p>To be used in + <seealso marker="crypto#block_encrypt-3">block_encrypt/3</seealso>, + <seealso marker="crypto#block_encrypt-4">block_encrypt/4</seealso>, + <seealso marker="crypto#block_decrypt-3">block_decrypt/3</seealso> and + <seealso marker="crypto#block_decrypt-4">block_decrypt/4</seealso>. + </p> + <p>Available in all OpenSSL compatible with Erlang CRYPTO if not disabled by configuration. + </p> + <p>To dynamically check availability, check that the name in the <i>Cipher and Mode</i> column is present in the + list with the <c>cipher</c> tag in the return value of + <seealso marker="crypto#supports-0">crypto:supports()</seealso>. + </p> + <table> + <row><cell><strong>Cipher and Mode</strong></cell><cell><strong>Key length</strong><br/><strong>[bytes]</strong></cell><cell><strong>IV length</strong><br/><strong>[bytes]</strong></cell><cell><strong>Block size</strong><br/><strong>[bytes]</strong></cell></row> + <row><cell><c>aes_cbc</c></cell> <cell>16, 24, 32</cell><cell>16</cell><cell>16</cell></row> + <row><cell><c>aes_cbc128</c></cell><cell>16</cell><cell>16</cell><cell>16</cell></row> + <row><cell><c>aes_cbc256</c></cell><cell>32</cell><cell>16</cell><cell>16</cell></row> + + <row><cell><c>aes_cfb8</c></cell> <cell>16, 24, 32</cell><cell>16</cell><cell>any</cell></row> + + <row><cell><c>aes_ecb</c></cell><cell>16, 24, 32</cell><cell> </cell><cell>16</cell></row> + + <row><cell><c>aes_ige256</c></cell><cell>16</cell><cell>32</cell><cell>16</cell></row> + <row><cell><c>blowfish_cbc</c></cell> <cell>4-56</cell> <cell>8</cell> <cell>8</cell></row> + <row><cell><c>blowfish_cfb64</c></cell> <cell>1-</cell> <cell>8</cell> <cell>any</cell></row> + <row><cell><c>blowfish_ecb</c></cell><cell>1-</cell><cell> </cell><cell>8</cell></row> + <row><cell><c>blowfish_ofb64</c></cell><cell>1-</cell><cell>8</cell><cell>any</cell></row> + + <row><cell><c>des3_cbc</c><br/><i>(=DES EDE3 CBC)</i></cell><cell>[8,8,8]</cell><cell>8</cell><cell>8</cell></row> + <row><cell><c>des3_cfb</c><br/><i>(=DES EDE3 CFB)</i></cell><cell>[8,8,8]</cell><cell>8</cell><cell>any</cell></row> + + <row><cell><c>des_cbc</c></cell><cell>8</cell><cell>8</cell> <cell>8</cell></row> + <row><cell><c>des_cfb</c></cell><cell>8</cell><cell>8</cell><cell>any</cell></row> + <row><cell><c>des_ecb</c></cell><cell>8</cell><cell> </cell><cell>8</cell></row> + <row><cell><c>des_ede3</c><br/><i>(=DES EDE3 CBC)</i></cell><cell>[8,8,8]</cell><cell>8</cell><cell>8</cell></row> + <row><cell><c>rc2_cbc</c></cell><cell>1-</cell><cell>8</cell><cell>8</cell></row> + <tcaption>Block cipher key lengths</tcaption> + </table> + </section> + + <section> + <title>AEAD Ciphers</title> + <p>To be used in <seealso marker="crypto#block_encrypt-4">block_encrypt/4</seealso> and + <seealso marker="crypto#block_decrypt-4">block_decrypt/4</seealso>. + </p> + <p>To dynamically check availability, check that the name in the <i>Cipher and Mode</i> column is present in the + list with the <c>cipher</c> tag in the return value of + <seealso marker="crypto#supports-0">crypto:supports()</seealso>. + </p> + <table> + <row><cell><strong>Cipher and Mode</strong></cell><cell><strong>Key length</strong><br/><strong>[bytes]</strong></cell><cell><strong>IV length</strong><br/><strong>[bytes]</strong></cell><cell><strong>AAD length</strong><br/><strong>[bytes]</strong></cell><cell><strong>Block size</strong><br/><strong>[bytes]</strong></cell><cell><strong>Supported with</strong><br/><strong>OpenSSL versions</strong></cell></row> + <row><cell><c>aes_gcm</c></cell> <cell>16</cell> <cell>16</cell> <cell>0-16</cell> <cell>any</cell><cell>1.0.1 -</cell></row> + <row><cell><c>chacha20_poly1305</c></cell><cell>32</cell> <cell>1-16</cell> <cell>any</cell> <cell>any</cell><cell>1.1.0 -</cell></row> + <tcaption>AEAD cipher key lengths</tcaption> + </table> + </section> + + <section> + <title>Stream Ciphers</title> + <p>To be used in <seealso marker="crypto#stream_init-2">stream_init/2</seealso> and + <seealso marker="crypto#stream_init/3">stream_init/3</seealso>. + </p> + <p>To dynamically check availability, check that the name in the <i>Cipher and Mode</i> column is present in the + list with the <c>cipher</c> tag in the return value of + <seealso marker="crypto#supports-0">crypto:supports()</seealso>. + </p> + <table> + <row><cell><strong>Cipher and Mode</strong></cell><cell><strong>Key length</strong><br/><strong>[bytes]</strong></cell><cell><strong>IV length</strong><br/><strong>[bytes]</strong></cell><cell><strong>Supported with</strong><br/><strong>OpenSSL versions</strong></cell></row> + <row><cell><c>aes_ctr</c></cell><cell>16, 24, 32</cell><cell>16</cell><cell>1.0.1 -</cell></row> + <row><cell><c>rc4</c></cell><cell>1-</cell><cell> </cell> <cell>all</cell></row> + <tcaption>Stream cipher key lengths</tcaption> + </table> + </section> + </section> + + <section> + <title>Message Authentication Codes (MACs)</title> + + <section> + <title>CMAC</title> + <p>To be used in <seealso marker="crypto#cmac-3">cmac/3</seealso> and + <seealso marker="crypto#cmac-3">cmac/4</seealso>. + </p> + <p>CMAC with the following ciphers are available with OpenSSL 1.0.1 or later if not disabled by configuration. + </p> + + <p>To dynamically check availability, check that the name <c>cmac</c> is present in the + list with the <c>macs</c> tag in the return value of + <seealso marker="crypto#supports-0">crypto:supports()</seealso>. + Also check that the name in the <i>Cipher and Mode</i> column is present in the + list with the <c>cipher</c> tag in the return value. + </p> + <table> + <row><cell><strong>Cipher and Mode</strong></cell><cell><strong>Key length</strong><br/><strong>[bytes]</strong></cell><cell><strong>Max Mac Length</strong><br/><strong>[bytes]</strong></cell></row> + <row><cell><c>aes_cbc</c></cell> <cell>16, 24, 32</cell><cell>16</cell></row> + <row><cell><c>aes_cbc128</c></cell><cell>16</cell><cell>16</cell></row> + <row><cell><c>aes_cbc256</c></cell><cell>32</cell><cell>16</cell></row> + + <row><cell><c>aes_cfb8</c></cell> <cell>16</cell><cell>1</cell></row> + + <row><cell><c>blowfish_cbc</c></cell> <cell>4-56</cell> <cell>8</cell></row> + <row><cell><c>blowfish_cfb64</c></cell> <cell>1-</cell> <cell>1</cell></row> + <row><cell><c>blowfish_ecb</c></cell><cell>1-</cell> <cell>8</cell></row> + <row><cell><c>blowfish_ofb64</c></cell><cell>1-</cell> <cell>1</cell></row> + + <row><cell><c>des3_cbc</c><br/><i>(=DES EDE3 CBC)</i></cell><cell>[8,8,8]</cell><cell>8</cell></row> + <row><cell><c>des3_cfb</c><br/><i>(=DES EDE3 CFB)</i></cell><cell>[8,8,8]</cell><cell>1</cell></row> + + <row><cell><c>des_cbc</c></cell><cell>8</cell><cell>8</cell></row> + + <row><cell><c>des_cfb</c></cell><cell>8</cell><cell>1</cell></row> + <row><cell><c>des_ecb</c></cell><cell>8</cell><cell>1</cell></row> + <row><cell><c>rc2_cbc</c></cell><cell>1-</cell><cell>8</cell></row> + <tcaption>CMAC cipher key lengths</tcaption> + </table> + </section> + + <section> + <title>HMAC</title> + <p>Available in all OpenSSL compatible with Erlang CRYPTO if not disabled by configuration. + </p> + <p>To dynamically check availability, check that the name <c>hmac</c> is present in the + list with the <c>macs</c> tag in the return value of + <seealso marker="crypto#supports-0">crypto:supports()</seealso>. + </p> + </section> + + <section> + <title>POLY1305</title> + <p>POLY1305 is available with OpenSSL 1.1.1 or later if not disabled by configuration. + </p> + <p>To dynamically check availability, check that the name <c>poly1305</c> is present in the + list with the <c>macs</c> tag in the return value of + <seealso marker="crypto#supports-0">crypto:supports()</seealso>. + </p> + </section> + + </section> + + <section> + <title>Hash</title> + + <p>To dynamically check availability, check that the wanted name in the <i>Names</i> column is present in the + list with the <c>hashs</c> tag in the return value of + <seealso marker="crypto#supports-0">crypto:supports()</seealso>. + </p> + + + <table> + <row><cell><strong>Type</strong></cell> + <cell><strong>Names</strong></cell> + <cell><strong>Supported with</strong><br/><strong>OpenSSL versions</strong></cell> + </row> + <row><cell>SHA1</cell><cell>sha</cell><cell>all</cell></row> + <row><cell>SHA2</cell><cell>sha224, sha256, sha384, sha512</cell><cell>all</cell></row> + <row><cell>SHA3</cell><cell>sha3_224, sha3_256, sha3_384, sha3_512</cell><cell>1.1.1 -</cell></row> + <row><cell>MD4</cell><cell>md4</cell><cell>all</cell></row> + <row><cell>MD5</cell><cell>md5</cell><cell>all</cell></row> + <row><cell>RIPEMD</cell><cell>ripemd160</cell><cell>all</cell></row> + <tcaption></tcaption> + </table> + </section> + + <section> + <title>Public Key Cryptography</title> + + <section> + <title>RSA</title> + <p>RSA is available with all OpenSSL versions compatible with Erlang CRYPTO if not disabled by configuration. + To dynamically check availability, check that the atom <c>rsa</c> is present in the + list with the <c>public_keys</c> tag in the return value of + <seealso marker="crypto#supports-0">crypto:supports()</seealso>. + </p> + + <table> + <row><cell><strong>Option</strong></cell> <cell><strong>sign/verify</strong></cell> <cell><strong>encrypt/decrypt</strong></cell> <cell><strong>Supported with</strong><br/><strong>OpenSSL versions</strong></cell> </row> + <row><cell>{rsa_mgf1_md,atom()}</cell> <cell>x</cell> <cell>x</cell> <cell>1.0.1</cell></row> + <row><cell>{rsa_oaep_label, binary()}</cell> <cell> </cell> <cell>x</cell> <cell></cell></row> + <row><cell>{rsa_oaep_md, atom()}</cell> <cell> </cell> <cell>x</cell> <cell></cell></row> + <row><cell>{rsa_padding,rsa_pkcs1_pss_padding}</cell> <cell>x</cell> <cell> </cell> <cell>1.0.0</cell></row> + <row><cell>{rsa_pss_saltlen, -2..}</cell> <cell>x</cell> <cell> </cell> <cell>1.0.0</cell></row> + <row><cell>{rsa_padding,rsa_no_padding}</cell> <cell>x</cell> <cell>x</cell> <cell></cell></row> + <row><cell>{rsa_padding,rsa_pkcs1_padding}</cell> <cell>x</cell> <cell>x</cell> <cell></cell></row> + <row><cell>{rsa_padding,rsa_sslv23_padding}</cell> <cell> </cell> <cell>x</cell> <cell></cell></row> + <row><cell>{rsa_padding,rsa_x931_padding}</cell> <cell>x</cell> <cell> </cell> <cell></cell></row> + <tcaption></tcaption> + </table> + </section> + + <section> + <title>DSS</title> + <p>DSS is available with OpenSSL versions compatible with Erlang CRYPTO if not disabled by configuration. + To dynamically check availability, check that the atom <c>dss</c> is present in the + list with the <c>public_keys</c> tag in the return value of + <seealso marker="crypto#supports-0">crypto:supports()</seealso>. + </p> + </section> + + <section> + <title>ECDSA</title> + <p>ECDSA is available with OpenSSL 0.9.8o or later if not disabled by configuration. + To dynamically check availability, check that the atom <c>ecdsa</c> is present in the + list with the <c>public_keys</c> tag in the return value of + <seealso marker="crypto#supports-0">crypto:supports()</seealso>. + If the atom <c>ec_gf2m</c> characteristic two field curves are available. + </p> + <p>The actual supported named curves could be checked by examining the list with the + <c>curves</c> tag in the return value of + <seealso marker="crypto#supports-0">crypto:supports()</seealso>. + </p> + </section> + + <section> + <title>Diffie-Hellman</title> + <p>Diffie-Hellman computations are available with OpenSSL versions compatible with Erlang CRYPTO + if not disabled by configuration. + To dynamically check availability, check that the atom <c>dh</c> is present in the + list with the <c>public_keys</c> tag in the return value of + <seealso marker="crypto#supports-0">crypto:supports()</seealso>. + </p> + </section> + + <section> + <title>Elliptic Curve Diffie-Hellman</title> + <p>Elliptic Curve Diffie-Hellman is available with OpenSSL 0.9.8o or later if not disabled by configuration. + To dynamically check availability, check that the atom <c>ecdh</c> is present in the + list with the <c>public_keys</c> tag in the return value of + <seealso marker="crypto#supports-0">crypto:supports()</seealso>. + </p> + + <p>The Edward curves <c>x25519</c> and <c>x448</c> are supported with OpenSSL 1.1.1 or later + if not disabled by configuration. + </p> + + <p>The actual supported named curves could be checked by examining the list with the + <c>curves</c> tag in the return value of + <seealso marker="crypto#supports-0">crypto:supports()</seealso>. + </p> + </section> + + </section> + + +</chapter> + + + + + diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml index 4289bd4a64..d5f5009297 100644 --- a/lib/crypto/doc/src/crypto.xml +++ b/lib/crypto/doc/src/crypto.xml @@ -47,6 +47,12 @@ Block Cipher Modes - <url href="http://csrc.nist.gov/groups/ST/toolkit/BCM/index.html"> ECB, CBC, CFB, OFB, CTR and GCM </url></p> </item> <item> + <p>GCM: <url href="https://csrc.nist.gov/publications/detail/sp/800-38d/final">Dworkin, M., + "Recommendation for Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC", + National Institute of Standards and Technology SP 800-38D, November 2007</url>. + </p> + </item> + <item> <p><url href="http://www.ietf.org/rfc/rfc1321.txt"> RSA encryption RFC 1321 </url> </p> </item> <item> @@ -56,192 +62,358 @@ <item> <p><url href="http://www.ietf.org/rfc/rfc2945.txt"> Secure Remote Password Protocol (SRP - RFC 2945) </url></p> </item> - <item> - <p>gcm: Dworkin, M., "Recommendation for Block Cipher Modes of - Operation: Galois/Counter Mode (GCM) and GMAC", - National Institute of Standards and Technology SP 800- - 38D, November 2007.</p> - </item> </list> - </description> - - <section> - <title>DATA TYPES </title> - <code>key_value() = integer() | binary() </code> - <p>Always <c>binary()</c> when used as return value</p> + <note> + <p>The actual supported algorithms and features depends on their availability in the actual libcrypto used. + See the <seealso marker="crypto:crypto_app">crypto (App)</seealso> about dependencies. + </p> + <p>Enabling FIPS mode will also disable algorithms and features. + </p> + </note> - <code>rsa_public() = [key_value()] = [E, N] </code> - <p> Where E is the public exponent and N is public modulus. </p> + <p>The <seealso marker="users_guide">CRYPTO User's Guide</seealso> has more information on + FIPS, Engines and Algorithm Details like key lengths. + </p> + </description> - <code>rsa_private() = [key_value()] = [E, N, D] | [E, N, D, P1, P2, E1, E2, C] </code> - <p>Where E is the public exponent, N is public modulus and D is - the private exponent. The longer key format contains redundant - information that will make the calculation faster. P1,P2 are first - and second prime factors. E1,E2 are first and second exponents. C - is the CRT coefficient. Terminology is taken from <url href="http://www.ietf.org/rfc/rfc3477.txt"> RFC 3447</url>.</p> + <datatypes> + <datatype_title>Ciphers</datatype_title> + <datatype> + <name name="stream_cipher"/> + <desc> + <p>Stream ciphers for + <seealso marker="#stream_encrypt-2">stream_encrypt/2</seealso> and + <seealso marker="#stream_decrypt-2">stream_decrypt/2</seealso> . + </p> + </desc> + </datatype> - <code>dss_public() = [key_value()] = [P, Q, G, Y] </code> - <p>Where P, Q and G are the dss parameters and Y is the public key.</p> + <datatype> + <name name="block_cipher_with_iv"/> + <name name="cbc_cipher"/> + <name name="cfb_cipher"/> + <desc> + <p>Block ciphers with initialization vector for + <seealso marker="#block_encrypt-4">block_encrypt/4</seealso> and + <seealso marker="#block_decrypt-4">block_decrypt/4</seealso> . + </p> + </desc> + </datatype> - <code>dss_private() = [key_value()] = [P, Q, G, X] </code> - <p>Where P, Q and G are the dss parameters and X is the private key.</p> + <datatype> + <name name="block_cipher_without_iv"/> + <name name="ecb_cipher"/> + <desc> + <p>Block ciphers without initialization vector for + <seealso marker="#block_encrypt-3">block_encrypt/3</seealso> and + <seealso marker="#block_decrypt-3">block_decrypt/3</seealso> . + </p> + </desc> + </datatype> - <code>srp_public() = key_value() </code> - <p>Where is <c>A</c> or <c>B</c> from <url href="http://srp.stanford.edu/design.html">SRP design</url></p> + <datatype> + <name name="aead_cipher"/> + <desc> + <p>Ciphers with simultaneous MAC-calculation or MAC-checking. + <seealso marker="#block_encrypt-4">block_encrypt/4</seealso> and + <seealso marker="#block_decrypt-4">block_decrypt/4</seealso> . + </p> + </desc> + </datatype> - <code>srp_private() = key_value() </code> - <p>Where is <c>a</c> or <c>b</c> from <url href="http://srp.stanford.edu/design.html">SRP design</url></p> + <datatype_title>Digests</datatype_title> + <datatype> + <name name="sha1"/> + <name name="sha2"/> + <name name="sha3"/> + <desc> + </desc> + </datatype> - <p>Where Verifier is <c>v</c>, Generator is <c>g</c> and Prime is<c> N</c>, DerivedKey is <c>X</c>, and Scrambler is - <c>u</c> (optional will be generated if not provided) from <url href="http://srp.stanford.edu/design.html">SRP design</url> - Version = '3' | '6' | '6a' - </p> + <datatype> + <name name="compatibility_only_hash"/> + <desc> + <p>The <c>compatibility_only_hash()</c> algorithms are recommended only for compatibility with existing applications.</p> + </desc> + </datatype> - <code>dh_public() = key_value() </code> + <datatype> + <name name="rsa_digest_type"/> + <desc> + </desc> + </datatype> - <code>dh_private() = key_value() </code> + <datatype> + <name name="dss_digest_type"/> + <desc> + </desc> + </datatype> - <code>dh_params() = [key_value()] = [P, G] | [P, G, PrivateKeyBitLength]</code> + <datatype> + <name name="ecdsa_digest_type"/> + <desc> + </desc> + </datatype> - <code>ecdh_public() = key_value() </code> + <datatype_title>Elliptic Curves</datatype_title> + <datatype> + <name name="ec_named_curve"/> + <name name="edwards_curve"/> + <desc> + <p>Note that some curves are disabled if FIPS is enabled.</p> + </desc> + </datatype> - <code>ecdh_private() = key_value() </code> + <datatype> + <name name="ec_explicit_curve"/> + <name name="ec_field"/> + <name name="ec_curve"/> + <desc> + <p>Parametric curve definition.</p> + </desc> + </datatype> - <code>ecdh_params() = ec_named_curve() | ec_explicit_curve()</code> + <datatype> + <name name="ec_prime_field"/> + <name name="ec_characteristic_two_field"/> + <name name="ec_basis"/> + <desc> + <p>Curve definition details.</p> + </desc> + </datatype> - <code>ed_named_curves_ecdh() -> x448 | x25519</code> - <p>Note that the curves are only supported if the underlying OpenSSL has support for them.</p> + <datatype_title>Keys</datatype_title> + <datatype> + <name name="key"/> + <name name="des3_key"/> + <desc> + <p>For keylengths, iv-sizes and blocksizes see the + <seealso marker="crypto:algorithm_details#ciphers">User's Guide</seealso>. + </p> + <p>A key for des3 is a list of three iolists</p> + </desc> + </datatype> - <code>ec_explicit_curve() = - {ec_field(), Prime :: key_value(), Point :: key_value(), Order :: integer(), - CoFactor :: none | integer()} </code> + <datatype> + <name name="key_integer"/> + <desc> + <p>Always <c>binary()</c> when used as return value</p> + </desc> + </datatype> - <code>ec_field() = {prime_field, Prime :: integer()} | - {characteristic_two_field, M :: integer(), Basis :: ec_basis()}</code> + <datatype_title>Public/Private Keys</datatype_title> + <datatype> + <name name="rsa_public"/> + <name name="rsa_private"/> + <name name="rsa_params"/> + <desc> + <code>rsa_public() = [E, N]</code> + <code>rsa_private() = [E, N, D] | [E, N, D, P1, P2, E1, E2, C]</code> + <p>Where E is the public exponent, N is public modulus and D is + the private exponent. The longer key format contains redundant + information that will make the calculation faster. P1,P2 are first + and second prime factors. E1,E2 are first and second exponents. C + is the CRT coefficient. Terminology is taken from <url href="http://www.ietf.org/rfc/rfc3477.txt"> RFC 3447</url>.</p> + </desc> + </datatype> - <code>ec_basis() = {tpbasis, K :: non_neg_integer()} | - {ppbasis, K1 :: non_neg_integer(), K2 :: non_neg_integer(), K3 :: non_neg_integer()} | - onbasis</code> + <datatype> + <name name="dss_public"/> + <name name="dss_private"/> + <desc> + <code>dss_public() = [P, Q, G, Y] </code> + <p>Where P, Q and G are the dss parameters and Y is the public key.</p> - <code>ec_named_curve() -> - sect571r1| sect571k1| sect409r1| sect409k1| secp521r1| secp384r1| secp224r1| secp224k1| - secp192k1| secp160r2| secp128r2| secp128r1| sect233r1| sect233k1| sect193r2| sect193r1| - sect131r2| sect131r1| sect283r1| sect283k1| sect163r2| secp256k1| secp160k1| secp160r1| - secp112r2| secp112r1| sect113r2| sect113r1| sect239k1| sect163r1| sect163k1| secp256r1| - secp192r1| - brainpoolP160r1| brainpoolP160t1| brainpoolP192r1| brainpoolP192t1| brainpoolP224r1| - brainpoolP224t1| brainpoolP256r1| brainpoolP256t1| brainpoolP320r1| brainpoolP320t1| - brainpoolP384r1| brainpoolP384t1| brainpoolP512r1| brainpoolP512t1 - </code> - <p>Note that the <em>sect</em> curves are GF2m (characteristic two) curves and are only supported if the - underlying OpenSSL has support for them. - See also <seealso marker="#supports-0">crypto:supports/0</seealso> - </p> + <code>dss_private() = [P, Q, G, X] </code> + <p>Where P, Q and G are the dss parameters and X is the private key.</p> + </desc> + </datatype> - <marker id="type-engine_key_ref"/> - <marker id="engine_key_ref_type"/> - <code>engine_key_ref() = #{engine := engine_ref(), - key_id := key_id(), - password => password()}</code> + <datatype> + <name name="ecdsa_public"/> + <name name="ecdsa_private"/> + <name name="ecdsa_params"/> + <desc> + </desc> + </datatype> - <code>engine_ref() = term()</code> - <p>The result of a call to for example <seealso marker="#engine_load-3">engine_load/3</seealso>. - </p> + <datatype> + <name name="srp_public"/> + <name name="srp_private"/> + <desc> + <code>srp_public() = key_integer() </code> + <p>Where is <c>A</c> or <c>B</c> from <url href="http://srp.stanford.edu/design.html">SRP design</url></p> + + <code>srp_private() = key_integer() </code> + <p>Where is <c>a</c> or <c>b</c> from <url href="http://srp.stanford.edu/design.html">SRP design</url></p> + </desc> + </datatype> - <code>key_id() = string() | binary()</code> - <p>Identifies the key to be used. The format depends on the loaded engine. It is passed to - the <c>ENGINE_load_(private|public)_key</c> functions in libcrypto. - </p> + <datatype> + <name name="srp_gen_params"/> + <name name="srp_comp_params"/> + <desc> + <marker id="type-srp_user_gen_params"/> + <code>srp_user_gen_params() = [DerivedKey::binary(), Prime::binary(), Generator::binary(), Version::atom()]</code> + <marker id="type-srp_host_gen_params"/> + <code>srp_host_gen_params() = [Verifier::binary(), Prime::binary(), Version::atom() ]</code> + <marker id="type-srp_user_comp_params"/> + <code>srp_user_comp_params() = [DerivedKey::binary(), Prime::binary(), Generator::binary(), Version::atom() | ScramblerArg::list()]</code> + <marker id="type-srp_host_comp_params"/> + <code>srp_host_comp_params() = [Verifier::binary(), Prime::binary(), Version::atom() | ScramblerArg::list()]</code> + <p>Where Verifier is <c>v</c>, Generator is <c>g</c> and Prime is<c> N</c>, DerivedKey is <c>X</c>, and Scrambler is + <c>u</c> (optional will be generated if not provided) from <url href="http://srp.stanford.edu/design.html">SRP design</url> + Version = '3' | '6' | '6a' + </p> + </desc> + </datatype> - <code>password() = string() | binary()</code> - <p>The key's password - </p> + <datatype_title>Public Key Ciphers</datatype_title> - <code>stream_cipher() = rc4 | aes_ctr | chacha20 </code> + <datatype> + <name name="pk_encrypt_decrypt_algs"/> + <desc> + <p>Algorithms for public key encrypt/decrypt. Only RSA is supported.</p> + </desc> + </datatype> - <code>block_cipher() = aes_cbc | aes_cfb8 | aes_cfb128 | aes_ige256 | blowfish_cbc | - blowfish_cfb64 | des_cbc | des_cfb | des3_cbc | des3_cfb | des_ede3 | rc2_cbc </code> + <datatype> + <name name="pk_encrypt_decrypt_opts"/> + <name name="rsa_opt"/> + <name name="rsa_padding"/> + <desc> + <p>Options for public key encrypt/decrypt. Only RSA is supported.</p> + </desc> + </datatype> - <code>aead_cipher() = aes_gcm | chacha20_poly1305 </code> - <p>Note that the actual supported algorithms depends on the underlying crypto library.</p> + <datatype> + <name name="rsa_compat_opts"/> + <desc> + <p>Those option forms are kept only for compatibility and should not be used in new code.</p> + </desc> + </datatype> - <code>stream_key() = aes_key() | rc4_key() </code> + <datatype_title>Public Key Sign and Verify</datatype_title> - <code>block_key() = aes_key() | blowfish_key() | des_key()| des3_key() </code> + <datatype> + <name name="pk_sign_verify_algs"/> + <desc> + <p>Algorithms for sign and verify.</p> + </desc> + </datatype> - <code>aes_key() = iodata() </code> <p>Key length is 128, 192 or 256 bits</p> + <datatype> + <name name="pk_sign_verify_opts"/> + <name name="rsa_sign_verify_opt"/> + <name name="rsa_sign_verify_padding"/> + <desc> + <p>Options for sign and verify.</p> + </desc> + </datatype> - <code>rc4_key() = iodata() </code> <p>Variable key length from 8 bits up to 2048 bits (usually between 40 and 256)</p> + <datatype_title>Diffie-Hellman Keys and parameters</datatype_title> + <datatype> + <name name="dh_public"/> + <name name="dh_private"/> + <desc> + </desc> + </datatype> - <code>blowfish_key() = iodata() </code> <p>Variable key length from 32 bits up to 448 bits</p> + <datatype> + <name name="dh_params"/> + <desc> + <code>dh_params() = [P, G] | [P, G, PrivateKeyBitLength]</code> + </desc> + </datatype> - <code>des_key() = iodata() </code> <p>Key length is 64 bits (in CBC mode only 8 bits are used)</p> + <datatype> + <name name="ecdh_public"/> + <name name="ecdh_private"/> + <name name="ecdh_params"/> + <desc> + </desc> + </datatype> - <code>des3_key() = [binary(), binary(), binary()] </code> <p>Each key part is 64 bits (in CBC mode only 8 bits are used)</p> + <datatype_title>Types for Engines</datatype_title> - <code>digest_type() = md5 | sha | sha224 | sha256 | sha384 | sha512</code> + <datatype> + <name name="engine_key_ref"/> + <name name="engine_ref"/> + <desc> + <p>The result of a call to <seealso marker="#engine_load-3">engine_load/3</seealso>. + </p> + </desc> + </datatype> - <code>rsa_digest_type() = md5 | ripemd160 | sha | sha224 | sha256 | sha384 | sha512</code> + <datatype> + <name name="key_id"/> + <desc> + <p>Identifies the key to be used. The format depends on the loaded engine. It is passed to + the <c>ENGINE_load_(private|public)_key</c> functions in libcrypto. + </p> + </desc> + </datatype> - <code>dss_digest_type() = sha | sha224 | sha256 | sha384 | sha512</code> <p>Note that the actual supported - dss_digest_type depends on the underlying crypto library. In OpenSSL version >= 1.0.1 the listed digest are supported, while in 1.0.0 only sha, sha224 and sha256 are supported. In version 0.9.8 only sha is supported.</p> + <datatype> + <name name="password"/> + <desc> + <p>The password of the key stored in an engine. + </p> + </desc> + </datatype> - <code>ecdsa_digest_type() = sha | sha224 | sha256 | sha384 | sha512</code> + <datatype> + <name name="engine_method_type"/> + </datatype> - <code>sign_options() = [{rsa_pad, rsa_sign_padding()} | {rsa_pss_saltlen, integer()}]</code> + <datatype> + <name name="engine_cmnd"/> + <desc> + <p>Pre and Post commands for <seealso marker="#engine_load-3">engine_load/3 and /4</seealso>. + </p> + </desc> + </datatype> - <code>rsa_sign_padding() = rsa_pkcs1_padding | rsa_pkcs1_pss_padding</code> + <datatype_title>Internal data types</datatype_title> - <code> hash_algorithms() = md5 | ripemd160 | sha | sha224 | sha256 | sha384 | sha512 | - sha3_224 | sha3_256 | sha3_384 | sha3_512 </code> - <p>md4 is also supported for hash_init/1 and hash/2. - Note that both md4 and md5 are recommended only for compatibility with existing applications. - Note that the actual supported hash_algorithms depends on the underlying crypto library. - </p> - <code> cipher_algorithms() = aes_cbc | aes_cfb8 | aes_cfb128 | aes_ctr | aes_gcm | - aes_ige256 | blowfish_cbc | blowfish_cfb64 | chacha20 | chacha20_poly1305 | des_cbc | - des_cfb | des3_cbc | des3_cfb | des_ede3 | rc2_cbc | rc4 </code> - <code> mac_algorithms() = hmac | cmac | poly1305</code> - <code> public_key_algorithms() = rsa |dss | ecdsa | dh | ecdh | ec_gf2m</code> - <p>Note that ec_gf2m is not strictly a public key algorithm, but a restriction on what curves are supported - with ecdsa and ecdh. - </p> - <code>engine_method_type() = engine_method_rsa | engine_method_dsa | engine_method_dh | - engine_method_rand | engine_method_ecdh | engine_method_ecdsa | - engine_method_ciphers | engine_method_digests | engine_method_store | - engine_method_pkey_meths | engine_method_pkey_asn1_meths</code> + <datatype> + <name name="stream_state"/> + <name name="hmac_state"/> + <name name="hash_state"/> + <desc> + <p>Contexts with an internal state that should not be manipulated but passed between function calls. + </p> + </desc> + </datatype> - </section> + </datatypes> + <!--================ FUNCTIONS ================--> <funcs> <func> - <name>block_encrypt(Type, Key, PlainText) -> CipherText</name> + <name name="block_encrypt" arity="3"/> <fsummary>Encrypt <c>PlainText</c> according to <c>Type</c> block cipher</fsummary> - <type> - <v>Type = des_ecb | blowfish_ecb | aes_ecb </v> - <v>Key = block_key() </v> - <v>PlainText = iodata() </v> - </type> <desc> - <p>Encrypt <c>PlainText</c> according to <c>Type</c> block cipher.</p> - <p>May throw exception <c>notsup</c> in case the chosen <c>Type</c> - is not supported by the underlying OpenSSL implementation.</p> + <p>Encrypt <c>PlainText</c> according to <c>Type</c> block cipher.</p> + <p>May raise exception <c>error:notsup</c> in case the chosen <c>Type</c> + is not supported by the underlying libcrypto implementation.</p> + <p>For keylengths and blocksizes see the + <seealso marker="crypto:algorithm_details#ciphers">User's Guide</seealso>. + </p> </desc> </func> <func> - <name>block_decrypt(Type, Key, CipherText) -> PlainText</name> + <name name="block_decrypt" arity="3"/> <fsummary>Decrypt <c>CipherText</c> according to <c>Type</c> block cipher</fsummary> - <type> - <v>Type = des_ecb | blowfish_ecb | aes_ecb </v> - <v>Key = block_key() </v> - <v>PlainText = iodata() </v> - </type> <desc> <p>Decrypt <c>CipherText</c> according to <c>Type</c> block cipher.</p> - <p>May throw exception <c>notsup</c> in case the chosen <c>Type</c> - is not supported by the underlying OpenSSL implementation.</p> + <p>May raise exception <c>error:notsup</c> in case the chosen <c>Type</c> + is not supported by the underlying libcrypto implementation.</p> + <p>For keylengths and blocksizes see the + <seealso marker="crypto:algorithm_details#ciphers">User's Guide</seealso>. + </p> </desc> </func> @@ -251,10 +423,10 @@ <name>block_encrypt(aes_gcm, Key, Ivec, {AAD, PlainText, TagLength}) -> {CipherText, CipherTag}</name> <fsummary>Encrypt <c>PlainText</c> according to <c>Type</c> block cipher</fsummary> <type> - <v>Type = block_cipher() </v> - <v>AeadType = aead_cipher() </v> - <v>Key = block_key() </v> - <v>PlainText = iodata() </v> + <v>Type = <seealso marker="#type-block_cipher_with_iv">block_cipher_with_iv()</seealso></v> + <v>AeadType = <seealso marker="#type-aead_cipher">aead_cipher()</seealso></v> + <v>Key = <seealso marker="#type-key">key()</seealso> | <seealso marker="#type-des3_key">des3_key()</seealso></v> + <v>PlainText = iodata()</v> <v>AAD = IVec = CipherText = CipherTag = binary()</v> <v>TagLength = 1..16</v> </type> @@ -264,8 +436,11 @@ <p>In AEAD (Authenticated Encryption with Associated Data) mode, encrypt <c>PlainText</c>according to <c>Type</c> block cipher and calculate <c>CipherTag</c> that also authenticates the <c>AAD</c> (Associated Authenticated Data).</p> - <p>May throw exception <c>notsup</c> in case the chosen <c>Type</c> - is not supported by the underlying OpenSSL implementation.</p> + <p>May raise exception <c>error:notsup</c> in case the chosen <c>Type</c> + is not supported by the underlying libcrypto implementation.</p> + <p>For keylengths, iv-sizes and blocksizes see the + <seealso marker="crypto:algorithm_details#ciphers">User's Guide</seealso>. + </p> </desc> </func> @@ -274,10 +449,10 @@ <name>block_decrypt(AeadType, Key, Ivec, {AAD, CipherText, CipherTag}) -> PlainText | error</name> <fsummary>Decrypt <c>CipherText</c> according to <c>Type</c> block cipher</fsummary> <type> - <v>Type = block_cipher() </v> - <v>AeadType = aead_cipher() </v> - <v>Key = block_key() </v> - <v>PlainText = iodata() </v> + <v>Type = <seealso marker="#type-block_cipher_with_iv">block_cipher_with_iv()</seealso></v> + <v>AeadType = <seealso marker="#type-aead_cipher">aead_cipher()</seealso></v> + <v>Key = <seealso marker="#type-key">key()</seealso> | <seealso marker="#type-des3_key">des3_key()</seealso></v> + <v>PlainText = iodata()</v> <v>AAD = IVec = CipherText = CipherTag = binary()</v> </type> <desc> @@ -287,19 +462,17 @@ <c>CipherText</c>according to <c>Type</c> block cipher and check the authenticity the <c>PlainText</c> and <c>AAD</c> (Associated Authenticated Data) using the <c>CipherTag</c>. May return <c>error</c> if the decryption or validation fail's</p> - <p>May throw exception <c>notsup</c> in case the chosen <c>Type</c> - is not supported by the underlying OpenSSL implementation.</p> + <p>May raise exception <c>error:notsup</c> in case the chosen <c>Type</c> + is not supported by the underlying libcrypto implementation.</p> + <p>For keylengths, iv-sizes and blocksizes see the + <seealso marker="crypto:algorithm_details#ciphers">User's Guide</seealso>. + </p> </desc> </func> <func> - <name>bytes_to_integer(Bin) -> Integer </name> + <name name="bytes_to_integer" arity="1"/> <fsummary>Convert binary representation, of an integer, to an Erlang integer.</fsummary> - <type> - <v>Bin = binary() - as returned by crypto functions</v> - - <v>Integer = integer() </v> - </type> <desc> <p>Convert binary representation, of an integer, to an Erlang integer. </p> @@ -307,17 +480,8 @@ </func> <func> - <name>compute_key(Type, OthersPublicKey, MyKey, Params) -> SharedSecret</name> + <name name="compute_key" arity="4"/> <fsummary>Computes the shared secret</fsummary> - <type> - <v> Type = dh | ecdh | srp </v> - <v>OthersPublicKey = dh_public() | ecdh_public() | srp_public() </v> - <v>MyKey = dh_private() | ecdh_private() | {srp_public(),srp_private()}</v> - <v>Params = dh_params() | ecdh_params() | ed_named_curves_ecdh() | SrpUserParams | SrpHostParams</v> - <v>SrpUserParams = {user, [DerivedKey::binary(), Prime::binary(), Generator::binary(), Version::atom() | [Scrambler:binary()]]} </v> - <v>SrpHostParams = {host, [Verifier::binary(), Prime::binary(), Version::atom() | [Scrambler::binary]]} </v> - <v>SharedSecret = binary()</v> - </type> <desc> <p>Computes the shared secret from the private key and the other party's public key. See also <seealso marker="public_key:public_key#compute_key-2">public_key:compute_key/2</seealso> @@ -326,85 +490,61 @@ </func> <func> - <name>exor(Data1, Data2) -> Result</name> + <name name="exor" arity="2"/> <fsummary>XOR data</fsummary> - <type> - <v>Data1, Data2 = iodata()</v> - <v>Result = binary()</v> - </type> <desc> <p>Performs bit-wise XOR (exclusive or) on the data supplied.</p> </desc> </func> - <func> - <name>generate_key(Type, Params) -> {PublicKey, PrivKeyOut} </name> - <name>generate_key(Type, Params, PrivKeyIn) -> {PublicKey, PrivKeyOut} </name> + + <func> + <name name="generate_key" arity="2"/> + <name name="generate_key" arity="3"/> <fsummary>Generates a public key of type <c>Type</c></fsummary> - <type> - <v> Type = dh | ecdh | rsa | srp </v> - <v>Params = dh_params() | ecdh_params() | ed_named_curves_ecdh()| RsaParams | SrpUserParams | SrpHostParams </v> - <v>RsaParams = {ModulusSizeInBits::integer(), PublicExponent::key_value()}</v> - <v>SrpUserParams = {user, [Generator::binary(), Prime::binary(), Version::atom()]}</v> - <v>SrpHostParams = {host, [Verifier::binary(), Generator::binary(), Prime::binary(), Version::atom()]}</v> - <v>PublicKey = dh_public() | ecdh_public() | rsa_public() | srp_public() </v> - <v>PrivKeyIn = undefined | dh_private() | ecdh_private() | srp_private() </v> - <v>PrivKeyOut = dh_private() | ecdh_private() | rsa_private() | srp_private() </v> - </type> <desc> <p>Generates a public key of type <c>Type</c>. See also <seealso marker="public_key:public_key#generate_key-1">public_key:generate_key/1</seealso>. - May throw exception an exception of class <c>error</c>: + May raise exception: </p> <list type="bulleted"> - <item><c>badarg</c>: an argument is of wrong type or has an illegal value,</item> - <item><c>low_entropy</c>: the random generator failed due to lack of secure "randomness",</item> - <item><c>computation_failed</c>: the computation fails of another reason than <c>low_entropy</c>.</item> + <item><c>error:badarg</c>: an argument is of wrong type or has an illegal value,</item> + <item><c>error:low_entropy</c>: the random generator failed due to lack of secure "randomness",</item> + <item><c>error:computation_failed</c>: the computation fails of another reason than <c>low_entropy</c>.</item> </list> <note> <p>RSA key generation is only available if the runtime was built with dirty scheduler support. Otherwise, attempting to - generate an RSA key will throw exception <c>error:notsup</c>.</p> + generate an RSA key will raise exception <c>error:notsup</c>.</p> </note> </desc> </func> <func> - <name>hash(Type, Data) -> Digest</name> + <name name="hash" arity="2"/> <fsummary></fsummary> - <type> - <v>Type = md4 | hash_algorithms()</v> - <v>Data = iodata()</v> - <v>Digest = binary()</v> - </type> <desc> <p>Computes a message digest of type <c>Type</c> from <c>Data</c>.</p> - <p>May throw exception <c>notsup</c> in case the chosen <c>Type</c> - is not supported by the underlying OpenSSL implementation.</p> + <p>May raise exception <c>error:notsup</c> in case the chosen <c>Type</c> + is not supported by the underlying libcrypto implementation.</p> </desc> </func> <func> - <name>hash_init(Type) -> Context</name> + <name name="hash_init" arity="1"/> <fsummary></fsummary> - <type> - <v>Type = md4 | hash_algorithms()</v> - </type> <desc> <p>Initializes the context for streaming hash operations. <c>Type</c> determines which digest to use. The returned context should be used as argument to <seealso marker="#hash_update-2">hash_update</seealso>.</p> - <p>May throw exception <c>notsup</c> in case the chosen <c>Type</c> - is not supported by the underlying OpenSSL implementation.</p> + <p>May raise exception <c>error:notsup</c> in case the chosen <c>Type</c> + is not supported by the underlying libcrypto implementation.</p> </desc> </func> <func> - <name>hash_update(Context, Data) -> NewContext</name> + <name name="hash_update" arity="2"/> <fsummary></fsummary> - <type> - <v>Data = iodata()</v> - </type> <desc> <p>Updates the digest represented by <c>Context</c> using the given <c>Data</c>. <c>Context</c> must have been generated using <seealso marker="#hash_init-1">hash_init</seealso> @@ -413,12 +553,10 @@ or <seealso marker="#hash_final-1">hash_final</seealso>.</p> </desc> </func> + <func> - <name>hash_final(Context) -> Digest</name> + <name name="hash_final" arity="1"/> <fsummary></fsummary> - <type> - <v>Digest = binary()</v> - </type> <desc> <p>Finalizes the hash operation referenced by <c>Context</c> returned from a previous call to <seealso marker="#hash_update-2">hash_update</seealso>. @@ -428,16 +566,9 @@ </func> <func> - <name>hmac(Type, Key, Data) -> Mac</name> - <name>hmac(Type, Key, Data, MacLength) -> Mac</name> + <name name="hmac" arity="3"/> + <name name="hmac" arity="4"/> <fsummary></fsummary> - <type> - <v>Type = hash_algorithms() - except ripemd160</v> - <v>Key = iodata()</v> - <v>Data = iodata()</v> - <v>MacLength = integer()</v> - <v>Mac = binary()</v> - </type> <desc> <p>Computes a HMAC of type <c>Type</c> from <c>Data</c> using <c>Key</c> as the authentication key.</p> <p><c>MacLength</c> @@ -446,13 +577,8 @@ </func> <func> - <name>hmac_init(Type, Key) -> Context</name> + <name name="hmac_init" arity="2"/> <fsummary></fsummary> - <type> - <v>Type = hash_algorithms() - except ripemd160</v> - <v>Key = iodata()</v> - <v>Context = binary()</v> - </type> <desc> <p>Initializes the context for streaming HMAC operations. <c>Type</c> determines which hash function to use in the HMAC operation. <c>Key</c> is the authentication @@ -461,12 +587,8 @@ </func> <func> - <name>hmac_update(Context, Data) -> NewContext</name> + <name name="hmac_update" arity="2"/> <fsummary></fsummary> - <type> - <v>Context = NewContext = binary()</v> - <v>Data = iodata()</v> - </type> <desc> <p>Updates the HMAC represented by <c>Context</c> using the given <c>Data</c>. <c>Context</c> must have been generated using an HMAC init function (such as @@ -479,16 +601,13 @@ call to hmac_update or hmac_final. The semantics of reusing old contexts in any way is undefined and could even crash the VM in earlier releases. The reason for this limitation is a lack of support in the underlying - OpenSSL API.</p></warning> + libcrypto API.</p></warning> </desc> </func> <func> - <name>hmac_final(Context) -> Mac</name> + <name name="hmac_final" arity="1"/> <fsummary></fsummary> - <type> - <v>Context = Mac = binary()</v> - </type> <desc> <p>Finalizes the HMAC operation referenced by <c>Context</c>. The size of the resultant MAC is determined by the type of hash function used to generate it.</p> @@ -496,12 +615,8 @@ </func> <func> - <name>hmac_final_n(Context, HashLen) -> Mac</name> + <name name="hmac_final_n" arity="2"/> <fsummary></fsummary> - <type> - <v>Context = Mac = binary()</v> - <v>HashLen = non_neg_integer()</v> - </type> <desc> <p>Finalizes the HMAC operation referenced by <c>Context</c>. <c>HashLen</c> must be greater than zero. <c>Mac</c> will be a binary with at most <c>HashLen</c> bytes. Note that if HashLen is greater than the actual number of bytes returned from the underlying hash, the returned hash will have fewer than <c>HashLen</c> bytes.</p> @@ -509,16 +624,9 @@ </func> <func> - <name>cmac(Type, Key, Data) -> Mac</name> - <name>cmac(Type, Key, Data, MacLength) -> Mac</name> + <name name="cmac" arity="3"/> + <name name="cmac" arity="4"/> <fsummary>Calculates the Cipher-based Message Authentication Code.</fsummary> - <type> - <v>Type = block_cipher()</v> - <v>Key = iodata()</v> - <v>Data = iodata()</v> - <v>MacLength = integer()</v> - <v>Mac = binary()</v> - </type> <desc> <p>Computes a CMAC of type <c>Type</c> from <c>Data</c> using <c>Key</c> as the authentication key.</p> <p><c>MacLength</c> @@ -527,20 +635,21 @@ </func> <func> - <name>info_fips() -> Status</name> + <name name="info_fips" arity="0"/> <fsummary>Provides information about the FIPS operating status.</fsummary> - <type> - <v>Status = enabled | not_enabled | not_supported</v> - </type> <desc> <p>Provides information about the FIPS operating status of - crypto and the underlying OpenSSL library. If crypto was built + crypto and the underlying libcrypto library. If crypto was built with FIPS support this can be either <c>enabled</c> (when running in FIPS mode) or <c>not_enabled</c>. For other builds - this value is always <c>not_supported</c>.</p> + this value is always <c>not_supported</c>. + </p> + <p>See <seealso marker="#enable_fips_mode-1">enable_fips_mode/1</seealso> about how to enable + FIPS mode. + </p> <warning> <p>In FIPS mode all non-FIPS compliant algorithms are - disabled and throw exception <c>not_supported</c>. Check + disabled and raise exception <c>error:notsup</c>. Check <seealso marker="#supports-0">supports</seealso> that in FIPS mode returns the restricted list of available algorithms.</p> @@ -549,13 +658,23 @@ </func> <func> - <name>info_lib() -> [{Name,VerNum,VerStr}]</name> + <name name="enable_fips_mode" arity="1"/> + <fsummary>Change FIPS mode.</fsummary> + <desc> + <p>Enables (<c>Enable = true</c>) or disables (<c>Enable = false</c>) FIPS mode. Returns <c>true</c> if + the operation was successful or <c>false</c> otherwise. + </p> + <p>Note that to enable FIPS mode succesfully, OTP must be built with the configure option <c>--enable-fips</c>, + and the underlying libcrypto must also support FIPS. + </p> + <p>See also <seealso marker="#info_fips-0">info_fips/0</seealso>. + </p> + </desc> + </func> + + <func> + <name name="info_lib" arity="0"/> <fsummary>Provides information about the libraries used by crypto.</fsummary> - <type> - <v>Name = binary()</v> - <v>VerNum = integer()</v> - <v>VerStr = binary()</v> - </type> <desc> <p>Provides the name and version of the libraries used by crypto.</p> <p><c>Name</c> is the name of the library. <c>VerNum</c> is @@ -568,50 +687,36 @@ <note><p> From OTP R16 the <em>numeric version</em> represents the version of the OpenSSL <em>header files</em> (<c>openssl/opensslv.h</c>) used when crypto was compiled. - The text variant represents the OpenSSL library used at runtime. + The text variant represents the libcrypto library used at runtime. In earlier OTP versions both numeric and text was taken from the library. </p></note> </desc> </func> <func> - <name>mod_pow(N, P, M) -> Result</name> + <name name="mod_pow" arity="3"/> <fsummary>Computes the function: N^P mod M</fsummary> - <type> - <v>N, P, M = binary() | integer()</v> - <v>Result = binary() | error</v> - </type> <desc> <p>Computes the function <c>N^P mod M</c>.</p> </desc> </func> <func> - <name>next_iv(Type, Data) -> NextIVec</name> - <name>next_iv(Type, Data, IVec) -> NextIVec</name> - <fsummary></fsummary> - <type> - <v>Type = des_cbc | des3_cbc | aes_cbc | des_cfb</v> - <v>Data = iodata()</v> - <v>IVec = NextIVec = binary()</v> - </type> - <desc> - <p>Returns the initialization vector to be used in the next - iteration of encrypt/decrypt of type <c>Type</c>. <c>Data</c> is the - encrypted data from the previous iteration step. The <c>IVec</c> - argument is only needed for <c>des_cfb</c> as the vector used - in the previous iteration step.</p> - </desc> + <name name="next_iv" arity="2"/> + <name name="next_iv" arity="3"/> + <fsummary></fsummary> + <desc> + <p>Returns the initialization vector to be used in the next + iteration of encrypt/decrypt of type <c>Type</c>. <c>Data</c> is the + encrypted data from the previous iteration step. The <c>IVec</c> + argument is only needed for <c>des_cfb</c> as the vector used + in the previous iteration step.</p> + </desc> </func> <func> - <name>poly1305(Key, Data) -> Mac</name> + <name name="poly1305" arity="2"/> <fsummary></fsummary> - <type> - <v>Key = iodata()</v> - <v>Data = iodata()</v> - <v>Mac = binary()</v> - </type> <desc> <p>Computes a POLY1305 message authentication code (<c>Mac</c>) from <c>Data</c> using <c>Key</c> as the authentication key.</p> @@ -619,15 +724,8 @@ </func> <func> - <name>private_decrypt(Type, CipherText, PrivateKey, Padding) -> PlainText</name> + <name name="private_decrypt" arity="4"/> <fsummary>Decrypts CipherText using the private Key.</fsummary> - <type> - <v>Type = rsa</v> - <v>CipherText = binary()</v> - <v>PrivateKey = rsa_private() | engine_key_ref()</v> - <v>Padding = rsa_pkcs1_padding | rsa_pkcs1_oaep_padding | rsa_no_padding</v> - <v>PlainText = binary()</v> - </type> <desc> <p>Decrypts the <c>CipherText</c>, encrypted with <seealso marker="#public_encrypt-4">public_encrypt/4</seealso> (or equivalent function) @@ -640,34 +738,8 @@ </func> <func> - <name>privkey_to_pubkey(Type, EnginePrivateKeyRef) -> PublicKey</name> - <fsummary>Fetches a public key from an Engine stored private key.</fsummary> - <type> - <v>Type = rsa | dss</v> - <v>EnginePrivateKeyRef = engine_key_ref()</v> - <v>PublicKey = rsa_public() | dss_public()</v> - </type> - <desc> - <p>Fetches the corresponding public key from a private key stored in an Engine. - The key must be of the type indicated by the Type parameter. - </p> - </desc> - </func> - - <func> - <name>private_encrypt(Type, PlainText, PrivateKey, Padding) -> CipherText</name> + <name name="private_encrypt" arity="4"/> <fsummary>Encrypts PlainText using the private Key.</fsummary> - <type> - <v>Type = rsa</v> - <v>PlainText = binary()</v> - <d> The size of the <c>PlainText</c> must be less - than <c>byte_size(N)-11</c> if <c>rsa_pkcs1_padding</c> is - used, and <c>byte_size(N)</c> if <c>rsa_no_padding</c> is - used, where N is public modulus of the RSA key.</d> - <v>PrivateKey = rsa_private() | engine_key_ref()</v> - <v>Padding = rsa_pkcs1_padding | rsa_no_padding</v> - <v>CipherText = binary()</v> - </type> <desc> <p>Encrypts the <c>PlainText</c> using the <c>PrivateKey</c> and returns the ciphertext. This is a low level signature operation @@ -677,16 +749,10 @@ </p> </desc> </func> + <func> - <name>public_decrypt(Type, CipherText, PublicKey, Padding) -> PlainText</name> + <name name="public_decrypt" arity="4"/> <fsummary>Decrypts CipherText using the public Key.</fsummary> - <type> - <v>Type = rsa</v> - <v>CipherText = binary()</v> - <v>PublicKey = rsa_public() | engine_key_ref()</v> - <v>Padding = rsa_pkcs1_padding | rsa_no_padding</v> - <v>PlainText = binary()</v> - </type> <desc> <p>Decrypts the <c>CipherText</c>, encrypted with <seealso marker="#private_encrypt-4">private_encrypt/4</seealso>(or equivalent function) @@ -699,19 +765,8 @@ </func> <func> - <name>public_encrypt(Type, PlainText, PublicKey, Padding) -> CipherText</name> + <name name="public_encrypt" arity="4"/> <fsummary>Encrypts PlainText using the public Key.</fsummary> - <type> - <v>Type = rsa</v> - <v>PlainText = binary()</v> - <d> The size of the <c>PlainText</c> must be less - than <c>byte_size(N)-11</c> if <c>rsa_pkcs1_padding</c> is - used, and <c>byte_size(N)</c> if <c>rsa_no_padding</c> is - used, where N is public modulus of the RSA key.</d> - <v>PublicKey = rsa_public() | engine_key_ref()</v> - <v>Padding = rsa_pkcs1_padding | rsa_pkcs1_oaep_padding | rsa_no_padding</v> - <v>CipherText = binary()</v> - </type> <desc> <p>Encrypts the <c>PlainText</c> (message digest) using the <c>PublicKey</c> and returns the <c>CipherText</c>. This is a low level signature operation @@ -722,18 +777,15 @@ </func> <func> - <name>rand_seed(Seed) -> ok</name> + <name name="rand_seed" arity="1"/> <fsummary>Set the seed for random bytes generation</fsummary> - <type> - <v>Seed = binary()</v> - </type> <desc> <p>Set the seed for PRNG to the given binary. This calls the RAND_seed function from openssl. Only use this if the system you are running on does not have enough "randomness" built in. Normally this is when <seealso marker="#strong_rand_bytes/1">strong_rand_bytes/1</seealso> - throws <c>low_entropy</c></p> + raises <c>error:low_entropy</c></p> </desc> </func> @@ -751,36 +803,15 @@ </func> <func> - <name>sign(Algorithm, DigestType, Msg, Key) -> binary()</name> - <name>sign(Algorithm, DigestType, Msg, Key, Options) -> binary()</name> - <fsummary> Create digital signature.</fsummary> - <type> - <v>Algorithm = rsa | dss | ecdsa </v> - <v>Msg = binary() | {digest,binary()}</v> - <d>The msg is either the binary "cleartext" data to be - signed or it is the hashed value of "cleartext" i.e. the - digest (plaintext).</d> - <v>DigestType = rsa_digest_type() | dss_digest_type() | ecdsa_digest_type()</v> - <v>Key = rsa_private() | dss_private() | [ecdh_private(),ecdh_params()] | engine_key_ref()</v> - <v>Options = sign_options()</v> - </type> - <desc> - <p>Creates a digital signature.</p> - <p>Algorithm <c>dss</c> can only be used together with digest type - <c>sha</c>.</p> - <p>See also <seealso marker="public_key:public_key#sign-3">public_key:sign/3</seealso>.</p> - </desc> - </func> - - <func> - <name>start() -> ok</name> + <name name="start" arity="0"/> <fsummary> Equivalent to application:start(crypto). </fsummary> <desc> <p> Equivalent to application:start(crypto).</p> </desc> </func> + <func> - <name>stop() -> ok</name> + <name name="stop" arity="0"/> <fsummary> Equivalent to application:stop(crypto).</fsummary> <desc> <p> Equivalent to application:stop(crypto).</p> @@ -788,23 +819,20 @@ </func> <func> - <name>strong_rand_bytes(N) -> binary()</name> + <name name="strong_rand_bytes" arity="1"/> <fsummary>Generate a binary of random bytes</fsummary> - <type> - <v>N = integer()</v> - </type> <desc> <p>Generates N bytes randomly uniform 0..255, and returns the result in a binary. Uses a cryptographically secure prng seeded and periodically mixed with operating system provided entropy. By default this is the <c>RAND_bytes</c> method from OpenSSL.</p> - <p>May throw exception <c>low_entropy</c> in case the random generator + <p>May raise exception <c>error:low_entropy</c> in case the random generator failed due to lack of secure "randomness".</p> </desc> </func> <func> - <name>rand_seed() -> rand:state()</name> + <name name="rand_seed" arity="0"/> <fsummary>Strong random number generation plugin state</fsummary> <desc> <p> @@ -820,7 +848,7 @@ <p> When using the state object from this function the <seealso marker="stdlib:rand">rand</seealso> functions using it - may throw exception <c>low_entropy</c> in case the random generator + may raise exception <c>error:low_entropy</c> in case the random generator failed due to lack of secure "randomness". </p> <p><em>Example</em></p> @@ -832,7 +860,7 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre> </func> <func> - <name>rand_seed_s() -> rand:state()</name> + <name name="rand_seed_s" arity="0"/> <fsummary>Strong random number generation plugin state</fsummary> <desc> <p> @@ -846,7 +874,7 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre> <p> When using the state object from this function the <seealso marker="stdlib:rand">rand</seealso> functions using it - may throw exception <c>low_entropy</c> in case the random generator + may raise exception <c>error:low_entropy</c> in case the random generator failed due to lack of secure "randomness". </p> <note> @@ -885,7 +913,7 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre> <p> When using the state object from this function the <seealso marker="stdlib:rand">rand</seealso> functions using it - may throw exception <c>low_entropy</c> in case the random generator + may raise exception <c>error:low_entropy</c> in case the random generator failed due to lack of secure "randomness". </p> <p> @@ -930,7 +958,7 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre> <p> When using the state object from this function the <seealso marker="stdlib:rand">rand</seealso> functions using it - may throw exception <c>low_entropy</c> in case the random generator + may raise exception <c>error:low_entropy</c> in case the random generator failed due to lack of secure "randomness". </p> <p> @@ -961,45 +989,36 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre> </func> <func> - <name>stream_init(Type, Key) -> State</name> + <name name="stream_init" arity="2"/> <fsummary></fsummary> - <type> - <v>Type = rc4 </v> - <v>State = opaque() </v> - <v>Key = iodata()</v> - </type> <desc> <p>Initializes the state for use in RC4 stream encryption <seealso marker="#stream_encrypt-2">stream_encrypt</seealso> and <seealso marker="#stream_decrypt-2">stream_decrypt</seealso></p> + <p>For keylengths see the + <seealso marker="crypto:algorithm_details#stream-ciphers">User's Guide</seealso>. + </p> </desc> </func> <func> - <name>stream_init(Type, Key, IVec) -> State</name> + <name name="stream_init" arity="3"/> <fsummary></fsummary> - <type> - <v>Type = aes_ctr | chacha20</v> - <v>State = opaque() </v> - <v>Key = iodata()</v> - <v>IVec = binary()</v> - </type> <desc> <p>Initializes the state for use in streaming AES encryption using Counter mode (CTR). <c>Key</c> is the AES key and must be either 128, 192, or 256 bits long. <c>IVec</c> is an arbitrary initializing vector of 128 bits (16 bytes). This state is for use with <seealso marker="#stream_encrypt-2">stream_encrypt</seealso> and <seealso marker="#stream_decrypt-2">stream_decrypt</seealso>.</p> + <p>For keylengths and iv-sizes see the + <seealso marker="crypto:algorithm_details#stream-ciphers">User's Guide</seealso>. + </p> </desc> </func> <func> - <name>stream_encrypt(State, PlainText) -> { NewState, CipherText}</name> + <name name="stream_encrypt" arity="2"/> <fsummary></fsummary> - <type> - <v>Text = iodata()</v> - <v>CipherText = binary()</v> - </type> <desc> <p>Encrypts <c>PlainText</c> according to the stream cipher <c>Type</c> specified in stream_init/3. <c>Text</c> can be any number of bytes. The initial <c>State</c> is created using @@ -1009,12 +1028,8 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre> </func> <func> - <name>stream_decrypt(State, CipherText) -> { NewState, PlainText }</name> + <name name="stream_decrypt" arity="2"/> <fsummary></fsummary> - <type> - <v>CipherText = iodata()</v> - <v>PlainText = binary()</v> - </type> <desc> <p>Decrypts <c>CipherText</c> according to the stream cipher <c>Type</c> specified in stream_init/3. <c>PlainText</c> can be any number of bytes. The initial <c>State</c> is created using @@ -1024,60 +1039,54 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre> </func> <func> - <name>supports() -> AlgorithmList </name> + <name name="supports" arity="0"/> <fsummary>Provide a list of available crypto algorithms.</fsummary> - <type> - <v> AlgorithmList = [{hashs, [hash_algorithms()]}, - {ciphers, [cipher_algorithms()]}, - {public_keys, [public_key_algorithms()]}, - {macs, [mac_algorithms()]}] - </v> - </type> <desc> <p> Can be used to determine which crypto algorithms that are supported - by the underlying OpenSSL library</p> + by the underlying libcrypto library</p> </desc> </func> <func> - <name>ec_curves() -> EllipticCurveList </name> + <name name="ec_curves" arity="0"/> <fsummary>Provide a list of available named elliptic curves.</fsummary> - <type> - <v>EllipticCurveList = [ec_named_curve()]</v> - </type> <desc> <p>Can be used to determine which named elliptic curves are supported.</p> </desc> </func> <func> - <name>ec_curve(NamedCurve) -> EllipticCurve </name> + <name name="ec_curve" arity="1"/> <fsummary>Get the defining parameters of a elliptic curve.</fsummary> - <type> - <v>NamedCurve = ec_named_curve()</v> - <v>EllipticCurve = ec_explicit_curve()</v> - </type> <desc> <p>Return the defining parameters of a elliptic curve.</p> </desc> </func> - <func> - <name>verify(Algorithm, DigestType, Msg, Signature, Key) -> boolean()</name> - <name>verify(Algorithm, DigestType, Msg, Signature, Key, Options) -> boolean()</name> + <func> + <name name="sign" arity="4"/> + <name name="sign" arity="5"/> + <fsummary> Create digital signature.</fsummary> + <desc> + <p>Creates a digital signature.</p> + <p>The msg is either the binary "cleartext" data to be + signed or it is the hashed value of "cleartext" i.e. the + digest (plaintext).</p> + <p>Algorithm <c>dss</c> can only be used together with digest type + <c>sha</c>.</p> + <p>See also <seealso marker="public_key:public_key#sign-3">public_key:sign/3</seealso>.</p> + </desc> + </func> + + <func> + <name name="verify" arity="5"/> + <name name="verify" arity="6"/> <fsummary>Verifies a digital signature.</fsummary> - <type> - <v> Algorithm = rsa | dss | ecdsa </v> - <v>Msg = binary() | {digest,binary()}</v> - <d>The msg is either the binary "cleartext" data - or it is the hashed value of "cleartext" i.e. the digest (plaintext).</d> - <v>DigestType = rsa_digest_type() | dss_digest_type() | ecdsa_digest_type()</v> - <v>Signature = binary()</v> - <v>Key = rsa_public() | dss_public() | [ecdh_public(),ecdh_params()] | engine_key_ref()</v> - <v>Options = sign_options()</v> - </type> <desc> <p>Verifies a digital signature</p> + <p>The msg is either the binary "cleartext" data to be + signed or it is the hashed value of "cleartext" i.e. the + digest (plaintext).</p> <p>Algorithm <c>dss</c> can only be used together with digest type <c>sha</c>.</p> @@ -1087,17 +1096,24 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre> <!-- Engine functions --> <func> - <name>engine_get_all_methods() -> Result</name> + <name name="privkey_to_pubkey" arity="2"/> + <fsummary>Fetches a public key from an Engine stored private key.</fsummary> + <desc> + <p>Fetches the corresponding public key from a private key stored in an Engine. + The key must be of the type indicated by the Type parameter. + </p> + </desc> + </func> + + <func> + <name name="engine_get_all_methods" arity="0"/> <fsummary>Return list of all possible engine methods</fsummary> - <type> - <v>Result = [EngineMethod::atom()]</v> - </type> <desc> <p> Returns a list of all possible engine methods. </p> <p> - May throw exception notsup in case there is + May raise exception <c>error:notsup</c> in case there is no engine support in the underlying OpenSSL implementation. </p> <p> @@ -1108,13 +1124,8 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre> </func> <func> - <name>engine_load(EngineId, PreCmds, PostCmds) -> Result</name> + <name name="engine_load" arity="3"/> <fsummary>Dynamical load an encryption engine</fsummary> - <type> - <v>EngineId = unicode:chardata()</v> - <v>PreCmds, PostCmds = [{unicode:chardata(), unicode:chardata()}]</v> - <v>Result = {ok, Engine::engine_ref()} | {error, Reason::term()}</v> - </type> <desc> <p> Loads the OpenSSL engine given by <c>EngineId</c> if it is available and then returns ok and @@ -1123,8 +1134,8 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre> returned if the engine can't be loaded. </p> <p> - The function throws a badarg if the parameters are in wrong format. - It may also throw the exception notsup in case there is + The function raises a <c>error:badarg</c> if the parameters are in wrong format. + It may also raise the exception <c>error:notsup</c> in case there is no engine support in the underlying OpenSSL implementation. </p> <p> @@ -1135,22 +1146,16 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre> </func> <func> - <name>engine_load(EngineId, PreCmds, PostCmds, EngineMethods) -> Result</name> + <name name="engine_load" arity="4"/> <fsummary>Dynamical load an encryption engine</fsummary> - <type> - <v>EngineId = unicode:chardata()</v> - <v>PreCmds, PostCmds = [{unicode:chardata(), unicode:chardata()}]</v> - <v>EngineMethods = [engine_method_type()]</v> - <v>Result = {ok, Engine::engine_ref()} | {error, Reason::term()}</v> - </type> <desc> <p> Loads the OpenSSL engine given by <c>EngineId</c> if it is available and then returns ok and an engine handle. An error tuple is returned if the engine can't be loaded. </p> <p> - The function throws a badarg if the parameters are in wrong format. - It may also throw the exception notsup in case there is + The function raises a <c>error:badarg</c> if the parameters are in wrong format. + It may also raise the exception <c>error:notsup</c> in case there is no engine support in the underlying OpenSSL implementation. </p> <p> @@ -1161,20 +1166,16 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre> </func> <func> - <name>engine_unload(Engine) -> Result</name> + <name name="engine_unload" arity="1"/> <fsummary>Dynamical load an encryption engine</fsummary> - <type> - <v>Engine = engine_ref()</v> - <v>Result = ok | {error, Reason::term()}</v> - </type> <desc> <p> Unloads the OpenSSL engine given by <c>Engine</c>. An error tuple is returned if the engine can't be unloaded. </p> <p> - The function throws a badarg if the parameter is in wrong format. - It may also throw the exception notsup in case there is + The function raises a <c>error:badarg</c> if the parameter is in wrong format. + It may also raise the exception <c>error:notsup</c> in case there is no engine support in the underlying OpenSSL implementation. </p> <p> @@ -1185,20 +1186,16 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre> </func> <func> - <name>engine_by_id(EngineId) -> Result</name> + <name name="engine_by_id" arity="1"/> <fsummary>Get a reference to an already loaded engine</fsummary> - <type> - <v>EngineID = unicode:chardata()engine_ref()</v> - <v>Result = {ok, Engine::engine_ref()} | {error, Reason::term()}</v> - </type> <desc> <p> Get a reference to an already loaded engine with <c>EngineId</c>. An error tuple is returned if the engine can't be unloaded. </p> <p> - The function throws a badarg if the parameter is in wrong format. - It may also throw the exception notsup in case there is + The function raises a <c>error:badarg</c> if the parameter is in wrong format. + It may also raise the exception <c>error:notsup</c> in case there is no engine support in the underlying OpenSSL implementation. </p> <p> @@ -1209,14 +1206,8 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre> </func> <func> - <name>engine_ctrl_cmd_string(Engine, CmdName, CmdArg) -> Result</name> + <name name="engine_ctrl_cmd_string" arity="3"/> <fsummary>Sends ctrl commands to an OpenSSL engine</fsummary> - <type> - <v>Engine = engine_ref()</v> - <v>CmdName = unicode:chardata()</v> - <v>CmdArg = unicode:chardata()</v> - <v>Result = ok | {error, Reason::term()}</v> - </type> <desc> <p> Sends ctrl commands to the OpenSSL engine given by <c>Engine</c>. @@ -1224,23 +1215,16 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre> <c>Optional</c> set to <c>false</c>. </p> <p> - The function throws a badarg if the parameters are in wrong format. - It may also throw the exception notsup in case there is + The function raises a <c>error:badarg</c> if the parameters are in wrong format. + It may also raise the exception <c>error:notsup</c> in case there is no engine support in the underlying OpenSSL implementation. </p> </desc> </func> <func> - <name>engine_ctrl_cmd_string(Engine, CmdName, CmdArg, Optional) -> Result</name> + <name name="engine_ctrl_cmd_string" arity="4"/> <fsummary>Sends ctrl commands to an OpenSSL engine</fsummary> - <type> - <v>Engine = engine_ref()</v> - <v>CmdName = unicode:chardata()</v> - <v>CmdArg = unicode:chardata()</v> - <v>Optional = boolean()</v> - <v>Result = ok | {error, Reason::term()}</v> - </type> <desc> <p> Sends ctrl commands to the OpenSSL engine given by <c>Engine</c>. @@ -1252,91 +1236,72 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre> <c>false</c>. </p> <p> - The function throws a badarg if the parameters are in wrong format. - It may also throw the exception notsup in case there is + The function raises a <c>error:badarg</c> if the parameters are in wrong format. + It may also raise the exception <c>error:notsup</c> in case there is no engine support in the underlying OpenSSL implementation. </p> </desc> </func> <func> - <name>engine_add(Engine) -> Result</name> + <name name="engine_add" arity="1"/> <fsummary>Add engine to OpenSSL internal list</fsummary> - <type> - <v>Engine = engine_ref()</v> - <v>Result = ok | {error, Reason::term()}</v> - </type> <desc> <p>Add the engine to OpenSSL's internal list.</p> <p> - The function throws a badarg if the parameters are in wrong format. - It may also throw the exception notsup in case there is + The function raises a <c>error:badarg</c> if the parameters are in wrong format. + It may also raise the exception <c>error:notsup</c> in case there is no engine support in the underlying OpenSSL implementation. </p> </desc> </func> <func> - <name>engine_remove(Engine) -> Result</name> + <name name="engine_remove" arity="1"/> <fsummary>Remove engine to OpenSSL internal list</fsummary> - <type> - <v>Engine = engine_ref()</v> - <v>Result = ok | {error, Reason::term()}</v> - </type> <desc> <p>Remove the engine from OpenSSL's internal list.</p> <p> - The function throws a badarg if the parameters are in wrong format. - It may also throw the exception notsup in case there is + The function raises a <c>error:badarg</c> if the parameters are in wrong format. + It may also raise the exception <c>error:notsup</c> in case there is no engine support in the underlying OpenSSL implementation. </p> </desc> </func> <func> - <name>engine_get_id(Engine) -> EngineId</name> + <name name="engine_get_id" arity="1"/> <fsummary>Fetch engine ID</fsummary> - <type> - <v>Engine = engine_ref()</v> - <v>EngineId = unicode:chardata()</v> - </type> <desc> <p>Return the ID for the engine, or an empty binary if there is no id set.</p> <p> - The function throws a badarg if the parameters are in wrong format. - It may also throw the exception notsup in case there is + The function raises a <c>error:badarg</c> if the parameters are in wrong format. + It may also raise the exception <c>error:notsup</c> in case there is no engine support in the underlying OpenSSL implementation. </p> </desc> </func> <func> - <name>engine_get_name(Engine) -> EngineName</name> + <name name="engine_get_name" arity="1"/> <fsummary>Fetch engine name</fsummary> - <type> - <v>Engine = engine_ref()</v> - <v>EngineName = unicode:chardata()</v> - </type> <desc> <p>Return the name (eg a description) for the engine, or an empty binary if there is no name set.</p> <p> - The function throws a badarg if the parameters are in wrong format. - It may also throw the exception notsup in case there is + The function raises a <c>error:badarg</c> if the parameters are in wrong format. + It may also raise the exception <c>error:notsup</c> in case there is no engine support in the underlying OpenSSL implementation. </p> </desc> </func> <func> - <name>engine_list() -> Result</name> + <name name="engine_list" arity="0"/> <fsummary>List the known engine ids</fsummary> - <type> - <v>Result = [EngineId::unicode:chardata()]</v> - </type> <desc> <p>List the id's of all engines in OpenSSL's internal list.</p> <p> - It may also throw the exception notsup in case there is + It may also raise the exception <c>error:notsup</c> in case there is no engine support in the underlying OpenSSL implementation. </p> <p> @@ -1344,20 +1309,15 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre> in the User's Guide. </p> <p> - May throw exception notsup in case engine functionality is not supported by the underlying + May raise exception <c>error:notsup</c> in case engine functionality is not supported by the underlying OpenSSL implementation. </p> </desc> </func> <func> - <name>ensure_engine_loaded(EngineId, LibPath) -> Result</name> + <name name="ensure_engine_loaded" arity="2"/> <fsummary>Ensure encryption engine just loaded once</fsummary> - <type> - <v>EngineId = unicode:chardata()</v> - <v>LibPath = unicode:chardata()</v> - <v>Result = {ok, Engine::engine_ref()} | {error, Reason::term()}</v> - </type> <desc> <p> Loads the OpenSSL engine given by <c>EngineId</c> and the path to the dynamic library @@ -1366,8 +1326,8 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre> returned if the engine can't be loaded. </p> <p> - The function throws a badarg if the parameters are in wrong format. - It may also throw the exception notsup in case there is + The function raises a <c>error:badarg</c> if the parameters are in wrong format. + It may also raise the exception <c>error:notsup</c> in case there is no engine support in the underlying OpenSSL implementation. </p> <p> @@ -1378,14 +1338,8 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre> </func> <func> - <name>ensure_engine_loaded(EngineId, LibPath, EngineMethods) -> Result</name> + <name name="ensure_engine_loaded" arity="3"/> <fsummary>Ensure encryption engine just loaded once</fsummary> - <type> - <v>EngineId = unicode:chardata()</v> - <v>LibPath = unicode:chardata()</v> - <v>EngineMethods = [engine_method_type()]</v> - <v>Result = {ok, Engine::engine_ref()} | {error, Reason::term()}</v> - </type> <desc> <p> Loads the OpenSSL engine given by <c>EngineId</c> and the path to the dynamic library @@ -1395,8 +1349,8 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre> An error tuple is returned if the engine can't be loaded. </p> <p> - The function throws a badarg if the parameters are in wrong format. - It may also throw the exception notsup in case there is + The function raises a <c>error:badarg</c> if the parameters are in wrong format. + It may also raise the exception <c>error:notsup</c> in case there is no engine support in the underlying OpenSSL implementation. </p> <p> @@ -1407,12 +1361,8 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre> </func> <func> - <name>ensure_engine_unloaded(Engine) -> Result</name> + <name name="ensure_engine_unloaded" arity="1"/> <fsummary>Unload an engine loaded with the ensure function</fsummary> - <type> - <v>Engine = engine_ref()</v> - <v>Result = ok | {error, Reason::term()}</v> - </type> <desc> <p> Unloads an engine loaded with the <c>ensure_engine_loaded</c> function. @@ -1422,8 +1372,8 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre> returned if the engine can't be unloaded. </p> <p> - The function throws a badarg if the parameters are in wrong format. - It may also throw the exception notsup in case there is + The function raises a <c>error:badarg</c> if the parameters are in wrong format. + It may also raise the exception <c>error:notsup</c> in case there is no engine support in the underlying OpenSSL implementation. </p> <p> @@ -1434,13 +1384,8 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre> </func> <func> - <name>ensure_engine_unloaded(Engine, EngineMethods) -> Result</name> + <name name="ensure_engine_unloaded" arity="2"/> <fsummary>Unload an engine loaded with the ensure function</fsummary> - <type> - <v>Engine = engine_ref()</v> - <v>EngineMethods = [engine_method_type()]</v> - <v>Result = ok | {error, Reason::term()}</v> - </type> <desc> <p> Unloads an engine loaded with the <c>ensure_engine_loaded</c> function. @@ -1448,8 +1393,8 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre> An error tuple is returned if the engine can't be unloaded. </p> <p> - The function throws a badarg if the parameters are in wrong format. - It may also throw the exception notsup in case there is + The function raises a <c>error:badarg</c> if the parameters are in wrong format. + It may also raise the exception <c>error:notsup</c> in case there is no engine support in the underlying OpenSSL implementation. </p> <p> @@ -1461,75 +1406,5 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre> </funcs> - <!-- Maybe put this in the users guide --> - <!-- <section> --> - <!-- <title>DES in CBC mode</title> --> - <!-- <p>The Data Encryption Standard (DES) defines an algorithm for --> - <!-- encrypting and decrypting an 8 byte quantity using an 8 byte key --> - <!-- (actually only 56 bits of the key is used). --> - <!-- </p> --> - <!-- <p>When it comes to encrypting and decrypting blocks that are --> - <!-- multiples of 8 bytes various modes are defined (NIST SP --> - <!-- 800-38A). One of those modes is the Cipher Block Chaining (CBC) --> - <!-- mode, where the encryption of an 8 byte segment depend not only --> - <!-- of the contents of the segment itself, but also on the result of --> - <!-- encrypting the previous segment: the encryption of the previous --> - <!-- segment becomes the initializing vector of the encryption of the --> - <!-- current segment. --> - <!-- </p> --> - <!-- <p>Thus the encryption of every segment depends on the encryption --> - <!-- key (which is secret) and the encryption of the previous --> - <!-- segment, except the first segment which has to be provided with --> - <!-- an initial initializing vector. That vector could be chosen at --> - <!-- random, or be a counter of some kind. It does not have to be --> - <!-- secret. --> - <!-- </p> --> - <!-- <p>The following example is drawn from the old FIPS 81 standard --> - <!-- (replaced by NIST SP 800-38A), where both the plain text and the --> - <!-- resulting cipher text is settled. The following code fragment --> - <!-- returns `true'. --> - <!-- </p> --> - <!-- <pre><![CDATA[ --> - - <!-- Key = <<16#01,16#23,16#45,16#67,16#89,16#ab,16#cd,16#ef>>, --> - <!-- IVec = <<16#12,16#34,16#56,16#78,16#90,16#ab,16#cd,16#ef>>, --> - <!-- P = "Now is the time for all ", --> - <!-- C = crypto:des_cbc_encrypt(Key, IVec, P), --> - <!-- % Which is the same as --> - <!-- P1 = "Now is t", P2 = "he time ", P3 = "for all ", --> - <!-- C1 = crypto:des_cbc_encrypt(Key, IVec, P1), --> - <!-- C2 = crypto:des_cbc_encrypt(Key, C1, P2), --> - <!-- C3 = crypto:des_cbc_encrypt(Key, C2, P3), --> - - <!-- C = <<C1/binary, C2/binary, C3/binary>>, --> - <!-- C = <<16#e5,16#c7,16#cd,16#de,16#87,16#2b,16#f2,16#7c, --> - <!-- 16#43,16#e9,16#34,16#00,16#8c,16#38,16#9c,16#0f, --> - <!-- 16#68,16#37,16#88,16#49,16#9a,16#7c,16#05,16#f6>>, --> - <!-- <<"Now is the time for all ">> == --> - <!-- crypto:des_cbc_decrypt(Key, IVec, C). --> - <!-- ]]></pre> --> - <!-- <p>The following is true for the DES CBC mode. For all --> - <!-- decompositions <c>P1 ++ P2 = P</c> of a plain text message --> - <!-- <c>P</c> (where the length of all quantities are multiples of 8 --> - <!-- bytes), the encryption <c>C</c> of <c>P</c> is equal to <c>C1 ++ --> - <!-- C2</c>, where <c>C1</c> is obtained by encrypting <c>P1</c> with --> - <!-- <c>Key</c> and the initializing vector <c>IVec</c>, and where --> - <!-- <c>C2</c> is obtained by encrypting <c>P2</c> with <c>Key</c> --> - <!-- and the initializing vector <c>last8(C1)</c>, --> - <!-- where <c>last(Binary)</c> denotes the last 8 bytes of the --> - <!-- binary <c>Binary</c>. --> - <!-- </p> --> - <!-- <p>Similarly, for all decompositions <c>C1 ++ C2 = C</c> of a --> - <!-- cipher text message <c>C</c> (where the length of all quantities --> - <!-- are multiples of 8 bytes), the decryption <c>P</c> of <c>C</c> --> - <!-- is equal to <c>P1 ++ P2</c>, where <c>P1</c> is obtained by --> - <!-- decrypting <c>C1</c> with <c>Key</c> and the initializing vector --> - <!-- <c>IVec</c>, and where <c>P2</c> is obtained by decrypting --> - <!-- <c>C2</c> with <c>Key</c> and the initializing vector --> - <!-- <c>last8(C1)</c>, where <c>last8(Binary)</c> is as above. --> - <!-- </p> --> - <!-- <p>For DES3 (which uses three 64 bit keys) the situation is the --> - <!-- same. --> - <!-- </p> --> - <!-- </section> --> + </erlref> diff --git a/lib/crypto/doc/src/engine_keys.xml b/lib/crypto/doc/src/engine_keys.xml index 38714fed8a..4f7b0243fb 100644 --- a/lib/crypto/doc/src/engine_keys.xml +++ b/lib/crypto/doc/src/engine_keys.xml @@ -62,7 +62,7 @@ on the Engine loaded </item> <item>an Erlang map is constructed with the Engine reference, the key reference and possibly a key passphrase if - needed by the Engine. See the <seealso marker="crypto:crypto#engine_key_ref_type">Reference Manual</seealso> for + needed by the Engine. See the <seealso marker="crypto:crypto#type-engine_key_ref">Reference Manual</seealso> for details of the map. </item> </list> diff --git a/lib/crypto/doc/src/specs.xml b/lib/crypto/doc/src/specs.xml new file mode 100644 index 0000000000..66c79a906b --- /dev/null +++ b/lib/crypto/doc/src/specs.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" ?> +<specs xmlns:xi="http://www.w3.org/2001/XInclude"> + <xi:include href="../specs/specs_crypto.xml"/> +</specs> diff --git a/lib/crypto/doc/src/usersguide.xml b/lib/crypto/doc/src/usersguide.xml index 0124121433..2dfc966609 100644 --- a/lib/crypto/doc/src/usersguide.xml +++ b/lib/crypto/doc/src/usersguide.xml @@ -50,4 +50,5 @@ <xi:include href="fips.xml"/> <xi:include href="engine_load.xml"/> <xi:include href="engine_keys.xml"/> + <xi:include href="algorithm_details.xml"/> </part> diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index 17351d10ea..c64586897e 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -66,12 +66,31 @@ ensure_engine_unloaded/2 ]). +-export_type([ %% A minimum exported: only what public_key needs. + dh_private/0, + dh_public/0, + dss_digest_type/0, + ec_named_curve/0, + ecdsa_digest_type/0, + pk_encrypt_decrypt_opts/0, + pk_sign_verify_opts/0, + rsa_digest_type/0, + sha1/0, + sha2/0 + ]). + -export_type([engine_ref/0, key_id/0, password/0 ]). - +%%% Opaque types must be exported :( +-export_type([ + stream_state/0, + hmac_state/0, + hash_state/0 + ]). + %% Private. For tests. -export([packed_openssl_version/4, engine_methods_convert_to_bitmask/2, get_test_engine/0]). @@ -83,16 +102,187 @@ %% Used by strong_rand_float/0 -define(HALF_DBL_EPSILON, 1.1102230246251565e-16). % math:pow(2, -53) -%%-type ecdsa_digest_type() :: 'md5' | 'sha' | 'sha256' | 'sha384' | 'sha512'. + +%%% ===== BEGIN NEW TYPING ==== + +%%% Basic +-type key_integer() :: integer() | binary(). % Always binary() when used as return value + +%%% Keys +-type rsa_public() :: [key_integer()] . % [E, N] +-type rsa_private() :: [key_integer()] . % [E, N, D] | [E, N, D, P1, P2, E1, E2, C] +-type rsa_params() :: {ModulusSizeInBits::integer(), PublicExponent::key_integer()} . + +-type dss_public() :: [key_integer()] . % [P, Q, G, Y] +-type dss_private() :: [key_integer()] . % [P, Q, G, X] + +-type ecdsa_public() :: key_integer() . +-type ecdsa_private() :: key_integer() . +-type ecdsa_params() :: ec_named_curve() | edwards_curve() | ec_explicit_curve() . + +-type srp_public() :: key_integer() . +-type srp_private() :: key_integer() . +-type srp_gen_params() :: {user,srp_user_gen_params()} | {host,srp_host_gen_params()}. +-type srp_comp_params() :: {user,srp_user_comp_params()} | {host,srp_host_comp_params()}. +-type srp_user_gen_params() :: list(binary() | atom() | list()) . +-type srp_host_gen_params() :: list(binary() | atom() | list()) . +-type srp_user_comp_params() :: list(binary() | atom()) . +-type srp_host_comp_params() :: list(binary() | atom()) . + +-type dh_public() :: key_integer() . +-type dh_private() :: key_integer() . +-type dh_params() :: [key_integer()] . % [P, G] | [P, G, PrivateKeyBitLength] + +-type ecdh_public() :: key_integer() . +-type ecdh_private() :: key_integer() . +-type ecdh_params() :: ec_named_curve() | edwards_curve() | ec_explicit_curve() . + + +%%% Curves + +-type ec_explicit_curve() :: {Field :: ec_field(), + Curve :: ec_curve(), + BasePoint :: binary(), + Order :: binary(), + CoFactor :: none | % FIXME: Really? + binary() + } . + +-type ec_curve() :: {A :: binary(), + B :: binary(), + Seed :: none | binary() + } . + +-type ec_field() :: ec_prime_field() | ec_characteristic_two_field() . + +-type ec_prime_field() :: {prime_field, Prime :: integer()} . +-type ec_characteristic_two_field() :: {characteristic_two_field, M :: integer(), Basis :: ec_basis()} . + +-type ec_basis() :: {tpbasis, K :: non_neg_integer()} + | {ppbasis, K1 :: non_neg_integer(), K2 :: non_neg_integer(), K3 :: non_neg_integer()} + | onbasis . + +-type ec_named_curve() :: brainpoolP160r1 + | brainpoolP160t1 + | brainpoolP192r1 + | brainpoolP192t1 + | brainpoolP224r1 + | brainpoolP224t1 + | brainpoolP256r1 + | brainpoolP256t1 + | brainpoolP320r1 + | brainpoolP320t1 + | brainpoolP384r1 + | brainpoolP384t1 + | brainpoolP512r1 + | brainpoolP512t1 + | c2pnb163v1 + | c2pnb163v2 + | c2pnb163v3 + | c2pnb176v1 + | c2pnb208w1 + | c2pnb272w1 + | c2pnb304w1 + | c2pnb368w1 + | c2tnb191v1 + | c2tnb191v2 + | c2tnb191v3 + | c2tnb239v1 + | c2tnb239v2 + | c2tnb239v3 + | c2tnb359v1 + | c2tnb431r1 + | ipsec3 + | ipsec4 + | prime192v1 + | prime192v2 + | prime192v3 + | prime239v1 + | prime239v2 + | prime239v3 + | prime256v1 + | secp112r1 + | secp112r2 + | secp128r1 + | secp128r2 + | secp160k1 + | secp160r1 + | secp160r2 + | secp192k1 + | secp192r1 + | secp224k1 + | secp224r1 + | secp256k1 + | secp256r1 + | secp384r1 + | secp521r1 + | sect113r1 + | sect113r2 + | sect131r1 + | sect131r2 + | sect163k1 + | sect163r1 + | sect163r2 + | sect193r1 + | sect193r2 + | sect233k1 + | sect233r1 + | sect239k1 + | sect283k1 + | sect283r1 + | sect409k1 + | sect409r1 + | sect571k1 + | sect571r1 + | wtls1 + | wtls10 + | wtls11 + | wtls12 + | wtls3 + | wtls4 + | wtls5 + | wtls6 + | wtls7 + | wtls8 + | wtls9 + . + +-type edwards_curve() :: x25519 + | x448 . + +%%% +-type block_cipher_with_iv() :: cbc_cipher() + | cfb_cipher() + | aes_cbc128 + | aes_cbc256 + | aes_ige256 + | blowfish_ofb64 + | des3_cbf % cfb misspelled + | des_ede3 + | rc2_cbc . + +-type cbc_cipher() :: des_cbc | des3_cbc | aes_cbc | blowfish_cbc . +-type aead_cipher() :: aes_gcm | chacha20_poly1305 . +-type cfb_cipher() :: aes_cfb128 | aes_cfb8 | blowfish_cfb64 | des3_cfb | des_cfb . + +-type block_cipher_without_iv() :: ecb_cipher() . +-type ecb_cipher() :: des_ecb | blowfish_ecb | aes_ecb . + +-type key() :: iodata(). +-type des3_key() :: [key()]. + +%%% +-type rsa_digest_type() :: sha1() | sha2() | md5 | ripemd160 . +-type dss_digest_type() :: sha1() | sha2() . +-type ecdsa_digest_type() :: sha1() | sha2() . + +-type sha1() :: sha . +-type sha2() :: sha224 | sha256 | sha384 | sha512 . +-type sha3() :: sha3_224 | sha3_256 | sha3_384 | sha3_512 . + +-type compatibility_only_hash() :: md5 | md4 . + -type crypto_integer() :: binary() | integer(). -%%-type ec_named_curve() :: atom(). -%%-type ec_point() :: crypto_integer(). -%%-type ec_basis() :: {tpbasis, K :: non_neg_integer()} | {ppbasis, K1 :: non_neg_integer(), K2 :: non_neg_integer(), K3 :: non_neg_integer()} | onbasis. -%%-type ec_field() :: {prime_field, Prime :: integer()} | {characteristic_two_field, M :: integer(), Basis :: ec_basis()}. -%%-type ec_prime() :: {A :: crypto_integer(), B :: crypto_integer(), Seed :: binary() | none}. -%%-type ec_curve_spec() :: {Field :: ec_field(), Prime :: ec_prime(), Point :: crypto_integer(), Order :: integer(), CoFactor :: none | integer()}. -%%-type ec_curve() :: ec_named_curve() | ec_curve_spec(). -%%-type ec_key() :: {Curve :: ec_curve(), PrivKey :: binary() | undefined, PubKey :: ec_point() | undefined}. -compile(no_native). -on_load(on_load/0). @@ -108,14 +298,36 @@ nif_stub_error(Line) -> %% Crypto app version history: %% (no version): Driver implementation %% 2.0 : NIF implementation, requires OTP R14 + +%% When generating documentation from crypto.erl, the macro ?CRYPTO_VSN is not defined. +%% That causes the doc generation to stop... +-ifndef(CRYPTO_VSN). +-define(CRYPTO_VSN, "??"). +-endif. version() -> ?CRYPTO_VSN. +-spec start() -> ok | {error, Reason::term()}. start() -> application:start(crypto). +-spec stop() -> ok | {error, Reason::term()}. stop() -> application:stop(crypto). +-spec supports() -> [Support] + when Support :: {hashs, Hashs} + | {ciphers, Ciphers} + | {public_keys, PKs} + | {macs, Macs} + | {curves, Curves}, + Hashs :: [sha1() | sha2() | sha3() | ripemd160 | compatibility_only_hash()], + Ciphers :: [stream_cipher() + | block_cipher_with_iv() | block_cipher_without_iv() + | aead_cipher() + ], + PKs :: [rsa | dss | ecdsa | dh | ecdh | ec_gf2m], + Macs :: [hmac | cmac | poly1305], + Curves :: [ec_named_curve() | edwards_curve()]. supports()-> {Hashs, PubKeys, Ciphers, Macs, Curves} = algorithms(), [{hashs, Hashs}, @@ -125,95 +337,163 @@ supports()-> {curves, Curves} ]. +-spec info_lib() -> [{Name,VerNum,VerStr}] when Name :: binary(), + VerNum :: integer(), + VerStr :: binary() . info_lib() -> ?nif_stub. -spec info_fips() -> not_supported | not_enabled | enabled. info_fips() -> ?nif_stub. --spec enable_fips_mode(boolean()) -> boolean(). - +-spec enable_fips_mode(Enable) -> Result when Enable :: boolean(), + Result :: boolean(). enable_fips_mode(_) -> ?nif_stub. --spec hash(_, iodata()) -> binary(). +%%%================================================================ +%%% +%%% Hashing +%%% +%%%================================================================ -hash(Hash, Data0) -> - Data = iolist_to_binary(Data0), - MaxBytes = max_bytes(), - hash(Hash, Data, erlang:byte_size(Data), MaxBytes). +-define(HASH_HASH_ALGORITHM, sha1() | sha2() | sha3() | ripemd160 | compatibility_only_hash() ). --spec hash_init('md5'|'md4'|'ripemd160'| - 'sha'|'sha224'|'sha256'|'sha384'|'sha512'| - 'sha3_224' | 'sha3_256' | 'sha3_384' | 'sha3_512') -> any(). +-spec hash(Type, Data) -> Digest when Type :: ?HASH_HASH_ALGORITHM, + Data :: iodata(), + Digest :: binary(). +hash(Type, Data) -> + Data1 = iolist_to_binary(Data), + MaxBytes = max_bytes(), + hash(Type, Data1, erlang:byte_size(Data1), MaxBytes). -hash_init(Hash) -> - notsup_to_error(hash_init_nif(Hash)). +-opaque hash_state() :: reference(). --spec hash_update(_, iodata()) -> any(). +-spec hash_init(Type) -> State when Type :: ?HASH_HASH_ALGORITHM, + State :: hash_state(). +hash_init(Type) -> + notsup_to_error(hash_init_nif(Type)). -hash_update(State, Data0) -> - Data = iolist_to_binary(Data0), +-spec hash_update(State, Data) -> NewState when State :: hash_state(), + NewState :: hash_state(), + Data :: iodata() . +hash_update(Context, Data) -> + Data1 = iolist_to_binary(Data), MaxBytes = max_bytes(), - hash_update(State, Data, erlang:byte_size(Data), MaxBytes). + hash_update(Context, Data1, erlang:byte_size(Data1), MaxBytes). --spec hash_final(_) -> binary(). +-spec hash_final(State) -> Digest when State :: hash_state(), + Digest :: binary(). +hash_final(Context) -> + notsup_to_error(hash_final_nif(Context)). -hash_final(State) -> - notsup_to_error(hash_final_nif(State)). +%%%================================================================ +%%% +%%% MACs (Message Authentication Codes) +%%% +%%%================================================================ +%%%---- HMAC --spec hmac(_, iodata(), iodata()) -> binary(). --spec hmac(_, iodata(), iodata(), integer()) -> binary(). --spec hmac_init(atom(), iodata()) -> binary(). --spec hmac_update(binary(), iodata()) -> binary(). --spec hmac_final(binary()) -> binary(). --spec hmac_final_n(binary(), integer()) -> binary(). +-define(HMAC_HASH_ALGORITHM, sha1() | sha2() | sha3() | compatibility_only_hash()). -hmac(Type, Key, Data0) -> - Data = iolist_to_binary(Data0), - hmac(Type, Key, Data, undefined, erlang:byte_size(Data), max_bytes()). -hmac(Type, Key, Data0, MacSize) -> - Data = iolist_to_binary(Data0), - hmac(Type, Key, Data, MacSize, erlang:byte_size(Data), max_bytes()). +%%%---- hmac/3,4 + +-spec hmac(Type, Key, Data) -> + Mac when Type :: ?HMAC_HASH_ALGORITHM, + Key :: iodata(), + Data :: iodata(), + Mac :: binary() . +hmac(Type, Key, Data) -> + Data1 = iolist_to_binary(Data), + hmac(Type, Key, Data1, undefined, erlang:byte_size(Data1), max_bytes()). + +-spec hmac(Type, Key, Data, MacLength) -> + Mac when Type :: ?HMAC_HASH_ALGORITHM, + Key :: iodata(), + Data :: iodata(), + MacLength :: integer(), + Mac :: binary() . +hmac(Type, Key, Data, MacLength) -> + Data1 = iolist_to_binary(Data), + hmac(Type, Key, Data1, MacLength, erlang:byte_size(Data1), max_bytes()). + +%%%---- hmac_init, hamc_update, hmac_final + +-opaque hmac_state() :: binary(). + +-spec hmac_init(Type, Key) -> + State when Type :: ?HMAC_HASH_ALGORITHM, + Key :: iodata(), + State :: hmac_state() . hmac_init(Type, Key) -> notsup_to_error(hmac_init_nif(Type, Key)). +%%%---- hmac_update + +-spec hmac_update(State, Data) -> NewState when Data :: iodata(), + State :: hmac_state(), + NewState :: hmac_state(). hmac_update(State, Data0) -> Data = iolist_to_binary(Data0), hmac_update(State, Data, erlang:byte_size(Data), max_bytes()). +%%%---- hmac_final + +-spec hmac_final(State) -> Mac when State :: hmac_state(), + Mac :: binary(). hmac_final(Context) -> notsup_to_error(hmac_final_nif(Context)). + +-spec hmac_final_n(State, HashLen) -> Mac when State :: hmac_state(), + HashLen :: integer(), + Mac :: binary(). hmac_final_n(Context, HashLen) -> notsup_to_error(hmac_final_nif(Context, HashLen)). --spec cmac(_, iodata(), iodata()) -> binary(). --spec cmac(_, iodata(), iodata(), integer()) -> binary(). +%%%---- CMAC +-define(CMAC_CIPHER_ALGORITHM, cbc_cipher() | cfb_cipher() | blowfish_cbc | des_ede3 | rc2_cbc ). + +-spec cmac(Type, Key, Data) -> + Mac when Type :: ?CMAC_CIPHER_ALGORITHM, + Key :: iodata(), + Data :: iodata(), + Mac :: binary(). cmac(Type, Key, Data) -> notsup_to_error(cmac_nif(Type, Key, Data)). -cmac(Type, Key, Data, MacSize) -> - erlang:binary_part(cmac(Type, Key, Data), 0, MacSize). --spec poly1305(iodata(), iodata()) -> binary(). +-spec cmac(Type, Key, Data, MacLength) -> + Mac when Type :: ?CMAC_CIPHER_ALGORITHM, + Key :: iodata(), + Data :: iodata(), + MacLength :: integer(), + Mac :: binary(). +cmac(Type, Key, Data, MacLength) -> + erlang:binary_part(cmac(Type, Key, Data), 0, MacLength). + +%%%---- POLY1305 + +-spec poly1305(iodata(), iodata()) -> Mac when Mac :: binary(). poly1305(Key, Data) -> poly1305_nif(Key, Data). -%% Ecrypt/decrypt %%% +%%%================================================================ +%%% +%%% Encrypt/decrypt +%%% +%%%================================================================ + +%%%---- Block ciphers --spec block_encrypt(des_cbc | des_cfb | - des3_cbc | des3_cbf | des3_cfb | des_ede3 | - blowfish_cbc | blowfish_cfb64 | blowfish_ofb64 | - aes_cbc128 | aes_cfb8 | aes_cfb128 | aes_cbc256 | aes_ige256 | - aes_cbc | - rc2_cbc, - Key::iodata(), Ivec::binary(), Data::iodata()) -> binary(); - (aes_gcm | chacha20_poly1305, Key::iodata(), Ivec::binary(), {AAD::binary(), Data::iodata()}) -> {binary(), binary()}; - (aes_gcm, Key::iodata(), Ivec::binary(), {AAD::binary(), Data::iodata(), TagLength::1..16}) -> {binary(), binary()}. +-spec block_encrypt(Type::block_cipher_with_iv(), Key::key()|des3_key(), Ivec::binary(), PlainText::iodata()) -> binary(); + (Type::aead_cipher(), Key::iodata(), Ivec::binary(), {AAD::binary(), PlainText::iodata()}) -> + {binary(), binary()}; + (aes_gcm, Key::iodata(), Ivec::binary(), {AAD::binary(), PlainText::iodata(), TagLength::1..16}) -> + {binary(), binary()}. -block_encrypt(Type, Key, Ivec, Data) when Type =:= des_cbc; +block_encrypt(Type, Key, Ivec, PlainText) when Type =:= des_cbc; Type =:= des_cfb; Type =:= blowfish_cbc; Type =:= blowfish_cfb64; @@ -224,34 +504,28 @@ block_encrypt(Type, Key, Ivec, Data) when Type =:= des_cbc; Type =:= aes_cbc256; Type =:= aes_cbc; Type =:= rc2_cbc -> - block_crypt_nif(Type, Key, Ivec, Data, true); -block_encrypt(Type, Key0, Ivec, Data) when Type =:= des3_cbc; + block_crypt_nif(Type, Key, Ivec, PlainText, true); +block_encrypt(Type, Key0, Ivec, PlainText) when Type =:= des3_cbc; Type =:= des_ede3 -> Key = check_des3_key(Key0), - block_crypt_nif(des_ede3_cbc, Key, Ivec, Data, true); -block_encrypt(des3_cbf, Key0, Ivec, Data) -> + block_crypt_nif(des_ede3_cbc, Key, Ivec, PlainText, true); +block_encrypt(des3_cbf, Key0, Ivec, PlainText) -> % cfb misspelled Key = check_des3_key(Key0), - block_crypt_nif(des_ede3_cbf, Key, Ivec, Data, true); -block_encrypt(des3_cfb, Key0, Ivec, Data) -> + block_crypt_nif(des_ede3_cbf, Key, Ivec, PlainText, true); +block_encrypt(des3_cfb, Key0, Ivec, PlainText) -> Key = check_des3_key(Key0), - block_crypt_nif(des_ede3_cfb, Key, Ivec, Data, true); -block_encrypt(aes_ige256, Key, Ivec, Data) -> - notsup_to_error(aes_ige_crypt_nif(Key, Ivec, Data, true)); -block_encrypt(aes_gcm, Key, Ivec, {AAD, Data}) -> - aes_gcm_encrypt(Key, Ivec, AAD, Data); -block_encrypt(aes_gcm, Key, Ivec, {AAD, Data, TagLength}) -> - aes_gcm_encrypt(Key, Ivec, AAD, Data, TagLength); -block_encrypt(chacha20_poly1305, Key, Ivec, {AAD, Data}) -> - chacha20_poly1305_encrypt(Key, Ivec, AAD, Data). - --spec block_decrypt(des_cbc | des_cfb | - des3_cbc | des3_cbf | des3_cfb | des_ede3 | - blowfish_cbc | blowfish_cfb64 | blowfish_ofb64 | - aes_cbc128 | aes_cfb8 | aes_cfb128 | aes_cbc256 | aes_ige256 | - aes_cbc | - rc2_cbc, - Key::iodata(), Ivec::binary(), Data::iodata()) -> binary(); - (aes_gcm | chacha20_poly1305, Key::iodata(), Ivec::binary(), + block_crypt_nif(des_ede3_cfb, Key, Ivec, PlainText, true); +block_encrypt(aes_ige256, Key, Ivec, PlainText) -> + notsup_to_error(aes_ige_crypt_nif(Key, Ivec, PlainText, true)); +block_encrypt(aes_gcm, Key, Ivec, {AAD, PlainText}) -> + aes_gcm_encrypt(Key, Ivec, AAD, PlainText); +block_encrypt(aes_gcm, Key, Ivec, {AAD, PlainText, TagLength}) -> + aes_gcm_encrypt(Key, Ivec, AAD, PlainText, TagLength); +block_encrypt(chacha20_poly1305, Key, Ivec, {AAD, PlainText}) -> + chacha20_poly1305_encrypt(Key, Ivec, AAD, PlainText). + +-spec block_decrypt(Type::block_cipher_with_iv(), Key::key()|des3_key(), Ivec::binary(), Data::iodata()) -> binary(); + (Type::aead_cipher(), Key::iodata(), Ivec::binary(), {AAD::binary(), Data::iodata(), Tag::binary()}) -> binary() | error. block_decrypt(Type, Key, Ivec, Data) when Type =:= des_cbc; Type =:= des_cfb; @@ -269,7 +543,7 @@ block_decrypt(Type, Key0, Ivec, Data) when Type =:= des3_cbc; Type =:= des_ede3 -> Key = check_des3_key(Key0), block_crypt_nif(des_ede3_cbc, Key, Ivec, Data, false); -block_decrypt(des3_cbf, Key0, Ivec, Data) -> +block_decrypt(des3_cbf, Key0, Ivec, Data) -> % cfb misspelled Key = check_des3_key(Key0), block_crypt_nif(des_ede3_cbf, Key, Ivec, Data, false); block_decrypt(des3_cfb, Key0, Ivec, Data) -> @@ -282,18 +556,23 @@ block_decrypt(aes_gcm, Key, Ivec, {AAD, Data, Tag}) -> block_decrypt(chacha20_poly1305, Key, Ivec, {AAD, Data, Tag}) -> chacha20_poly1305_decrypt(Key, Ivec, AAD, Data, Tag). --spec block_encrypt(des_ecb | blowfish_ecb | aes_ecb, Key::iodata(), Data::iodata()) -> binary(). -block_encrypt(Type, Key, Data) -> - block_crypt_nif(Type, Key, Data, true). --spec block_decrypt(des_ecb | blowfish_ecb | aes_ecb, Key::iodata(), Data::iodata()) -> binary(). +-spec block_encrypt(Type::block_cipher_without_iv(), Key::key(), PlainText::iodata()) -> binary(). + +block_encrypt(Type, Key, PlainText) -> + block_crypt_nif(Type, Key, PlainText, true). + + +-spec block_decrypt(Type::block_cipher_without_iv(), Key::key(), Data::iodata()) -> binary(). block_decrypt(Type, Key, Data) -> block_crypt_nif(Type, Key, Data, false). --spec next_iv(des_cbc | des3_cbc | aes_cbc | aes_ige, Data::iodata()) -> binary(). +-spec next_iv(Type:: cbc_cipher(), Data) -> NextIVec when % Type :: cbc_cipher(), %des_cbc | des3_cbc | aes_cbc | aes_ige, + Data :: iodata(), + NextIVec :: binary(). next_iv(Type, Data) when is_binary(Data) -> IVecSize = case Type of des_cbc -> 8; @@ -308,7 +587,9 @@ next_iv(Type, Data) when is_binary(Data) -> next_iv(Type, Data) when is_list(Data) -> next_iv(Type, list_to_binary(Data)). --spec next_iv(des_cfb, Data::iodata(), Ivec::binary()) -> binary(). +-spec next_iv(des_cfb, Data, IVec) -> NextIVec when Data :: iodata(), + IVec :: binary(), + NextIVec :: binary(). next_iv(des_cfb, Data, IVec) -> IVecAndData = list_to_binary([IVec, Data]), @@ -317,41 +598,57 @@ next_iv(des_cfb, Data, IVec) -> next_iv(Type, Data, _Ivec) -> next_iv(Type, Data). +%%%---- Stream ciphers + +-opaque stream_state() :: {stream_cipher(), reference()}. + +-type stream_cipher() :: rc4 | aes_ctr | chacha20 . + +-spec stream_init(Type, Key, IVec) -> State when Type :: aes_ctr | chacha20, + Key :: iodata(), + IVec :: binary(), + State :: stream_state() . stream_init(aes_ctr, Key, Ivec) -> {aes_ctr, aes_ctr_stream_init(Key, Ivec)}; stream_init(chacha20, Key, Ivec) -> {chacha20, chacha20_stream_init(Key,Ivec)}. +-spec stream_init(Type, Key) -> State when Type :: rc4, + Key :: iodata(), + State :: stream_state() . stream_init(rc4, Key) -> {rc4, notsup_to_error(rc4_set_key(Key))}. +-spec stream_encrypt(State, PlainText) -> {NewState, CipherText} + when State :: stream_state(), + PlainText :: iodata(), + NewState :: stream_state(), + CipherText :: iodata() . stream_encrypt(State, Data0) -> Data = iolist_to_binary(Data0), MaxByts = max_bytes(), stream_crypt(fun do_stream_encrypt/2, State, Data, erlang:byte_size(Data), MaxByts, []). +-spec stream_decrypt(State, CipherText) -> {NewState, PlainText} + when State :: stream_state(), + CipherText :: iodata(), + NewState :: stream_state(), + PlainText :: iodata() . stream_decrypt(State, Data0) -> Data = iolist_to_binary(Data0), MaxByts = max_bytes(), stream_crypt(fun do_stream_decrypt/2, State, Data, erlang:byte_size(Data), MaxByts, []). -%% -%% RAND - pseudo random numbers using RN_ and BN_ functions in crypto lib -%% + +%%%================================================================ +%%% +%%% RAND - pseudo random numbers using RN_ and BN_ functions in crypto lib +%%% +%%%================================================================ -type rand_cache_seed() :: nonempty_improper_list(non_neg_integer(), binary()). --spec strong_rand_bytes(non_neg_integer()) -> binary(). --spec rand_seed() -> rand:state(). --spec rand_seed_s() -> rand:state(). --spec rand_seed_alg(Alg :: atom()) -> - {rand:alg_handler(), - atom() | rand_cache_seed()}. --spec rand_seed_alg_s(Alg :: atom()) -> - {rand:alg_handler(), - atom() | rand_cache_seed()}. --spec rand_uniform(crypto_integer(), crypto_integer()) -> - crypto_integer(). +-spec strong_rand_bytes(N::non_neg_integer()) -> binary(). strong_rand_bytes(Bytes) -> case strong_rand_bytes_nif(Bytes) of false -> erlang:error(low_entropy); @@ -360,16 +657,24 @@ strong_rand_bytes(Bytes) -> strong_rand_bytes_nif(_Bytes) -> ?nif_stub. +-spec rand_seed() -> rand:state(). rand_seed() -> rand:seed(rand_seed_s()). +-spec rand_seed_s() -> rand:state(). rand_seed_s() -> rand_seed_alg_s(?MODULE). +-spec rand_seed_alg(Alg :: atom()) -> + {rand:alg_handler(), + atom() | rand_cache_seed()}. rand_seed_alg(Alg) -> rand:seed(rand_seed_alg_s(Alg)). -define(CRYPTO_CACHE_BITS, 56). +-spec rand_seed_alg_s(Alg :: atom()) -> + {rand:alg_handler(), + atom() | rand_cache_seed()}. rand_seed_alg_s(?MODULE) -> {#{ type => ?MODULE, bits => 64, @@ -427,7 +732,9 @@ strong_rand_float() -> WholeRange = strong_rand_range(1 bsl 53), ?HALF_DBL_EPSILON * bytes_to_integer(WholeRange). -rand_uniform(From,To) when is_binary(From), is_binary(To) -> +-spec rand_uniform(crypto_integer(), crypto_integer()) -> + crypto_integer(). +rand_uniform(From, To) when is_binary(From), is_binary(To) -> case rand_uniform_nif(From,To) of <<Len:32/integer, MSB, Rest/binary>> when MSB > 127 -> <<(Len + 1):32/integer, 0, MSB, Rest/binary>>; @@ -462,116 +769,228 @@ rand_seed(Seed) when is_binary(Seed) -> rand_seed_nif(_Seed) -> ?nif_stub. --spec mod_pow(binary()|integer(), binary()|integer(), binary()|integer()) -> binary() | error. -mod_pow(Base, Exponent, Prime) -> - case mod_exp_nif(ensure_int_as_bin(Base), ensure_int_as_bin(Exponent), ensure_int_as_bin(Prime), 0) of - <<0>> -> error; - R -> R - end. +%%%================================================================ +%%% +%%% Sign/verify +%%% +%%%================================================================ +-type pk_sign_verify_algs() :: rsa | dss | ecdsa . -verify(Algorithm, Type, Data, Signature, Key) -> - verify(Algorithm, Type, Data, Signature, Key, []). +-type pk_sign_verify_opts() :: [ rsa_sign_verify_opt() ] . + +-type rsa_sign_verify_opt() :: {rsa_padding, rsa_sign_verify_padding()} + | {rsa_pss_saltlen, integer()} . + +-type rsa_sign_verify_padding() :: rsa_pkcs1_padding | rsa_pkcs1_pss_padding + | rsa_x931_padding | rsa_no_padding + . -%% Backwards compatible -verify(Algorithm = dss, none, Digest, Signature, Key, Options) -> - verify(Algorithm, sha, {digest, Digest}, Signature, Key, Options); -verify(Algorithm, Type, Data, Signature, Key, Options) -> - case pkey_verify_nif(Algorithm, Type, Data, Signature, format_pkey(Algorithm, Key), Options) of - notsup -> erlang:error(notsup); - Boolean -> Boolean - end. +%%%---------------------------------------------------------------- +%%% Sign + +-spec sign(Algorithm, DigestType, Msg, Key) + -> Signature + when Algorithm :: pk_sign_verify_algs(), + DigestType :: rsa_digest_type() + | dss_digest_type() + | ecdsa_digest_type(), + Msg :: binary() | {digest,binary()}, + Key :: rsa_private() + | dss_private() + | [ecdsa_private()|ecdsa_params()] + | engine_key_ref(), + Signature :: binary() . sign(Algorithm, Type, Data, Key) -> sign(Algorithm, Type, Data, Key, []). -%% Backwards compatible -sign(Algorithm = dss, none, Digest, Key, Options) -> - sign(Algorithm, sha, {digest, Digest}, Key, Options); -sign(Algorithm, Type, Data, Key, Options) -> + +-spec sign(Algorithm, DigestType, Msg, Key, Options) + -> Signature + when Algorithm :: pk_sign_verify_algs(), + DigestType :: rsa_digest_type() + | dss_digest_type() + | ecdsa_digest_type() + | none, + Msg :: binary() | {digest,binary()}, + Key :: rsa_private() + | dss_private() + | [ecdsa_private() | ecdsa_params()] + | engine_key_ref(), + Options :: pk_sign_verify_opts(), + Signature :: binary() . + +sign(Algorithm0, Type0, Data, Key, Options) -> + {Algorithm, Type} = sign_verify_compatibility(Algorithm0, Type0, Data), case pkey_sign_nif(Algorithm, Type, Data, format_pkey(Algorithm, Key), Options) of error -> erlang:error(badkey, [Algorithm, Type, Data, Key, Options]); notsup -> erlang:error(notsup); Signature -> Signature end. +pkey_sign_nif(_Algorithm, _Type, _Digest, _Key, _Options) -> ?nif_stub. +%%%---------------------------------------------------------------- +%%% Verify + +-spec verify(Algorithm, DigestType, Msg, Signature, Key) + -> Result + when Algorithm :: pk_sign_verify_algs(), + DigestType :: rsa_digest_type() + | dss_digest_type() + | ecdsa_digest_type(), + Msg :: binary() | {digest,binary()}, + Signature :: binary(), + Key :: rsa_private() + | dss_private() + | [ecdsa_private() | ecdsa_params()] + | engine_key_ref(), + Result :: boolean(). --type key_id() :: string() | binary() . --type password() :: string() | binary() . - --type engine_key_ref() :: #{engine := engine_ref(), - key_id := key_id(), - password => password(), - term() => term() - }. - --type pk_algs() :: rsa | ecdsa | dss . --type pk_key() :: engine_key_ref() | [integer() | binary()] . --type pk_opt() :: list() | rsa_padding() . - --spec public_encrypt(pk_algs(), binary(), pk_key(), pk_opt()) -> binary(). --spec public_decrypt(pk_algs(), binary(), pk_key(), pk_opt()) -> binary(). --spec private_encrypt(pk_algs(), binary(), pk_key(), pk_opt()) -> binary(). --spec private_decrypt(pk_algs(), binary(), pk_key(), pk_opt()) -> binary(). +verify(Algorithm, Type, Data, Signature, Key) -> + verify(Algorithm, Type, Data, Signature, Key, []). -public_encrypt(Algorithm, In, Key, Options) when is_list(Options) -> - case pkey_crypt_nif(Algorithm, In, format_pkey(Algorithm, Key), Options, false, true) of - error -> erlang:error(encrypt_failed, [Algorithm, In, Key, Options]); +-spec verify(Algorithm, DigestType, Msg, Signature, Key, Options) + -> Result + when Algorithm :: pk_sign_verify_algs(), + DigestType :: rsa_digest_type() + | dss_digest_type() + | ecdsa_digest_type(), + Msg :: binary() | {digest,binary()}, + Signature :: binary(), + Key :: rsa_public() + | dss_public() + | [ecdsa_public() | ecdsa_params()] + | engine_key_ref(), + Options :: pk_sign_verify_opts(), + Result :: boolean(). + +verify(Algorithm0, Type0, Data, Signature, Key, Options) -> + {Algorithm, Type} = sign_verify_compatibility(Algorithm0, Type0, Data), + case pkey_verify_nif(Algorithm, Type, Data, Signature, format_pkey(Algorithm, Key), Options) of notsup -> erlang:error(notsup); - Out -> Out - end; -%% Backwards compatible -public_encrypt(Algorithm = rsa, In, Key, Padding) when is_atom(Padding) -> - public_encrypt(Algorithm, In, Key, [{rsa_padding, Padding}]). + Boolean -> Boolean + end. -private_decrypt(Algorithm, In, Key, Options) when is_list(Options) -> - case pkey_crypt_nif(Algorithm, In, format_pkey(Algorithm, Key), Options, true, false) of - error -> erlang:error(decrypt_failed, [Algorithm, In, Key, Options]); - notsup -> erlang:error(notsup); - Out -> Out - end; -%% Backwards compatible -private_decrypt(Algorithm = rsa, In, Key, Padding) when is_atom(Padding) -> - private_decrypt(Algorithm, In, Key, [{rsa_padding, Padding}]). +pkey_verify_nif(_Algorithm, _Type, _Data, _Signature, _Key, _Options) -> ?nif_stub. -private_encrypt(Algorithm, In, Key, Options) when is_list(Options) -> - case pkey_crypt_nif(Algorithm, In, format_pkey(Algorithm, Key), Options, true, true) of - error -> erlang:error(encrypt_failed, [Algorithm, In, Key, Options]); - notsup -> erlang:error(notsup); - Out -> Out - end; -%% Backwards compatible -private_encrypt(Algorithm = rsa, In, Key, Padding) when is_atom(Padding) -> - private_encrypt(Algorithm, In, Key, [{rsa_padding, Padding}]). +%% Backwards compatible: +sign_verify_compatibility(dss, none, Digest) -> + {sha, {digest, Digest}}; +sign_verify_compatibility(Algorithm0, Type0, _Digest) -> + {Algorithm0, Type0}. -public_decrypt(Algorithm, In, Key, Options) when is_list(Options) -> - case pkey_crypt_nif(Algorithm, In, format_pkey(Algorithm, Key), Options, false, false) of - error -> erlang:error(decrypt_failed, [Algorithm, In, Key, Options]); +%%%================================================================ +%%% +%%% Public/private encrypt/decrypt +%%% +%%% Only rsa works so far (although ecdsa | dss should do it) +%%%================================================================ +-type pk_encrypt_decrypt_algs() :: rsa . + +-type pk_encrypt_decrypt_opts() :: [rsa_opt()] | rsa_compat_opts(). + +-type rsa_compat_opts() :: [{rsa_pad, rsa_padding()}] + | rsa_padding() . + +-type rsa_padding() :: rsa_pkcs1_padding + | rsa_pkcs1_oaep_padding + | rsa_sslv23_padding + | rsa_x931_padding + | rsa_no_padding. + +-type rsa_opt() :: {rsa_padding, rsa_padding()} + | {signature_md, atom()} + | {rsa_mgf1_md, sha} + | {rsa_oaep_label, binary()} + | {rsa_oaep_md, sha} . + +%%%---- Encrypt with public key + +-spec public_encrypt(Algorithm, PlainText, PublicKey, Options) -> + CipherText when Algorithm :: pk_encrypt_decrypt_algs(), + PlainText :: binary(), + PublicKey :: rsa_public() | engine_key_ref(), + Options :: pk_encrypt_decrypt_opts(), + CipherText :: binary(). +public_encrypt(Algorithm, PlainText, PublicKey, Options) -> + pkey_crypt(Algorithm, PlainText, PublicKey, Options, false, true). + +%%%---- Decrypt with private key + +-spec private_decrypt(Algorithm, CipherText, PrivateKey, Options) -> + PlainText when Algorithm :: pk_encrypt_decrypt_algs(), + CipherText :: binary(), + PrivateKey :: rsa_private() | engine_key_ref(), + Options :: pk_encrypt_decrypt_opts(), + PlainText :: binary() . +private_decrypt(Algorithm, CipherText, PrivateKey, Options) -> + pkey_crypt(Algorithm, CipherText, PrivateKey, Options, true, false). + +%%%---- Encrypt with private key + +-spec private_encrypt(Algorithm, PlainText, PrivateKey, Options) -> + CipherText when Algorithm :: pk_encrypt_decrypt_algs(), + PlainText :: binary(), + PrivateKey :: rsa_private() | engine_key_ref(), + Options :: pk_encrypt_decrypt_opts(), + CipherText :: binary(). +private_encrypt(Algorithm, PlainText, PrivateKey, Options) -> + pkey_crypt(Algorithm, PlainText, PrivateKey, Options, true, true). + +%%%---- Decrypt with public key + +-spec public_decrypt(Algorithm, CipherText, PublicKey, Options) -> + PlainText when Algorithm :: pk_encrypt_decrypt_algs(), + CipherText :: binary(), + PublicKey :: rsa_public() | engine_key_ref(), + Options :: pk_encrypt_decrypt_opts(), + PlainText :: binary() . +public_decrypt(Algorithm, CipherText, PublicKey, Options) -> + pkey_crypt(Algorithm, CipherText, PublicKey, Options, false, false). + +%%%---- Call the nif, but fix a compatibility issue first + +%% Backwards compatible (rsa_pad -> rsa_padding is handled by the pkey_crypt_nif): +pkey_crypt(rsa, Text, Key, Padding, PubPriv, EncDec) when is_atom(Padding) -> + pkey_crypt(rsa, Text, Key, [{rsa_padding, Padding}], PubPriv, EncDec); + +pkey_crypt(Alg, Text, Key, Options, PubPriv, EncDec) -> + case pkey_crypt_nif(Alg, Text, format_pkey(Alg,Key), Options, PubPriv, EncDec) of + error when EncDec==true -> erlang:error(encrypt_failed, [Alg, Text, Key, Options]); + error when EncDec==false -> erlang:error(decrypt_failed, [Alg, Text, Key, Options]); notsup -> erlang:error(notsup); Out -> Out - end; -%% Backwards compatible -public_decrypt(Algorithm = rsa, In, Key, Padding) when is_atom(Padding) -> - public_decrypt(Algorithm, In, Key, [{rsa_padding, Padding}]). - - -%% -%% XOR - xor to iolists and return a binary -%% NB doesn't check that they are the same size, just concatenates -%% them and sends them to the driver -%% --spec exor(iodata(), iodata()) -> binary(). + end. -exor(Bin1, Bin2) -> - Data1 = iolist_to_binary(Bin1), - Data2 = iolist_to_binary(Bin2), - MaxBytes = max_bytes(), - exor(Data1, Data2, erlang:byte_size(Data1), MaxBytes, []). +pkey_crypt_nif(_Algorithm, _In, _Key, _Options, _IsPrivate, _IsEncrypt) -> ?nif_stub. +%%%================================================================ +%%% +%%% +%%% +%%%================================================================ + +-spec generate_key(Type, Params) + -> {PublicKey, PrivKeyOut} + when Type :: dh | ecdh | rsa | srp, + PublicKey :: dh_public() | ecdh_public() | rsa_public() | srp_public(), + PrivKeyOut :: dh_private() | ecdh_private() | rsa_private() | {srp_public(),srp_private()}, + Params :: dh_params() | ecdh_params() | rsa_params() | srp_gen_params() + . generate_key(Type, Params) -> generate_key(Type, Params, undefined). +-spec generate_key(Type, Params, PrivKeyIn) + -> {PublicKey, PrivKeyOut} + when Type :: dh | ecdh | rsa | srp, + PublicKey :: dh_public() | ecdh_public() | rsa_public() | srp_public(), + PrivKeyIn :: undefined | dh_private() | ecdh_private() | rsa_private() | {srp_public(),srp_private()}, + PrivKeyOut :: dh_private() | ecdh_private() | rsa_private() | {srp_public(),srp_private()}, + Params :: dh_params() | ecdh_params() | rsa_params() | srp_comp_params() + . + generate_key(dh, DHParameters0, PrivateKey) -> {DHParameters, Len} = case DHParameters0 of @@ -618,6 +1037,14 @@ generate_key(ecdh, Curve, PrivKey) -> evp_generate_key_nif(_Curve) -> ?nif_stub. +-spec compute_key(Type, OthersPublicKey, MyPrivateKey, Params) + -> SharedSecret + when Type :: dh | ecdh | srp, + SharedSecret :: binary(), + OthersPublicKey :: dh_public() | ecdh_public() | srp_public(), + MyPrivateKey :: dh_private() | ecdh_private() | {srp_public(),srp_private()}, + Params :: dh_params() | ecdh_params() | srp_comp_params() + . compute_key(dh, OthersPublicKey, MyPrivateKey, DHParameters) -> case dh_compute_key_nif(ensure_int_as_bin(OthersPublicKey), @@ -670,9 +1097,59 @@ compute_key(ecdh, Others, My, Curve) -> evp_compute_key_nif(_Curve, _OthersBin, _MyBin) -> ?nif_stub. -%%====================================================================== -%% Engine functions -%%====================================================================== + +%%%================================================================ +%%% +%%% XOR - xor to iolists and return a binary +%%% NB doesn't check that they are the same size, just concatenates +%%% them and sends them to the driver +%%% +%%%================================================================ + +-spec exor(iodata(), iodata()) -> binary(). + +exor(Bin1, Bin2) -> + Data1 = iolist_to_binary(Bin1), + Data2 = iolist_to_binary(Bin2), + MaxBytes = max_bytes(), + exor(Data1, Data2, erlang:byte_size(Data1), MaxBytes, []). + + +%%%================================================================ +%%% +%%% Exponentiation modulo +%%% +%%%================================================================ + +-spec mod_pow(N, P, M) -> Result when N :: binary() | integer(), + P :: binary() | integer(), + M :: binary() | integer(), + Result :: binary() | error . +mod_pow(Base, Exponent, Prime) -> + case mod_exp_nif(ensure_int_as_bin(Base), ensure_int_as_bin(Exponent), ensure_int_as_bin(Prime), 0) of + <<0>> -> error; + R -> R + end. + +%%%====================================================================== +%%% +%%% Engine functions +%%% +%%%====================================================================== + +%%%---- Refering to keys stored in an engine: +-type key_id() :: string() | binary() . +-type password() :: string() | binary() . + +-type engine_key_ref() :: #{engine := engine_ref(), + key_id := key_id(), + password => password(), + term() => term() + }. + +%%%---- Commands: +-type engine_cmnd() :: {unicode:chardata(), unicode:chardata()}. + %%---------------------------------------------------------------------- %% Function: engine_get_all_methods/0 %%---------------------------------------------------------------------- @@ -684,18 +1161,18 @@ evp_compute_key_nif(_Curve, _OthersBin, _MyBin) -> ?nif_stub. -type engine_ref() :: term(). --spec engine_get_all_methods() -> - [engine_method_type()]. +-spec engine_get_all_methods() -> Result when Result :: [engine_method_type()]. engine_get_all_methods() -> notsup_to_error(engine_get_all_methods_nif()). %%---------------------------------------------------------------------- %% Function: engine_load/3 %%---------------------------------------------------------------------- --spec engine_load(EngineId::unicode:chardata(), - PreCmds::[{unicode:chardata(), unicode:chardata()}], - PostCmds::[{unicode:chardata(), unicode:chardata()}]) -> - {ok, Engine::engine_ref()} | {error, Reason::term()}. +-spec engine_load(EngineId, PreCmds, PostCmds) -> + Result when EngineId::unicode:chardata(), + PreCmds::[engine_cmnd()], + PostCmds::[engine_cmnd()], + Result :: {ok, Engine::engine_ref()} | {error, Reason::term()}. engine_load(EngineId, PreCmds, PostCmds) when is_list(PreCmds), is_list(PostCmds) -> engine_load(EngineId, PreCmds, PostCmds, engine_get_all_methods()). @@ -703,11 +1180,12 @@ engine_load(EngineId, PreCmds, PostCmds) when is_list(PreCmds), %%---------------------------------------------------------------------- %% Function: engine_load/4 %%---------------------------------------------------------------------- --spec engine_load(EngineId::unicode:chardata(), - PreCmds::[{unicode:chardata(), unicode:chardata()}], - PostCmds::[{unicode:chardata(), unicode:chardata()}], - EngineMethods::[engine_method_type()]) -> - {ok, Engine::term()} | {error, Reason::term()}. +-spec engine_load(EngineId, PreCmds, PostCmds, EngineMethods) -> + Result when EngineId::unicode:chardata(), + PreCmds::[engine_cmnd()], + PostCmds::[engine_cmnd()], + EngineMethods::[engine_method_type()], + Result :: {ok, Engine::engine_ref()} | {error, Reason::term()}. engine_load(EngineId, PreCmds, PostCmds, EngineMethods) when is_list(PreCmds), is_list(PostCmds) -> try @@ -752,13 +1230,14 @@ engine_load_2(Engine, PostCmds, EngineMethods) -> %%---------------------------------------------------------------------- %% Function: engine_unload/1 %%---------------------------------------------------------------------- --spec engine_unload(Engine::term()) -> - ok | {error, Reason::term()}. +-spec engine_unload(Engine) -> Result when Engine :: engine_ref(), + Result :: ok | {error, Reason::term()}. engine_unload(Engine) -> engine_unload(Engine, engine_get_all_methods()). --spec engine_unload(Engine::term(), EngineMethods::[engine_method_type()]) -> - ok | {error, Reason::term()}. +-spec engine_unload(Engine, EngineMethods) -> Result when Engine :: engine_ref(), + EngineMethods :: [engine_method_type()], + Result :: ok | {error, Reason::term()}. engine_unload(Engine, EngineMethods) -> try [ok = engine_nif_wrapper(engine_unregister_nif(Engine, engine_method_atom_to_int(Method))) || @@ -775,6 +1254,8 @@ engine_unload(Engine, EngineMethods) -> %%---------------------------------------------------------------------- %% Function: engine_by_id/1 %%---------------------------------------------------------------------- +-spec engine_by_id(EngineId) -> Result when EngineId :: unicode:chardata(), + Result :: {ok, Engine::engine_ref()} | {error, Reason::term()} . engine_by_id(EngineId) -> try notsup_to_error(engine_by_id_nif(ensure_bin_chardata(EngineId))) @@ -786,32 +1267,39 @@ engine_by_id(EngineId) -> %%---------------------------------------------------------------------- %% Function: engine_add/1 %%---------------------------------------------------------------------- +-spec engine_add(Engine) -> Result when Engine :: engine_ref(), + Result :: ok | {error, Reason::term()} . engine_add(Engine) -> notsup_to_error(engine_add_nif(Engine)). %%---------------------------------------------------------------------- %% Function: engine_remove/1 %%---------------------------------------------------------------------- +-spec engine_remove(Engine) -> Result when Engine :: engine_ref(), + Result :: ok | {error, Reason::term()} . engine_remove(Engine) -> notsup_to_error(engine_remove_nif(Engine)). %%---------------------------------------------------------------------- %% Function: engine_get_id/1 %%---------------------------------------------------------------------- +-spec engine_get_id(Engine) -> EngineId when Engine :: engine_ref(), + EngineId :: unicode:chardata(). engine_get_id(Engine) -> notsup_to_error(engine_get_id_nif(Engine)). %%---------------------------------------------------------------------- %% Function: engine_get_name/1 %%---------------------------------------------------------------------- +-spec engine_get_name(Engine) -> EngineName when Engine :: engine_ref(), + EngineName :: unicode:chardata(). engine_get_name(Engine) -> notsup_to_error(engine_get_name_nif(Engine)). %%---------------------------------------------------------------------- %% Function: engine_list/0 %%---------------------------------------------------------------------- --spec engine_list() -> - [EngineId::binary()]. +-spec engine_list() -> Result when Result :: [EngineId::unicode:chardata()]. engine_list() -> case notsup_to_error(engine_get_first_nif()) of {ok, <<>>} -> @@ -841,21 +1329,23 @@ engine_list(Engine0, IdList) -> %%---------------------------------------------------------------------- %% Function: engine_ctrl_cmd_string/3 %%---------------------------------------------------------------------- --spec engine_ctrl_cmd_string(Engine::term(), - CmdName::unicode:chardata(), - CmdArg::unicode:chardata()) -> - ok | {error, Reason::term()}. +-spec engine_ctrl_cmd_string(Engine, CmdName, CmdArg) -> + Result when Engine::term(), + CmdName::unicode:chardata(), + CmdArg::unicode:chardata(), + Result :: ok | {error, Reason::term()}. engine_ctrl_cmd_string(Engine, CmdName, CmdArg) -> engine_ctrl_cmd_string(Engine, CmdName, CmdArg, false). %%---------------------------------------------------------------------- %% Function: engine_ctrl_cmd_string/4 %%---------------------------------------------------------------------- --spec engine_ctrl_cmd_string(Engine::term(), - CmdName::unicode:chardata(), - CmdArg::unicode:chardata(), - Optional::boolean()) -> - ok | {error, Reason::term()}. +-spec engine_ctrl_cmd_string(Engine, CmdName, CmdArg, Optional) -> + Result when Engine::term(), + CmdName::unicode:chardata(), + CmdArg::unicode:chardata(), + Optional::boolean(), + Result :: ok | {error, Reason::term()}. engine_ctrl_cmd_string(Engine, CmdName, CmdArg, Optional) -> case engine_ctrl_cmd_strings_nif(Engine, ensure_bin_cmds([{CmdName, CmdArg}]), @@ -872,6 +1362,10 @@ engine_ctrl_cmd_string(Engine, CmdName, CmdArg, Optional) -> %% Function: ensure_engine_loaded/2 %% Special version of load that only uses dynamic engine to load %%---------------------------------------------------------------------- +-spec ensure_engine_loaded(EngineId, LibPath) -> + Result when EngineId :: unicode:chardata(), + LibPath :: unicode:chardata(), + Result :: {ok, Engine::engine_ref()} | {error, Reason::term()}. ensure_engine_loaded(EngineId, LibPath) -> ensure_engine_loaded(EngineId, LibPath, engine_get_all_methods()). @@ -879,6 +1373,11 @@ ensure_engine_loaded(EngineId, LibPath) -> %% Function: ensure_engine_loaded/3 %% Special version of load that only uses dynamic engine to load %%---------------------------------------------------------------------- +-spec ensure_engine_loaded(EngineId, LibPath, EngineMethods) -> + Result when EngineId :: unicode:chardata(), + LibPath :: unicode:chardata(), + EngineMethods :: [engine_method_type()], + Result :: {ok, Engine::engine_ref()} | {error, Reason::term()}. ensure_engine_loaded(EngineId, LibPath, EngineMethods) -> try List = crypto:engine_list(), @@ -930,12 +1429,18 @@ ensure_engine_loaded_2(Engine, Methods) -> %%---------------------------------------------------------------------- %% Function: ensure_engine_unloaded/1 %%---------------------------------------------------------------------- +-spec ensure_engine_unloaded(Engine) -> Result when Engine :: engine_ref(), + Result :: ok | {error, Reason::term()}. ensure_engine_unloaded(Engine) -> ensure_engine_unloaded(Engine, engine_get_all_methods()). %%---------------------------------------------------------------------- %% Function: ensure_engine_unloaded/2 %%---------------------------------------------------------------------- +-spec ensure_engine_unloaded(Engine, EngineMethods) -> + Result when Engine :: engine_ref(), + EngineMethods :: [engine_method_type()], + Result :: ok | {error, Reason::term()}. ensure_engine_unloaded(Engine, EngineMethods) -> case engine_remove(Engine) of ok -> @@ -1010,9 +1515,13 @@ path2bin(Path) when is_list(Path) -> Bin end. -%%-------------------------------------------------------------------- +%%%================================================================ +%%%================================================================ +%%% %%% Internal functions -%%-------------------------------------------------------------------- +%%% +%%%================================================================ + max_bytes() -> ?MAX_BYTES_TO_NIF. @@ -1151,14 +1660,6 @@ do_stream_decrypt({chacha20, State0}, Data) -> %% %% AES - in counter mode (CTR) with state maintained for multi-call streaming %% --type ctr_state() :: { iodata(), binary(), binary(), integer() } | binary(). - --spec aes_ctr_stream_init(iodata(), binary()) -> ctr_state(). --spec aes_ctr_stream_encrypt(ctr_state(), binary()) -> - { ctr_state(), binary() }. --spec aes_ctr_stream_decrypt(ctr_state(), binary()) -> - { ctr_state(), binary() }. - aes_ctr_stream_init(_Key, _IVec) -> ?nif_stub. aes_ctr_stream_encrypt(_State, _Data) -> ?nif_stub. aes_ctr_stream_decrypt(_State, _Cipher) -> ?nif_stub. @@ -1172,11 +1673,6 @@ rc4_encrypt_with_state(_State, _Data) -> ?nif_stub. %% %% CHACHA20 - stream cipher %% --type chacha20_state() :: term(). --spec chacha20_stream_init(iodata(), binary()) -> chacha20_state(). --spec chacha20_stream_encrypt(chacha20_state(), binary()) -> {chacha20_state(), binary()}. --spec chacha20_stream_decrypt(chacha20_state(), binary()) -> {chacha20_state(), binary()}. - chacha20_stream_init(_Key, _IVec) -> ?nif_stub. chacha20_stream_encrypt(_State, _Data) -> ?nif_stub. chacha20_stream_decrypt(_State, _Data) -> ?nif_stub. @@ -1247,11 +1743,6 @@ srp_user_secret_nif(_A, _U, _B, _Multiplier, _Generator, _Exponent, _Prime) -> ? srp_value_B_nif(_Multiplier, _Verifier, _Generator, _Exponent, _Prime) -> ?nif_stub. -%% Digital signatures -------------------------------------------------------------------- - -pkey_sign_nif(_Algorithm, _Type, _Digest, _Key, _Options) -> ?nif_stub. -pkey_verify_nif(_Algorithm, _Type, _Data, _Signature, _Key, _Options) -> ?nif_stub. - %% Public Keys -------------------------------------------------------------------- %% RSA Rivest-Shamir-Adleman functions %% @@ -1273,13 +1764,20 @@ ec_key_generate(_Curve, _Key) -> ?nif_stub. ecdh_compute_key_nif(_Others, _Curve, _My) -> ?nif_stub. +-spec ec_curves() -> [EllipticCurve] when EllipticCurve :: ec_named_curve() | edwards_curve() . + ec_curves() -> crypto_ec_curves:curves(). +-spec ec_curve(CurveName) -> ExplicitCurve when CurveName :: ec_named_curve(), + ExplicitCurve :: ec_explicit_curve() . ec_curve(X) -> crypto_ec_curves:curve(X). +-spec privkey_to_pubkey(Type, EnginePrivateKeyRef) -> PublicKey when Type :: rsa | dss, + EnginePrivateKeyRef :: engine_key_ref(), + PublicKey :: rsa_public() | dss_public() . privkey_to_pubkey(Alg, EngineMap) when Alg == rsa; Alg == dss; Alg == ecdsa -> try privkey_to_pubkey_nif(Alg, format_pkey(Alg,EngineMap)) of @@ -1305,10 +1803,16 @@ term_to_nif_prime({prime_field, Prime}) -> {prime_field, ensure_int_as_bin(Prime)}; term_to_nif_prime(PrimeField) -> PrimeField. + term_to_nif_curve({A, B, Seed}) -> {ensure_int_as_bin(A), ensure_int_as_bin(B), Seed}. + nif_curve_params({PrimeField, Curve, BasePoint, Order, CoFactor}) -> - {term_to_nif_prime(PrimeField), term_to_nif_curve(Curve), ensure_int_as_bin(BasePoint), ensure_int_as_bin(Order), ensure_int_as_bin(CoFactor)}; + {term_to_nif_prime(PrimeField), + term_to_nif_curve(Curve), + ensure_int_as_bin(BasePoint), + ensure_int_as_bin(Order), + ensure_int_as_bin(CoFactor)}; nif_curve_params(Curve) when is_atom(Curve) -> %% named curve case Curve of @@ -1348,6 +1852,7 @@ int_to_bin_neg(-1, Ds=[MSB|_]) when MSB >= 16#80 -> int_to_bin_neg(X,Ds) -> int_to_bin_neg(X bsr 8, [(X band 255)|Ds]). +-spec bytes_to_integer(binary()) -> integer() . bytes_to_integer(Bin) -> bin_to_int(Bin). @@ -1395,9 +1900,6 @@ format_pwd(M) -> M. %%-------------------------------------------------------------------- %% --type rsa_padding() :: 'rsa_pkcs1_padding' | 'rsa_pkcs1_oaep_padding' | 'rsa_no_padding'. - -pkey_crypt_nif(_Algorithm, _In, _Key, _Options, _IsPrivate, _IsEncrypt) -> ?nif_stub. %% large integer in a binary with 32bit length %% MP representaion (SSH2) |