From 0a833d0339fe5bb4c26c30430d74f83d7f2b6519 Mon Sep 17 00:00:00 2001
From: Hans Nilsson <hans@erlang.org>
Date: Wed, 22 Aug 2018 16:50:15 +0200
Subject: crypto: A user's guide chapter on algorithm details Such as
 keylengths, blocksizes and IV lengths are hard to find otherwise

Conflicts:
	lib/crypto/doc/src/crypto.xml
---
 lib/crypto/doc/src/Makefile              |   2 +-
 lib/crypto/doc/src/algorithm_details.xml | 290 +++++++++++++++++++++++++++++++
 lib/crypto/doc/src/usersguide.xml        |   1 +
 3 files changed, 292 insertions(+), 1 deletion(-)
 create mode 100644 lib/crypto/doc/src/algorithm_details.xml

(limited to 'lib')

diff --git a/lib/crypto/doc/src/Makefile b/lib/crypto/doc/src/Makefile
index 2148062e78..3203324954 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
 
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/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>
-- 
cgit v1.2.3


From fa60c386364e4a1852151a56ec6942e394545983 Mon Sep 17 00:00:00 2001
From: Hans Nilsson <hans@erlang.org>
Date: Tue, 28 Aug 2018 16:04:42 +0200
Subject: crypto: Setup for doc generation

---
 lib/crypto/doc/specs/.gitignore | 1 +
 lib/crypto/doc/src/Makefile     | 7 +++++++
 lib/crypto/doc/src/specs.xml    | 4 ++++
 3 files changed, 12 insertions(+)
 create mode 100644 lib/crypto/doc/specs/.gitignore
 create mode 100644 lib/crypto/doc/src/specs.xml

(limited to 'lib')

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 3203324954..cbcafb7375 100644
--- a/lib/crypto/doc/src/Makefile
+++ b/lib/crypto/doc/src/Makefile
@@ -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/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>
-- 
cgit v1.2.3


From 35848c8ba5968b0d9aec3f7aaac6d31000e4da15 Mon Sep 17 00:00:00 2001
From: Hans Nilsson <hans@erlang.org>
Date: Tue, 28 Aug 2018 16:07:21 +0200
Subject: crypto: Rework -type and -spec Check code and documentation and write
 -type/-spec or adjust existing. Prepare for doc generation

---
 lib/crypto/src/crypto.erl | 976 +++++++++++++++++++++++++++++++++++-----------
 1 file changed, 739 insertions(+), 237 deletions(-)

(limited to 'lib')

diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index 17351d10ea..a841f0f168 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,6 +337,9 @@ 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.
@@ -135,85 +350,150 @@ info_fips() -> ?nif_stub.
 
 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() ] .
 
-%% 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.
+-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
+                                   .
+
+
+%%%----------------------------------------------------------------
+%%% 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)
-- 
cgit v1.2.3


From cb654518a4fa58fa65f46e1386ff91c6375f6f5a Mon Sep 17 00:00:00 2001
From: Hans Nilsson <hans@erlang.org>
Date: Tue, 28 Aug 2018 16:08:13 +0200
Subject: crypto: Generate refman from types and specs and fix links in engine
 chapter for generated crypto module refman

---
 lib/crypto/doc/src/crypto.xml      | 1104 ++++++++++++++++--------------------
 lib/crypto/doc/src/engine_keys.xml |    2 +-
 2 files changed, 481 insertions(+), 625 deletions(-)

(limited to 'lib')

diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml
index 4289bd4a64..9d436847ac 100644
--- a/lib/crypto/doc/src/crypto.xml
+++ b/lib/crypto/doc/src/crypto.xml
@@ -46,6 +46,12 @@
         <p>Block ciphers - <url href="http://csrc.nist.gov/groups/ST/toolkit/block_ciphers.html"> </url> DES and AES in
         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>
@@ -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,17 @@
     </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>
         <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 +654,8 @@
     </func>
 
     <func>
-      <name>info_lib() -> [{Name,VerNum,VerStr}]</name>
+      <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 +668,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 +705,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 +719,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 +730,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 +746,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 +758,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 +784,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 +800,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 +829,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 +841,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 +855,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 +894,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 +939,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 +970,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 +1009,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 +1020,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 +1077,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 +1105,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 +1115,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 +1127,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 +1147,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 +1167,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 +1187,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 +1196,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 +1217,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 +1290,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 +1307,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 +1319,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 +1330,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 +1342,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 +1353,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 +1365,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 +1374,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 +1387,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>
-- 
cgit v1.2.3


From 882fa794883e6dbc0e56f22645cd3aec21920c53 Mon Sep 17 00:00:00 2001
From: Hans Nilsson <hans@erlang.org>
Date: Fri, 7 Sep 2018 13:46:52 +0200
Subject: crypto: Add missing documentation for enable_fips_mode/1

---
 lib/crypto/doc/src/crypto.xml | 21 ++++++++++++++++++++-
 lib/crypto/src/crypto.erl     |  4 ++--
 2 files changed, 22 insertions(+), 3 deletions(-)

(limited to 'lib')

diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml
index 9d436847ac..d5f5009297 100644
--- a/lib/crypto/doc/src/crypto.xml
+++ b/lib/crypto/doc/src/crypto.xml
@@ -642,7 +642,11 @@
         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 raise exception <c>error:notsup</c>. Check
@@ -653,6 +657,21 @@
       </desc>
     </func>
 
+    <func>
+      <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>
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index a841f0f168..c64586897e 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -346,8 +346,8 @@ info_lib() -> ?nif_stub.
 
 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.
 
 %%%================================================================
-- 
cgit v1.2.3


From 5a67298324cc03454e659a1983fd7696451998aa Mon Sep 17 00:00:00 2001
From: Hans Nilsson <hans@erlang.org>
Date: Tue, 28 Aug 2018 15:52:52 +0200
Subject: public_key: Remove special type signature for one test

---
 lib/public_key/test/public_key_SUITE.erl | 4 ----
 1 file changed, 4 deletions(-)

(limited to 'lib')

diff --git a/lib/public_key/test/public_key_SUITE.erl b/lib/public_key/test/public_key_SUITE.erl
index cfd8e7a34b..1955e9e119 100644
--- a/lib/public_key/test/public_key_SUITE.erl
+++ b/lib/public_key/test/public_key_SUITE.erl
@@ -718,12 +718,8 @@ encrypt_decrypt(Config) when is_list(Config) ->
     Msg = list_to_binary(lists:duplicate(5, "Foo bar 100")),
     RsaEncrypted = public_key:encrypt_private(Msg, PrivateKey),
     Msg = public_key:decrypt_public(RsaEncrypted, PublicKey),
-    Msg = public_key:decrypt_public(RsaEncrypted, PrivateKey),
     RsaEncrypted2 = public_key:encrypt_public(Msg, PublicKey),
-    RsaEncrypted3 = public_key:encrypt_public(Msg, PrivateKey),
     Msg = public_key:decrypt_private(RsaEncrypted2, PrivateKey),
-    Msg = public_key:decrypt_private(RsaEncrypted3, PrivateKey),
-
     ok.
        
 %%--------------------------------------------------------------------
-- 
cgit v1.2.3


From dce332fd4adca8e1ef1b54db69f14ec7186a3a44 Mon Sep 17 00:00:00 2001
From: Hans Nilsson <hans@erlang.org>
Date: Tue, 28 Aug 2018 15:59:37 +0200
Subject: public_key: Setup for doc generation

---
 lib/public_key/doc/specs/.gitignore | 1 +
 lib/public_key/doc/src/Makefile     | 7 +++++++
 lib/public_key/doc/src/specs.xml    | 4 ++++
 3 files changed, 12 insertions(+)
 create mode 100644 lib/public_key/doc/specs/.gitignore
 create mode 100644 lib/public_key/doc/src/specs.xml

(limited to 'lib')

diff --git a/lib/public_key/doc/specs/.gitignore b/lib/public_key/doc/specs/.gitignore
new file mode 100644
index 0000000000..322eebcb06
--- /dev/null
+++ b/lib/public_key/doc/specs/.gitignore
@@ -0,0 +1 @@
+specs_*.xml
diff --git a/lib/public_key/doc/src/Makefile b/lib/public_key/doc/src/Makefile
index 03467e9783..8575b196b7 100644
--- a/lib/public_key/doc/src/Makefile
+++ b/lib/public_key/doc/src/Makefile
@@ -77,12 +77,18 @@ 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 +=
 DVIPS_FLAGS +=
 
+SPECS_FLAGS = -I../../include -I../../src -I../../..
+
 # ----------------------------------------------------
 # Targets
 # ----------------------------------------------------
@@ -103,6 +109,7 @@ clean clean_docs:
 	rm -f $(MAN3DIR)/*
 	rm -f $(MAN6DIR)/*
 	rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
+	rm -f $(SPECS_FILES)
 	rm -f errs core *~
 
 man: $(MAN3_FILES) $(MAN6_FILES)
diff --git a/lib/public_key/doc/src/specs.xml b/lib/public_key/doc/src/specs.xml
new file mode 100644
index 0000000000..e358ea1154
--- /dev/null
+++ b/lib/public_key/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_public_key.xml"/>
+</specs>
-- 
cgit v1.2.3


From 2920aa71a9163ea495e896264daa1b56bd845d12 Mon Sep 17 00:00:00 2001
From: Hans Nilsson <hans@erlang.org>
Date: Tue, 28 Aug 2018 16:01:19 +0200
Subject: public_key: Rework -type and -spec Check existing specs with code and
 documentation and adjust. Prepare for doc generation

---
 lib/public_key/src/public_key.erl | 439 +++++++++++++++++++++++---------------
 1 file changed, 269 insertions(+), 170 deletions(-)

(limited to 'lib')

diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl
index 3704503f1e..3f609ce6c6 100644
--- a/lib/public_key/src/public_key.erl
+++ b/lib/public_key/src/public_key.erl
@@ -76,7 +76,7 @@
 -type dsa_private_key()      ::  #'DSAPrivateKey'{}.
 -type dsa_public_key()       :: {integer(), #'Dss-Parms'{}}.
 -type ecpk_parameters() :: {ecParameters, #'ECParameters'{}} | {namedCurve, Oid::tuple()}.
--type ecpk_parameters_api() :: ecpk_parameters() | #'ECParameters'{} | {namedCurve, Name::atom()}.
+-type ecpk_parameters_api() :: ecpk_parameters() | #'ECParameters'{} | {namedCurve, Name::crypto:ec_named_curve()}.
 -type ec_public_key()        :: {#'ECPoint'{}, ecpk_parameters_api()}.
 -type ec_private_key()       :: #'ECPrivateKey'{}.
 -type key_params()           :: #'DHParameter'{} | {namedCurve, oid()} | #'ECParameters'{} | 
@@ -88,28 +88,41 @@
 				 'CertificationRequest' | 'CertificateList' |
 				 'ECPrivateKey' | 'EcpkParameters'.
 -type pem_entry()            :: {pki_asn1_type(), 
-				 binary(), %% DER or Encrypted DER
-				 not_encrypted | {Cipher :: string(), Salt :: binary()} |
-				 {Cipher :: string(), #'PBES2-params'{}} | 
-				 {Cipher :: string(), {#'PBEParameter'{}, atom()}} %% hash type
+				 der_or_encrypted_der(),
+				 not_encrypted | cipher_info()
 				}.
+-type der_or_encrypted_der() :: binary().
+-type cipher_info()          :: {cipher(),
+                                 cipher_info_params()} .
+-type cipher()               :: string() . % "RC2-CBC" | "DES-CBC" | "DES-EDE3-CBC", 
+-type cipher_info_params()   :: salt()
+                              | {#'PBEParameter'{}, digest_type()}
+                              | #'PBES2-params'{} .
+
+-type salt()                 :: binary(). % crypto:strong_rand_bytes(8)
+%% -type cipher_info()          :: {Cipher :: string(), Salt :: binary()} |
+%%                                 {Cipher :: string(), #'PBES2-params'{}} | 
+%%                                 {Cipher :: string(), {#'PBEParameter'{}, atom()}} %% hash type
+%%                                 .
+
 -type asn1_type()            :: atom(). %% see "OTP-PUB-KEY.hrl
 -type ssh_file()             :: openssh_public_key | rfc4716_public_key | known_hosts |
 				auth_keys.
--type rsa_padding()          :: 'rsa_pkcs1_padding' | 'rsa_pkcs1_oaep_padding' 
-			      | 'rsa_no_padding'.
--type rsa_sign_padding()     :: 'rsa_pkcs1_padding' | 'rsa_pkcs1_pss_padding'.
--type public_crypt_options() :: [{rsa_pad, rsa_padding()}].
--type rsa_digest_type()      :: 'md5' | 'ripemd160' | 'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512'.
--type dss_digest_type()      :: 'none' | 'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512'. %% None is for backwards compatibility
--type ecdsa_digest_type()    :: 'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512'.
--type public_sign_options()  :: [{rsa_pad, rsa_sign_padding()} | {rsa_pss_saltlen, integer()}].
--type digest_type()          :: rsa_digest_type() |  dss_digest_type() | ecdsa_digest_type().
+-type digest_type()          :: none % None is for backwards compatibility
+                              | crypto:rsa_digest_type()
+                              | crypto:dss_digest_type()
+                              | crypto:ecdsa_digest_type().
 -type crl_reason()           ::  unspecified | keyCompromise | cACompromise | affiliationChanged | superseded
 			       | cessationOfOperation | certificateHold | privilegeWithdrawn |  aACompromise.
 -type oid()                  :: tuple().
 -type chain_type()           :: server_chain | client_chain.
 
+-type issuer_id()            :: {SerialNr::integer(), issuer_name()} .
+
+-type issuer_name()          :: {rdnSequence,[#'AttributeTypeAndValue'{}]} .
+
+
+
 -define(UINT32(X), X:32/unsigned-big-integer).
 -define(DER_NULL, <<5, 0>>).
 
@@ -134,11 +147,11 @@ pem_encode(PemEntries) when is_list(PemEntries) ->
     iolist_to_binary(pubkey_pem:encode(PemEntries)).
 
 %%--------------------------------------------------------------------
--spec pem_entry_decode(pem_entry(), string()) -> term().
-%
 %% Description: Decodes a pem entry. pem_decode/1 returns a list of
 %% pem entries.
 %%--------------------------------------------------------------------
+-spec pem_entry_decode(PemEntry) -> term() when PemEntry :: pem_entry() .
+
 pem_entry_decode({'SubjectPublicKeyInfo', Der, _}) ->
     {_, {'AlgorithmIdentifier', AlgId, Params}, Key0}
         = der_decode('SubjectPublicKeyInfo', Der),
@@ -156,6 +169,9 @@ pem_entry_decode({'SubjectPublicKeyInfo', Der, _}) ->
 pem_entry_decode({Asn1Type, Der, not_encrypted}) when is_atom(Asn1Type),
 						      is_binary(Der) ->
     der_decode(Asn1Type, Der).
+
+-spec pem_entry_decode(PemEntry, Password) -> term() when PemEntry :: pem_entry(),
+                                                          Password :: string() .
 pem_entry_decode({Asn1Type, Der, not_encrypted}, _) when is_atom(Asn1Type),
 							 is_binary(Der) ->
     der_decode(Asn1Type, Der);
@@ -181,11 +197,12 @@ pem_entry_decode({Asn1Type, CryptDer, {Cipher, Salt}} = PemEntry,
 
 
 %%--------------------------------------------------------------------
--spec pem_entry_encode(pki_asn1_type(), term()) -> pem_entry().
--spec pem_entry_encode(pki_asn1_type(), term(), term()) -> pem_entry().
 %%
 %% Description: Creates a pem entry that can be feed to pem_encode/1.
 %%--------------------------------------------------------------------
+-spec pem_entry_encode(Asn1Type, Entity) -> pem_entry() when Asn1Type :: pki_asn1_type(),
+                                                             Entity :: term() .
+
 pem_entry_encode('SubjectPublicKeyInfo', Entity=#'RSAPublicKey'{}) ->
     Der = der_encode('RSAPublicKey', Entity),
     Spki = {'SubjectPublicKeyInfo',
@@ -208,6 +225,13 @@ pem_entry_encode('SubjectPublicKeyInfo',
 pem_entry_encode(Asn1Type, Entity)  when is_atom(Asn1Type) ->
     Der = der_encode(Asn1Type, Entity),
     {Asn1Type, Der, not_encrypted}.
+
+-spec pem_entry_encode(Asn1Type, Entity, InfoPwd) ->
+                              pem_entry() when Asn1Type :: pki_asn1_type(),
+                                               Entity :: term(),
+                                               InfoPwd :: {CipherInfo,Password},
+                                               CipherInfo :: cipher_info(),
+                                               Password :: string() .
 pem_entry_encode(Asn1Type, Entity, {{Cipher, #'PBES2-params'{}} = CipherInfo, 
 				    Password}) when is_atom(Asn1Type) andalso
 						    is_list(Password) andalso
@@ -229,7 +253,9 @@ pem_entry_encode(Asn1Type, Entity, {{Cipher, Salt} = CipherInfo,
     do_pem_entry_encode(Asn1Type, Entity, CipherInfo, Password).
     
 %%--------------------------------------------------------------------
--spec der_decode(asn1_type(), Der::binary()) -> term().
+-spec der_decode(Asn1Type, Der) -> Entity when Asn1Type :: asn1_type(),
+                                               Der :: binary(),
+                                               Entity :: term().
 %%
 %% Description: Decodes a public key asn1 der encoded entity.
 %%--------------------------------------------------------------------
@@ -269,7 +295,9 @@ der_priv_key_decode(PKCS8Key) ->
 	PKCS8Key.
 
 %%--------------------------------------------------------------------
--spec der_encode(asn1_type(), term()) -> Der::binary().
+-spec der_encode(Asn1Type, Entity) -> Der when Asn1Type :: asn1_type(),
+                                               Entity :: term(),
+                                               Der :: binary() .
 %%
 %% Description: Encodes a public key entity with asn1 DER encoding.
 %%--------------------------------------------------------------------
@@ -311,8 +339,10 @@ der_encode(Asn1Type, Entity) when is_atom(Asn1Type) ->
     end.
 
 %%--------------------------------------------------------------------
--spec pkix_decode_cert(Cert::binary(), plain | otp) ->
-			      #'Certificate'{} | #'OTPCertificate'{}.
+-spec pkix_decode_cert(Cert, Type) ->
+			      #'Certificate'{} | #'OTPCertificate'{} 
+                                  when Cert :: der_encoded(),
+                                       Type :: plain | otp .
 %%
 %% Description: Decodes an asn1 der encoded pkix certificate. The otp
 %% option will use the customized asn1 specification OTP-PKIX.asn1 for
@@ -332,7 +362,11 @@ pkix_decode_cert(DerCert, otp) when is_binary(DerCert) ->
     end.
 
 %%--------------------------------------------------------------------
--spec pkix_encode(asn1_type(), term(), otp | plain) -> Der::binary().
+-spec pkix_encode(Asn1Type, Entity, Type) -> Der
+                                                 when Asn1Type :: asn1_type(),
+                                                      Entity :: term(),
+                                                      Type :: otp | plain,
+                                                      Der :: der_encoded() .
 %%
 %% Description: Der encodes a certificate or part of a certificate.
 %% This function must be used for encoding certificates or parts of certificates
@@ -347,16 +381,21 @@ pkix_encode(Asn1Type, Term0, otp) when is_atom(Asn1Type) ->
     der_encode(Asn1Type, Term).
 
 %%--------------------------------------------------------------------
--spec decrypt_private(CipherText :: binary(), rsa_private_key()) -> 
-			     PlainText :: binary().
--spec decrypt_private(CipherText :: binary(), rsa_private_key(), 
-		      public_crypt_options()) -> PlainText :: binary().
 %%
 %% Description: Public key decryption using the private key.
 %%--------------------------------------------------------------------
+-spec decrypt_private(CipherText, Key) ->
+                             PlainText when CipherText :: binary(),
+                                            Key :: rsa_private_key(),
+                                            PlainText ::  binary() .
 decrypt_private(CipherText, Key) ->
     decrypt_private(CipherText, Key, []).
 
+-spec decrypt_private(CipherText, Key, Options) ->
+                             PlainText when CipherText :: binary(),
+                                            Key :: rsa_private_key(),
+                                            Options :: crypto:pk_encrypt_decrypt_opts(),
+                                            PlainText ::  binary() .
 decrypt_private(CipherText,
 		#'RSAPrivateKey'{} = Key,
 		Options)
@@ -366,61 +405,69 @@ decrypt_private(CipherText,
     crypto:private_decrypt(rsa, CipherText, format_rsa_private_key(Key), Padding).
 
 %%--------------------------------------------------------------------
--spec decrypt_public(CipherText :: binary(), rsa_public_key() | rsa_private_key()) ->
-			    PlainText :: binary().
--spec decrypt_public(CipherText :: binary(), rsa_public_key() | rsa_private_key(),
-		     public_crypt_options()) -> PlainText :: binary().
-%% NOTE: The rsa_private_key() is not part of the documented API it is
-%% here for testing purposes, in a real situation this is not a relevant
-%% thing to do.
-%%
 %% Description: Public key decryption using the public key.
 %%--------------------------------------------------------------------
+-spec decrypt_public(CipherText, Key) ->
+			    PlainText
+                                when CipherText :: binary(),
+                                     Key :: rsa_public_key(),
+                                     PlainText :: binary() .
 decrypt_public(CipherText, Key) ->
     decrypt_public(CipherText, Key, []).
 
+-spec decrypt_public(CipherText, Key, Options) ->
+			    PlainText
+                                when CipherText :: binary(),
+                                     Key :: rsa_public_key(),
+                                     Options :: crypto:pk_encrypt_decrypt_opts(),
+                                     PlainText :: binary() .
 decrypt_public(CipherText, #'RSAPublicKey'{modulus = N, publicExponent = E}, 
 	       Options) when is_binary(CipherText), is_list(Options)  ->
-    decrypt_public(CipherText, N,E, Options);
-
-decrypt_public(CipherText,#'RSAPrivateKey'{modulus = N, publicExponent = E}, 
-	       Options) when is_binary(CipherText), is_list(Options) ->
-    decrypt_public(CipherText, N,E, Options).
+    Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_padding),
+    crypto:public_decrypt(rsa, CipherText,[E, N], Padding).
 
 %%--------------------------------------------------------------------
--spec encrypt_public(PlainText :: binary(), rsa_public_key() | rsa_private_key()) ->
-			    CipherText :: binary().
--spec encrypt_public(PlainText :: binary(), rsa_public_key() | rsa_private_key(),
-		     public_crypt_options()) ->  CipherText :: binary().
-
-%% NOTE: The rsa_private_key() is not part of the documented API it is
-%% here for testing purposes, in a real situation this is not a relevant
-%% thing to do.
-%%
 %% Description: Public key encryption using the public key.
 %%--------------------------------------------------------------------
+-spec encrypt_public(PlainText, Key) ->
+			     CipherText
+                                 when  PlainText :: binary(),
+                                       Key :: rsa_public_key(),
+                                       CipherText :: binary() .
 encrypt_public(PlainText, Key) ->
     encrypt_public(PlainText, Key, []).
 
-encrypt_public(PlainText, #'RSAPublicKey'{modulus=N,publicExponent=E}, 
-	       Options) when is_binary(PlainText), is_list(Options) ->
-    encrypt_public(PlainText, N,E, Options);
 
-encrypt_public(PlainText, #'RSAPrivateKey'{modulus=N,publicExponent=E}, 
+-spec encrypt_public(PlainText, Key, Options) ->
+			     CipherText
+                                 when  PlainText :: binary(),
+                                       Key :: rsa_public_key(),
+                                       Options :: crypto:pk_encrypt_decrypt_opts(),
+                                       CipherText :: binary() .
+encrypt_public(PlainText, #'RSAPublicKey'{modulus=N,publicExponent=E}, 
 	       Options) when is_binary(PlainText), is_list(Options) ->
-    encrypt_public(PlainText, N,E, Options).
+    Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_padding),
+    crypto:public_encrypt(rsa, PlainText, [E,N], Padding).
 
 %%--------------------------------------------------------------------
--spec encrypt_private(PlainText :: binary(), rsa_private_key()) -> 
-			     CipherText :: binary().
--spec encrypt_private(PlainText :: binary(), rsa_private_key(), 
-		      public_crypt_options()) -> CipherText :: binary().
 %%
 %% Description: Public key encryption using the private key.
 %%--------------------------------------------------------------------
+-spec encrypt_private(PlainText, Key) ->
+			     CipherText
+                                 when  PlainText :: binary(),
+                                       Key :: rsa_private_key(),
+                                       CipherText :: binary() .
 encrypt_private(PlainText, Key) ->
     encrypt_private(PlainText, Key, []).
 
+
+-spec encrypt_private(PlainText, Key, Options) ->
+			     CipherText
+                                 when  PlainText :: binary(),
+                                       Key :: rsa_private_key(),
+                                       Options :: crypto:pk_encrypt_decrypt_opts(),
+                                       CipherText :: binary() .
 encrypt_private(PlainText,
 		#'RSAPrivateKey'{modulus = N, publicExponent = E,
 				 privateExponent = D} = Key,
@@ -432,22 +479,42 @@ encrypt_private(PlainText,
     crypto:private_encrypt(rsa, PlainText, format_rsa_private_key(Key), Padding).
 
 %%--------------------------------------------------------------------
+%% Description: List available group sizes among the pre-computed dh groups
+%%--------------------------------------------------------------------
+-spec dh_gex_group_sizes() -> [pos_integer()].
 dh_gex_group_sizes() ->
     pubkey_ssh:dh_gex_group_sizes().
 
+%%--------------------------------------------------------------------
+%% Description: Select a precomputed group
+%%--------------------------------------------------------------------
+-spec dh_gex_group(MinSize, SuggestedSize, MaxSize, Groups) ->
+                          {ok,{Size,Group}} | {error,term()}
+                              when MinSize :: pos_integer(),
+                                   SuggestedSize :: pos_integer(),
+                                   MaxSize :: pos_integer(),
+                                   Groups :: undefined | [{Size,[Group]}],
+                                   Size :: pos_integer(),
+                                   Group :: {G,P},
+                                   G :: pos_integer(),
+                                   P :: pos_integer() .
 dh_gex_group(Min, N, Max, Groups) ->
     pubkey_ssh:dh_gex_group(Min, N, Max, Groups).
 
 %%--------------------------------------------------------------------
--spec generate_key(#'DHParameter'{}) ->
-                          {Public::binary(), Private::binary()};
-                  (ecpk_parameters_api()) ->
-                          #'ECPrivateKey'{};
-                  ({rsa, Size::pos_integer(), PubExp::pos_integer()}) ->
-                          #'RSAPrivateKey'{}.
-
-%% Description: Generates a new keypair
+%% Description: Generate a new key pair
 %%--------------------------------------------------------------------
+-spec generate_key(DHparams | ECparams | RSAparams) ->
+                          DHkeys | ECkey | RSAkey
+                              when DHparams :: #'DHParameter'{},
+                                   DHkeys :: {PublicDH::binary(), PrivateDH::binary()},
+                                   ECparams :: ecpk_parameters_api(),
+                                   ECkey :: #'ECPrivateKey'{},
+                                   RSAparams :: {rsa, Size, PubExp},
+                                   Size::pos_integer(),
+                                   PubExp::pos_integer(),
+                                   RSAkey :: #'RSAPrivateKey'{} .
+
 generate_key(#'DHParameter'{prime = P, base = G}) ->
     crypto:generate_key(dh, [P, G]);
 generate_key({namedCurve, _} = Params) ->
@@ -494,24 +561,34 @@ generate_key({rsa, ModulusSize, PublicExponent}) ->
     end.
 
 %%--------------------------------------------------------------------
--spec compute_key(#'ECPoint'{} , #'ECPrivateKey'{}) -> binary().
--spec compute_key(OthersKey ::binary(), MyKey::binary(), #'DHParameter'{}) -> binary().
 %% Description: Compute shared secret
 %%--------------------------------------------------------------------
+-spec compute_key(OthersECDHkey, MyECDHkey) -> 
+                         SharedSecret
+                             when OthersECDHkey :: #'ECPoint'{},
+                                  MyECDHkey :: #'ECPrivateKey'{},
+                                  SharedSecret :: binary().
 compute_key(#'ECPoint'{point = Point}, #'ECPrivateKey'{privateKey = PrivKey,
 						       parameters = Param}) ->
     ECCurve = ec_curve_spec(Param),
     crypto:compute_key(ecdh, Point, PrivKey, ECCurve).
 
+-spec compute_key(OthersDHkey, MyDHkey, DHparms) -> 
+                         SharedSecret
+                             when OthersDHkey :: crypto:dh_public(), % Was: binary(),
+                                  MyDHkey :: crypto:dh_private(), % Was: binary(),
+                                  DHparms ::  #'DHParameter'{},
+                                  SharedSecret :: binary().
 compute_key(PubKey, PrivKey, #'DHParameter'{prime = P, base = G}) ->
     crypto:compute_key(dh, PubKey, PrivKey, [P, G]).
 
 %%--------------------------------------------------------------------
--spec pkix_sign_types(SignatureAlg::oid()) ->
-			     %% Relevant dsa digest type is subpart of rsa digest type
-			     { DigestType :: rsa_digest_type(),
-			       SignatureType :: rsa | dsa | ecdsa
-			     }.
+-spec pkix_sign_types(AlgorithmId) -> 
+                             {DigestType, SignatureType}
+                                 when AlgorithmId :: oid(),
+                                      %% Relevant dsa digest type is a subset of rsa_digest_type()
+                                      DigestType :: crypto:rsa_digest_type(),
+                                      SignatureType :: rsa | dsa | ecdsa .
 %% Description:
 %%--------------------------------------------------------------------
 pkix_sign_types(?sha1WithRSAEncryption) ->
@@ -542,24 +619,24 @@ pkix_sign_types(?'ecdsa-with-SHA512') ->
     {sha512, ecdsa}.
 
 %%--------------------------------------------------------------------
--spec sign(binary() | {digest, binary()},
-           rsa_digest_type() | dss_digest_type() | ecdsa_digest_type(),
-	   rsa_private_key() | dsa_private_key() | ec_private_key()
-          ) -> Signature :: binary().
-
--spec sign(binary() | {digest, binary()},
-           rsa_digest_type() | dss_digest_type() | ecdsa_digest_type(),
-	   rsa_private_key() | dsa_private_key() | ec_private_key(),
-           public_sign_options()
-          ) -> Signature :: binary().
-
 %% Description: Create digital signature.
 %%--------------------------------------------------------------------
+-spec sign(Msg, DigestType, Key) ->
+                  Signature when Msg ::  binary() | {digest,binary()},
+                                 DigestType :: digest_type(),
+                                 Key :: private_key(),
+                                 Signature :: binary() .
 sign(DigestOrPlainText, DigestType, Key) ->
     sign(DigestOrPlainText, DigestType, Key, []).
 
-%% Backwards compatible
+-spec sign(Msg, DigestType, Key, Options) ->
+                  Signature when Msg ::  binary() | {digest,binary()},
+                                 DigestType :: digest_type(),
+                                 Key :: private_key(),
+                                 Options :: crypto:pk_sign_verify_opts(),
+                                 Signature :: binary() .
 sign(Digest, none, Key = #'DSAPrivateKey'{}, Options) when is_binary(Digest) ->
+    %% Backwards compatible
     sign({digest, Digest}, sha, Key, Options);
 sign(DigestOrPlainText, DigestType, Key, Options) ->
     case format_sign_key(Key) of
@@ -570,28 +647,26 @@ sign(DigestOrPlainText, DigestType, Key, Options) ->
     end.
 
 %%--------------------------------------------------------------------
--spec verify(binary() | {digest, binary()},
-             rsa_digest_type() | dss_digest_type() | ecdsa_digest_type(),
-	     Signature :: binary(),
-             rsa_public_key() | dsa_public_key() | ec_public_key()
-               |  rsa_private_key() | dsa_private_key() | ec_private_key()
-            ) -> boolean().
-
--spec verify(binary() | {digest, binary()},
-             rsa_digest_type() | dss_digest_type() | ecdsa_digest_type(),
-	     Signature :: binary(),
-             rsa_public_key() | dsa_public_key() | ec_public_key()
-               |  rsa_private_key() | dsa_private_key() | ec_private_key(),
-             public_sign_options()
-            ) -> boolean().
-
 %% Description: Verifies a digital signature.
 %%--------------------------------------------------------------------
+-spec verify(Msg, DigestType, Signature, Key) ->
+                    boolean() when Msg :: binary() | {digest, binary()},
+                                   DigestType :: digest_type(),
+                                   Signature :: binary(),
+                                   Key :: public_key() .
+
 verify(DigestOrPlainText, DigestType, Signature, Key) ->
     verify(DigestOrPlainText, DigestType, Signature, Key, []).
 
-%% Backwards compatible
+-spec verify(Msg, DigestType, Signature, Key, Options) ->
+                    boolean() when Msg :: binary() | {digest, binary()},
+                                   DigestType :: digest_type(),
+                                   Signature :: binary(),
+                                   Key :: public_key(),
+                                   Options :: crypto:pk_sign_verify_opts().
+
 verify(Digest, none, Signature, Key = {_, #'Dss-Parms'{}}, Options) when is_binary(Digest) ->
+    %% Backwards compatible
     verify({digest, Digest}, sha, Signature, Key, Options);
 verify(DigestOrPlainText, DigestType, Signature, Key, Options) when is_binary(Signature) ->
     case format_verify_key(Key) of
@@ -606,8 +681,8 @@ verify(_,_,_,_,_) ->
     false.
 
 %%--------------------------------------------------------------------
--spec pkix_dist_point(der_encoded() | #'OTPCertificate'{}) -> 
-			      #'DistributionPoint'{}.  
+-spec pkix_dist_point(Cert) -> DistPoint when Cert :: der_encoded() | #'OTPCertificate'{},
+                                              DistPoint :: #'DistributionPoint'{}.
 %% Description:  Creates a distribution point for CRLs issued by the same issuer as <c>Cert</c>.
 %%--------------------------------------------------------------------
 pkix_dist_point(OtpCert) when is_binary(OtpCert) ->
@@ -630,8 +705,8 @@ pkix_dist_point(OtpCert) ->
 			 reasons = asn1_NOVALUE,
 			 distributionPoint =  Point}.	
 %%--------------------------------------------------------------------
--spec pkix_dist_points(der_encoded() | #'OTPCertificate'{}) -> 
-			      [#'DistributionPoint'{}].  
+-spec pkix_dist_points(Cert) -> DistPoints when Cert :: der_encoded() | #'OTPCertificate'{},
+                                                DistPoints :: [ #'DistributionPoint'{} ].
 %% Description:  Extracts distributionpoints specified in the certificates extensions.
 %%--------------------------------------------------------------------
 pkix_dist_points(OtpCert) when is_binary(OtpCert) ->
@@ -645,8 +720,10 @@ pkix_dist_points(OtpCert) ->
 		[], Value).
 
 %%--------------------------------------------------------------------
--spec pkix_match_dist_point(der_encoded() | #'CertificateList'{},
-			    #'DistributionPoint'{}) -> boolean().
+-spec pkix_match_dist_point(CRL, DistPoint) ->
+                                   boolean()
+                                       when CRL :: der_encoded() | #'CertificateList'{},
+                                            DistPoint :: #'DistributionPoint'{}.
 %% Description: Check whether the given distribution point matches
 %% the "issuing distribution point" of the CRL.
 %%--------------------------------------------------------------------
@@ -677,8 +754,9 @@ pkix_match_dist_point(#'CertificateList'{
     end.
 
 %%--------------------------------------------------------------------
--spec pkix_sign(#'OTPTBSCertificate'{},
-		rsa_private_key() | dsa_private_key() | ec_private_key()) -> Der::binary().
+-spec pkix_sign(Cert, Key) -> Der when Cert :: #'OTPTBSCertificate'{}, 
+                                       Key :: private_key(),
+                                       Der :: der_encoded() .
 %%
 %% Description: Sign a pkix x.509 certificate. Returns the corresponding
 %% der encoded 'Certificate'{}
@@ -697,8 +775,8 @@ pkix_sign(#'OTPTBSCertificate'{signature =
     pkix_encode('OTPCertificate', Cert, otp).
 
 %%--------------------------------------------------------------------
--spec pkix_verify(Cert::binary(), rsa_public_key()|
-		  dsa_public_key() | ec_public_key()) -> boolean().
+-spec pkix_verify(Cert, Key) -> boolean() when Cert :: der_encoded(),
+                                               Key :: public_key() .
 %%
 %% Description: Verify pkix x.509 certificate signature.
 %%--------------------------------------------------------------------
@@ -718,7 +796,9 @@ pkix_verify(DerCert, Key = {#'ECPoint'{}, _})
     verify(PlainText, DigestType, Signature,  Key).
 
 %%--------------------------------------------------------------------
--spec pkix_crl_verify(CRL::binary() | #'CertificateList'{}, Cert::binary() | #'OTPCertificate'{}) -> boolean().
+-spec pkix_crl_verify(CRL, Cert) -> boolean()
+                                        when CRL  :: der_encoded() | #'CertificateList'{},
+                                             Cert :: der_encoded() | #'OTPCertificate'{} .
 %%
 %% Description: Verify that Cert is the CRL signer.
 %%--------------------------------------------------------------------
@@ -737,9 +817,12 @@ pkix_crl_verify(#'CertificateList'{} = CRL, #'OTPCertificate'{} = Cert) ->
 				    PublicKey, PublicKeyParams).
 
 %%--------------------------------------------------------------------
--spec pkix_is_issuer(Cert :: der_encoded()| #'OTPCertificate'{} | #'CertificateList'{},
-		     IssuerCert :: der_encoded()|
-				   #'OTPCertificate'{}) -> boolean().
+-spec pkix_is_issuer(Cert, IssuerCert) -> 
+                            boolean() when Cert :: der_encoded()
+                                                 | #'OTPCertificate'{}
+                                                 | #'CertificateList'{},
+                                           IssuerCert :: der_encoded()
+                                                       | #'OTPCertificate'{} .
 %%
 %% Description: Checks if <IssuerCert> issued <Cert>.
 %%--------------------------------------------------------------------
@@ -759,7 +842,7 @@ pkix_is_issuer(#'CertificateList'{tbsCertList = TBSCRL},
 			  pubkey_cert_records:transform(TBSCRL#'TBSCertList'.issuer, decode)).
 
 %%--------------------------------------------------------------------
--spec pkix_is_self_signed(Cert::binary()| #'OTPCertificate'{}) -> boolean().
+-spec pkix_is_self_signed(Cert) -> boolean() when Cert::der_encoded()| #'OTPCertificate'{}.
 %%
 %% Description: Checks if a Certificate is self signed. 
 %%--------------------------------------------------------------------
@@ -770,7 +853,7 @@ pkix_is_self_signed(Cert) when is_binary(Cert) ->
     pkix_is_self_signed(OtpCert).
   
 %%--------------------------------------------------------------------
--spec pkix_is_fixed_dh_cert(Cert::binary()| #'OTPCertificate'{}) -> boolean().
+-spec pkix_is_fixed_dh_cert(Cert) -> boolean() when Cert::der_encoded()| #'OTPCertificate'{}.
 %%
 %% Description: Checks if a Certificate is a fixed Diffie-Hellman Cert.
 %%--------------------------------------------------------------------
@@ -781,13 +864,12 @@ pkix_is_fixed_dh_cert(Cert) when is_binary(Cert) ->
     pkix_is_fixed_dh_cert(OtpCert).
 
 %%--------------------------------------------------------------------
--spec pkix_issuer_id(Cert::binary()| #'OTPCertificate'{},
-		     IssuedBy :: self | other) ->
-			    {ok, {SerialNr :: integer(),
-				  Issuer :: {rdnSequence,
-					     [#'AttributeTypeAndValue'{}]}}}
-				| {error, Reason :: term()}.
-%
+-spec pkix_issuer_id(Cert, IssuedBy) ->
+			    {ok, issuer_id()} | {error, Reason}
+                                when Cert::der_encoded()| #'OTPCertificate'{},
+                                     IssuedBy :: self | other,
+                                     Reason :: term() .
+
 %% Description: Returns the issuer id.
 %%--------------------------------------------------------------------
 pkix_issuer_id(#'OTPCertificate'{} = OtpCert, Signed) when (Signed == self) or 
@@ -798,9 +880,9 @@ pkix_issuer_id(Cert, Signed) when is_binary(Cert) ->
     pkix_issuer_id(OtpCert, Signed).
 
 %%--------------------------------------------------------------------
--spec pkix_crl_issuer(CRL::binary()| #'CertificateList'{}) -> 
-			     {rdnSequence,
-			      [#'AttributeTypeAndValue'{}]}.
+-spec pkix_crl_issuer(CRL| #'CertificateList'{}) -> 
+                             Issuer when CRL :: der_encoded(),
+                                         Issuer :: issuer_name() .
 %
 %% Description: Returns the issuer.
 %%--------------------------------------------------------------------
@@ -811,10 +893,9 @@ pkix_crl_issuer(#'CertificateList'{} = CRL) ->
       CRL#'CertificateList'.tbsCertList#'TBSCertList'.issuer, decode).
 
 %%--------------------------------------------------------------------
--spec pkix_normalize_name({rdnSequence,
-				   [#'AttributeTypeAndValue'{}]}) ->
-					 {rdnSequence, 
-					  [#'AttributeTypeAndValue'{}]}.
+-spec pkix_normalize_name(Issuer) -> Normalized 
+                                         when Issuer :: issuer_name(),
+                                              Normalized :: issuer_name() .
 %%
 %% Description: Normalizes a issuer name so that it can be easily
 %%              compared to another issuer name. 
@@ -825,7 +906,7 @@ pkix_normalize_name(Issuer) ->
 %%-------------------------------------------------------------------- 
 -spec pkix_path_validation(Cert::binary()| #'OTPCertificate'{} | atom(),
 			   CertChain :: [binary()] ,
-			   Options :: proplists:proplist()) ->
+			   Options :: [{atom(),term()}]) ->
 				  {ok, {PublicKeyInfo :: term(), 
 					PolicyTree :: term()}} |
 				  {error, {bad_cert, Reason :: term()}}.
@@ -861,11 +942,19 @@ pkix_path_validation(#'OTPCertificate'{} = TrustedCert, CertChain, Options)
     path_validation(CertChain, ValidationState).
 
 %--------------------------------------------------------------------
--spec pkix_crls_validate(#'OTPCertificate'{},
-			 [{DP::#'DistributionPoint'{}, {DerCRL::binary(), CRL::#'CertificateList'{}}}],
-			 Options :: proplists:proplist()) -> valid | {bad_cert, revocation_status_undetermined} |
-                                                             {bad_cert, {revocation_status_undetermined, Reason::term()}} |
-                                                             {bad_cert, {revoked, crl_reason()}}.
+-spec pkix_crls_validate(OTPcertificate, DPandCRLs, Options) ->
+                                CRLstatus when OTPcertificate :: #'OTPCertificate'{},
+                                               DPandCRLs :: [DPandCRL],
+                                               DPandCRL  :: {DP, {DerCRL, CRL}},
+                                               DP :: #'DistributionPoint'{},
+                                               DerCRL :: der_encoded(),
+                                               CRL :: #'CertificateList'{},
+                                               Options :: [{atom(),term()}],
+                                               CRLstatus :: valid
+                                                          | {bad_cert, BadCertReason},
+                                               BadCertReason :: revocation_status_undetermined
+                                                              | {revocation_status_undetermined, Reason::term()}
+                                                              | {revoked, crl_reason()}.
 
 %% Description: Performs a CRL validation according to RFC 5280.
 %%--------------------------------------------------------------------
@@ -882,20 +971,10 @@ pkix_crls_validate(OtpCert, DPAndCRLs0, Options) ->
 		       Options, pubkey_crl:init_revokation_state()).
 
 %--------------------------------------------------------------------
--spec pkix_verify_hostname(#'OTPCertificate'{} | binary(),
-			   referenceIDs()
-                          ) -> boolean().
-
--spec pkix_verify_hostname(#'OTPCertificate'{} | binary(),
-			   referenceIDs(),
-			   proplists:proplist()) -> boolean().
-
 -type referenceIDs() :: [referenceID()] .
 -type referenceID() :: {uri_id | dns_id | ip | srv_id | oid(),  string()} 
                      | {ip, inet:ip_address()} .
 
--spec pkix_verify_hostname_match_fun(high_level_alg()) -> match_fun() .
-
 -type high_level_alg() :: https .
 -type match_fun() ::  fun((ReferenceID::referenceID() | string(),
                            PresentedID::{atom()|oid(),string()}) -> match_fun_result() ) .
@@ -903,9 +982,20 @@ pkix_crls_validate(OtpCert, DPAndCRLs0, Options) ->
 
 %% Description: Validates a hostname to RFC 6125
 %%--------------------------------------------------------------------
+-spec pkix_verify_hostname(Cert, ReferenceIDs) -> boolean()
+                                                      when Cert :: der_encoded() 
+                                                                 | #'OTPCertificate'{},
+                                                           ReferenceIDs :: referenceIDs() .
 pkix_verify_hostname(Cert, ReferenceIDs) ->
     pkix_verify_hostname(Cert, ReferenceIDs, []).
 
+-spec pkix_verify_hostname(Cert, ReferenceIDs, Options) ->
+                                  boolean()
+                                      when Cert :: der_encoded() 
+                                                 | #'OTPCertificate'{},
+                                           ReferenceIDs :: referenceIDs(),
+                                           Options :: [{atom(),term()}] .
+
 pkix_verify_hostname(BinCert, ReferenceIDs, Options)  when is_binary(BinCert) ->
     pkix_verify_hostname(pkix_decode_cert(BinCert,otp), ReferenceIDs, Options);
 
@@ -964,15 +1054,25 @@ pkix_verify_hostname(Cert = #'OTPCertificate'{tbsCertificate = TbsCert}, Referen
 	    end
     end.
 
+
+-spec pkix_verify_hostname_match_fun(high_level_alg()) -> match_fun() .
+
 pkix_verify_hostname_match_fun(https) ->
     fun({dns_id,FQDN=[_|_]}, {dNSName,Name=[_|_]}) -> verify_hostname_match_wildcard(FQDN, Name);
        (_, _) -> default
     end.
 
 %%--------------------------------------------------------------------
--spec ssh_decode(binary(), public_key | ssh_file()) -> [{public_key(), Attributes::list()}]
-	      ; (binary(), ssh2_pubkey) ->  public_key()
-	      .
+-spec ssh_decode(SshBin, Type) ->
+                        Decoded
+                            when SshBin :: binary(),
+                                 Type :: ssh2_pubkey | OtherType,
+                                 OtherType :: public_key | ssh_file(),
+                                 Decoded :: Decoded_ssh2_pubkey
+                                          | Decoded_OtherType,
+                                 Decoded_ssh2_pubkey :: public_key(),
+                                 Decoded_OtherType :: [{public_key(), Attributes}],
+                                 Attributes :: [{atom(),term()}] .
 %%
 %% Description: Decodes a ssh file-binary. In the case of know_hosts
 %% or auth_keys the binary may include one or more lines of the
@@ -990,9 +1090,15 @@ ssh_decode(SshBin, Type) when is_binary(SshBin),
     pubkey_ssh:decode(SshBin, Type).
 
 %%--------------------------------------------------------------------
--spec ssh_encode([{public_key(), Attributes::list()}], ssh_file()) -> binary()
-	      ; (public_key(), ssh2_pubkey) -> binary()
-	      .
+-spec ssh_encode(InData, Type) ->
+                        binary()
+                            when Type :: ssh2_pubkey | OtherType,
+                                 OtherType :: public_key | ssh_file(),
+                                 InData :: InData_ssh2_pubkey | OtherInData,
+                                 InData_ssh2_pubkey :: public_key(),
+                                 OtherInData :: [{Key,Attributes}],
+                                 Key :: public_key(),
+                                 Attributes :: [{atom(),term()}] .
 %%
 %% Description: Encodes a list of ssh file entries (public keys and
 %% attributes) to a binary. Possible attributes depends on the file
@@ -1027,13 +1133,14 @@ oid2ssh_curvename(?'secp521r1') -> <<"nistp521">>.
 
 %%--------------------------------------------------------------------
 -spec ssh_hostkey_fingerprint(public_key()) -> string().
--spec ssh_hostkey_fingerprint( digest_type(),  public_key()) ->  string()
-                           ; ([digest_type()], public_key())   -> [string()]
-                           .
 
 ssh_hostkey_fingerprint(Key) ->
     sshfp_string(md5, public_key:ssh_encode(Key,ssh2_pubkey) ).
 
+
+-spec ssh_hostkey_fingerprint( digest_type(),  public_key()) ->  string()
+                           ; ([digest_type()], public_key())   -> [string()]
+                           .
 ssh_hostkey_fingerprint(HashAlgs, Key) when is_list(HashAlgs) ->
     EncKey = public_key:ssh_encode(Key, ssh2_pubkey),
     [sshfp_full_string(HashAlg,EncKey) || HashAlg <- HashAlgs];
@@ -1071,8 +1178,7 @@ fp_fmt(b64, Bin) ->
     [lists:nth(C+1,B64Chars) || <<C:6>> <= <<Bin/binary,0:Padding>> ].
 
 %%--------------------------------------------------------------------
--spec short_name_hash({rdnSequence, [#'AttributeTypeAndValue'{}]}) ->
-			     string().
+-spec short_name_hash(Name) -> string() when Name :: issuer_name() .
 
 %% Description: Generates OpenSSL-style hash of a name.
 %%--------------------------------------------------------------------
@@ -1103,10 +1209,11 @@ pkix_test_data(#{} = Chain) ->
     pubkey_cert:gen_test_certs(maps:merge(Default, Chain)).
 
 %%--------------------------------------------------------------------
--spec pkix_test_root_cert(
-        Name :: string(), Opts :: [pubkey_cert:cert_opt()]) ->
-                                 pubkey_cert:test_root_cert().
-
+-spec pkix_test_root_cert(Name, Options) ->
+                                 RootCert
+                                     when Name :: string(),
+                                          Options :: [{atom(),term()}], %[cert_opt()],
+                                          RootCert :: pubkey_cert:test_root_cert().
 %% Description: Generates a root cert suitable for pkix_test_data/1
 %%--------------------------------------------------------------------
 
@@ -1152,14 +1259,6 @@ do_pem_entry_decode({Asn1Type,_, _} = PemEntry, Password) ->
     Der = pubkey_pem:decipher(PemEntry, Password),
     der_decode(Asn1Type, Der).
 
-encrypt_public(PlainText, N, E, Options)->
-    Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_padding),
-    crypto:public_encrypt(rsa, PlainText, [E,N], Padding).
-
-decrypt_public(CipherText, N,E, Options) ->
-    Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_padding),
-    crypto:public_decrypt(rsa, CipherText,[E, N], Padding).
-
 path_validation([], #path_validation_state{working_public_key_algorithm
 					   = Algorithm,
 					   working_public_key =
-- 
cgit v1.2.3


From 0cdaea5199c49c1511700db3b4b0ff59f4c7396d Mon Sep 17 00:00:00 2001
From: Hans Nilsson <hans@erlang.org>
Date: Mon, 3 Sep 2018 15:15:47 +0200
Subject: public_key: Generate refman from types and specs

---
 lib/public_key/doc/src/public_key.xml | 684 ++++++++++++----------------------
 1 file changed, 240 insertions(+), 444 deletions(-)

(limited to 'lib')

diff --git a/lib/public_key/doc/src/public_key.xml b/lib/public_key/doc/src/public_key.xml
index c0a67c25b8..a4d7e4a734 100644
--- a/lib/public_key/doc/src/public_key.xml
+++ b/lib/public_key/doc/src/public_key.xml
@@ -41,7 +41,7 @@
   </description>
 
   <section>
-    <title>DATA TYPES</title> 
+    <title>Common Records and ASN.1 Types</title> 
     
     <note><p>All records used in this Reference Manual 
     <!--     except #policy_tree_node{}  -->
@@ -54,193 +54,132 @@
     records and constant macros described here and in the User's Guide:</p>
     
     <code> -include_lib("public_key/include/public_key.hrl").</code>
+  </section>
+
+  <datatypes>
+    <datatype>
+      <name name="oid"/>
+      <desc>
+	<p>Object identifier, a tuple of integers as generated by the <c>ASN.1</c> compiler.</p>
+      </desc>
+    </datatype>
+
+    <datatype>
+      <name name="der_encoded"/>
+      <desc>
+      </desc>
+    </datatype>
+
+    <datatype>
+      <name name="pki_asn1_type"/>
+      <desc>
+      </desc>
+    </datatype>
+
+    <datatype>
+      <name name="asn1_type"/>
+      <desc>
+	<p>ASN.1 type present in the Public Key applications ASN.1 specifications.</p>
+      </desc>
+    </datatype>
+
+    <datatype>
+      <name name="pem_entry"/>
+      <name name="der_or_encrypted_der"/>
+      <name name="cipher_info"/>
+      <name name="cipher"/>
+      <name name="salt"/>
+      <name name="cipher_info_params"/>
+      <desc>
+	<code>Cipher = "RC2-CBC" | "DES-CBC" | "DES-EDE3-CBC"</code>
+	<p><c>Salt</c> could be generated with
+	<seealso marker="crypto:crypto#strong_rand_bytes-1"><c>crypto:strong_rand_bytes(8)</c></seealso>.</p>
+      </desc>
+    </datatype>
+
+    <datatype>
+      <name name="public_key"/>
+      <name name="rsa_public_key"/>
+      <name name="dsa_public_key"/>
+      <name name="ec_public_key"/>
+      <name name="ecpk_parameters"/>
+      <name name="ecpk_parameters_api"/>
+      <desc>
+      </desc>
+    </datatype>
+
+    <datatype>
+      <name name="private_key"/>
+      <name name="rsa_private_key"/>
+      <name name="dsa_private_key"/>
+      <name name="ec_private_key"/>
+      <desc>
+      </desc>
+    </datatype>
+
+    <datatype>
+      <name name="key_params"/>
+      <desc>
+      </desc>
+    </datatype>
+
+    <datatype>
+      <name name="digest_type"/>
+      <desc>
+      </desc>
+    </datatype>
+
+    <datatype>
+      <name name="crl_reason"/>
+      <desc>
+      </desc>
+    </datatype>
+
+    <datatype>
+      <name name="issuer_id"/>
+      <desc>
+      </desc>
+    </datatype>
+
+    <datatype>
+      <name name="issuer_name"/>
+      <desc>
+      </desc>
+    </datatype>
+
+    <datatype>
+      <name name="ssh_file"/>
+      <desc>
+      </desc>
+    </datatype>
+
+
+
+  </datatypes>
 
-    <p>The following data types are used in the functions for <c>public_key</c>:</p>
-
-    <taglist>
-      <tag><c>oid()</c></tag>
-      <item><p>Object identifier, a tuple of integers as generated by the <c>ASN.1</c> compiler.</p></item>
-
-      <tag><c>boolean() =</c></tag>
-      <item><p><c>true | false</c></p></item>
-      
-      <tag><c>string() =</c></tag>
-      <item><p><c>[bytes()]</c></p></item>
-
-      <tag><c>der_encoded() =</c></tag>
-      <item><p><c>binary()</c></p></item>
-
-      <tag><c>pki_asn1_type() =</c></tag>
-      <item>
-	<p><c>'Certificate'</c></p>
-	<p><c>| 'RSAPrivateKey'</c></p>
-	<p><c>| 'RSAPublicKey'</c></p>
-	<p><c>| 'DSAPrivateKey'</c></p>
-	<p><c>| 'DSAPublicKey'</c></p>
-	<p><c>| 'DHParameter'</c></p>
-	<p><c>| 'SubjectPublicKeyInfo'</c></p>
-	<p><c>| 'PrivateKeyInfo'</c></p>
-	<p><c>| 'CertificationRequest'</c></p>
-	<p><c>| 'CertificateList'</c></p>
-	<p><c>| 'ECPrivateKey'</c></p>
-	<p><c>| 'EcpkParameters'</c></p>
-      </item>
-
-      <tag><c>pem_entry () =</c></tag>
-      <item><p><c>{pki_asn1_type(), binary(), %% DER or encrypted DER</c></p>
-      <p><c> not_encrypted | cipher_info()}</c></p></item>
-      
-      <tag><c>cipher_info() = </c></tag>
-      <item><p><c>{"RC2-CBC" | "DES-CBC" | "DES-EDE3-CBC", crypto:strong_rand_bytes(8)</c></p>
-      <p><c>| {#'PBEParameter{}, digest_type()} | #'PBES2-params'{}}</c></p>
-      </item>
-      
-      <tag><marker id="type-public_key"/>
-      <c>public_key() =</c></tag>
-      <item><p><c>rsa_public_key() | dsa_public_key() | ec_public_key()</c></p></item>
-      
-      <tag><marker id="type-private_key"/>
-      <c>private_key() =</c></tag>
-      <item><p><c>rsa_private_key() | dsa_private_key() | ec_private_key()</c></p></item>
-
-      <tag><c>rsa_public_key() =</c></tag>
-      <item><p><c>#'RSAPublicKey'{}</c></p></item>
-
-      <tag><c>rsa_private_key() =</c></tag>
-      <item><p><c>#'RSAPrivateKey'{}</c></p></item>
-
-      <tag><c>dsa_public_key() =</c></tag>
-      <item><p><c>{integer(),  #'Dss-Parms'{}}</c></p></item>
-
-      <tag><c>dsa_private_key() =</c></tag>
-      <item><p><c>#'DSAPrivateKey'{}</c></p></item>
-
-      <tag><c>ec_public_key()</c></tag>
-      <item><p>= <c>{#'ECPoint'{}, #'ECParameters'{} | {namedCurve, oid()}}</c></p></item>
-
-      <tag><c>ec_private_key() =</c></tag>
-      <item><p><c>#'ECPrivateKey'{}</c></p></item>
-
-      <tag><c>key_params() =</c></tag>
-      <item><p> #'DHParameter'{} |  {namedCurve, oid()} |  #'ECParameters'{} 
-      | {rsa, Size::integer(), PubExp::integer()} </p></item>      
-
-      <tag><c>public_crypt_options() =</c></tag>
-      <item><p><c>[{rsa_pad, rsa_padding()}]</c></p></item>
-
-      <tag><c>rsa_padding() =</c></tag>
-      <item>
-	<p><c>'rsa_pkcs1_padding'</c></p>
-	<p><c>| 'rsa_pkcs1_oaep_padding'</c></p>
-	<p><c>| 'rsa_no_padding'</c></p>
-      </item>
-
-      <tag><c>public_sign_options() =</c></tag>
-      <item><p><c>[{rsa_pad, rsa_sign_padding()} | {rsa_pss_saltlen, integer()}]</c></p></item>
-
-      <tag><c>rsa_sign_padding() =</c></tag>
-      <item>
-	<p><c>'rsa_pkcs1_padding'</c></p>
-	<p><c>| 'rsa_pkcs1_pss_padding'</c></p>
-      </item>
-
-      <tag><c>digest_type() = </c></tag>
-      <item><p>Union of <c>rsa_digest_type()</c>, <c>dss_digest_type()</c>, 
-      and <c>ecdsa_digest_type()</c>.</p></item>
-
-      <tag><c>rsa_digest_type() = </c></tag>
-      <item><p><c>'md5' | 'ripemd160' | 'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512'</c></p></item>
-
-      <tag><c>dss_digest_type() = </c></tag>
-      <item><p><c>'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512'</c></p>
-      <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>
-      </item>
-
-      <tag><c>ecdsa_digest_type() = </c></tag>
-      <item><p><c>'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512'</c></p></item>
-      
-      <tag><c>crl_reason() = </c></tag>
-      <item>
-	<p><c>unspecified</c></p>
-	<p><c>| keyCompromise</c></p>
-	<p><c>| cACompromise</c></p>
-	<p><c>| affiliationChanged</c></p>
-	<p><c>| superseded</c></p>
-	<p><c>| cessationOfOperation</c></p>
-	<p><c>| certificateHold</c></p>
-	<p><c>| privilegeWithdrawn</c></p>
-	<p><c>| aACompromise</c></p>
-      </item>
-
-      <tag><c>issuer_name() =</c></tag>
-      <item><p><c>{rdnSequence,[#'AttributeTypeAndValue'{}]}</c></p>  
-      </item>
-      
-      <tag><c>ssh_file() =</c></tag>
-      <item>
-	<p><c>openssh_public_key</c></p>
-	<p><c>| rfc4716_public_key</c></p>
-	<p><c>| known_hosts</c></p>
-	<p><c>| auth_keys</c></p>
-      </item>
-    </taglist>
-    
-    
-<!--     <p><code>policy_tree() = [Root, Children]</code></p> -->
-    
-<!--     <p><code>Root = #policy_tree_node{}</code></p>    -->
-
-<!--     <p><code>Children = [] | policy_tree()</code></p> -->
-	
-<!--     <p>The <c>policy_tree_node</c> record has the following fields:</p> -->
-    
-<!--     <taglist> -->
-      
-<!--       <tag>valid_policy</tag> -->
-<!--       <item>A single policy OID representing a -->
-<!--          valid policy for the path of length x.</item> -->
-      
-<!--       <tag>qualifier_set</tag> -->
-<!--       <item>A set of policy qualifiers associated -->
-<!--          with the valid policy in certificate x.</item> -->
-      
-<!--       <tag>critically_indicator</tag> -->
-<!--       <item>Indicates whether the -->
-<!--          certificate policy extension in certificate x was marked as -->
-<!--          critical.</item> -->
-      
-<!--       <tag>expected_policy_set</tag> -->
-<!--       <item>Contains one or more policy OIDs -->
-<!--          that would satisfy this policy in the certificate x+1.</item>         -->
-<!--     </taglist> -->
-  </section> 
 
 <funcs>    
 
   <func>
-    <name>compute_key(OthersKey, MyKey)-></name>
-    <name>compute_key(OthersKey, MyKey, Params)-></name>
+    <name name="compute_key" arity="2"/>
+    <fsummary>Computes shared secret.</fsummary>
+  <desc>
+    <p>Computes shared secret.</p>
+  </desc>
+  </func>
+
+  <func>
+    <name name="compute_key" arity="3"/>
     <fsummary>Computes shared secret.</fsummary>
-    <type>
-      <v>OthersKey = #'ECPoint'{} | binary(), MyKey = #'ECPrivateKey'{} | binary()</v>
-      <v>Params =  #'DHParameter'{}</v>
-    </type>
   <desc>
     <p>Computes shared secret.</p>
   </desc>
   </func>
 
   <func>
-    <name>decrypt_private(CipherText, Key) -> binary()</name>
-    <name>decrypt_private(CipherText, Key, Options) -> binary()</name>
+    <name name="decrypt_private" arity="2"/>
+    <name name="decrypt_private" arity="3"/>
     <fsummary>Public-key decryption.</fsummary>
-    <type>
-      <v>CipherText = binary()</v>
-      <v>Key = rsa_private_key()</v>
-      <v>Options = public_crypt_options()</v>
-  </type> 
   <desc> 
     <p>Public-key decryption using the private key. See also <seealso
 	marker="crypto:crypto#private_decrypt/4">crypto:private_decrypt/4</seealso></p> 
@@ -248,14 +187,9 @@
   </func>
 
   <func>
-    <name>decrypt_public(CipherText, Key) - > binary()</name>
-    <name>decrypt_public(CipherText, Key, Options) - > binary()</name>
+    <name name="decrypt_public" arity="2"/>
+    <name name="decrypt_public" arity="3"/>
     <fsummary>Public-key decryption.</fsummary>
-    <type>
-      <v>CipherText = binary()</v>
-      <v>Key = rsa_public_key()</v>
-      <v>Options = public_crypt_options()</v>
-  </type> 
   <desc> 
     <p>Public-key decryption using the public key. See also <seealso
 	marker="crypto:crypto#public_decrypt/4">crypto:public_decrypt/4</seealso></p> 
@@ -263,47 +197,24 @@
   </func> 
 
   <func>
-    <name>der_decode(Asn1type, Der) -> term()</name>
+    <name name="der_decode" arity="2"/>
     <fsummary>Decodes a public-key ASN.1 DER encoded entity.</fsummary>
-    <type>
-      <v>Asn1Type = atom()</v>
-      <d>ASN.1 type present in the Public Key applications
-      ASN.1 specifications.</d>
-      <v>Der = der_encoded()</v>
-    </type> 
-    <desc> 
+    <desc>
       <p>Decodes a public-key ASN.1 DER encoded entity.</p>
     </desc> 
   </func>
-    
+
   <func>
-    <name>der_encode(Asn1Type, Entity) -> der_encoded()</name>
+    <name name="der_encode" arity="2"/>
     <fsummary>Encodes a public-key entity with ASN.1 DER encoding.</fsummary>
-    <type>
-      <v>Asn1Type = atom()</v>
-      <d>ASN.1 type present in the Public Key applications
-	 ASN.1 specifications.</d>
-      <v>Entity = term()</v>
-      <d>Erlang representation of <c>Asn1Type</c></d>
-  </type> 
   <desc> 
     <p>Encodes a public-key entity with ASN.1 DER encoding.</p>
   </desc> 
   </func>
 
   <func>
-    <name>dh_gex_group(MinSize, SuggestedSize, MaxSize, Groups) -> {ok, {Size,Group}} | {error,Error}</name>
+    <name name="dh_gex_group" arity="4"/>
     <fsummary>Selects a group for Diffie-Hellman key exchange</fsummary>
-    <type>
-      <v>MinSize = positive_integer()</v>
-      <v>SuggestedSize = positive_integer()</v>
-      <v>MaxSize = positive_integer()</v>
-      <v>Groups = undefined | [{Size,[{G,P}]}]</v>
-      <v>Size = positive_integer()</v>
-      <v>Group = {G,P}</v>
-      <v>G = positive_integer()</v>
-      <v>P = positive_integer()</v>
-    </type>
     <desc>
       <p>Selects a group for Diffie-Hellman key exchange with the key size in the range <c>MinSize...MaxSize</c>
       and as close to <c>SuggestedSize</c> as possible. If <c>Groups == undefined</c> a default set will be
@@ -322,13 +233,10 @@
     </desc>
   </func>
 
-    <func>
-    <name>encrypt_private(PlainText, Key) -> binary()</name>
+  <func>
+    <name name="encrypt_private" arity="2"/>
+    <name name="encrypt_private" arity="3"/>
     <fsummary>Public-key encryption using the private key.</fsummary>
-    <type>
-      <v>PlainText = binary()</v>
-      <v>Key = rsa_private_key()</v> 
-  </type> 
   <desc> 
     <p>Public-key encryption using the private key.
      See also <seealso
@@ -337,12 +245,9 @@
   </func>   
 
   <func>
-    <name>encrypt_public(PlainText, Key) -> binary()</name>
+    <name name="encrypt_public" arity="2"/>
+    <name name="encrypt_public" arity="3"/>
     <fsummary>Public-key encryption using the public key.</fsummary>
-    <type>
-      <v>PlainText = binary()</v>
-      <v>Key = rsa_public_key()</v> 
-  </type> 
   <desc> 
     <p>Public-key encryption using the public key. See also <seealso
 	marker="crypto:crypto#public_encrypt/4">crypto:public_encrypt/4</seealso>.</p> 
@@ -350,11 +255,8 @@
   </func>   
   
   <func>
-    <name>generate_key(Params) -> {Public::binary(), Private::binary()}  | #'ECPrivateKey'{} | #'RSAPrivateKey'{}</name>
+    <name name="generate_key" arity="1"/>
     <fsummary>Generates a new keypair.</fsummary>
-    <type>
-      <v>Params = key_params()</v>
-    </type>
   <desc>
     <p>Generates a new keypair. Note that except for Diffie-Hellman
     the public key is included in the private key structure. See also
@@ -364,38 +266,27 @@
   </func>
 
   <func>
-    <name>pem_decode(PemBin) -> [pem_entry()]</name>
+    <name name="pem_decode" arity="1"/>
     <fsummary>Decodes PEM binary data and returns
     entries as ASN.1 DER encoded entities.</fsummary>
-    <type>
-      <v>PemBin = binary()</v>
-      <d>Example {ok, PemBin} = file:read_file("cert.pem").</d>
-    </type> 
   <desc> 
-    <p>Decodes PEM binary data and returns
-    entries as ASN.1 DER encoded entities.</p>
+    <p>Decodes PEM binary data and returns entries as ASN.1 DER encoded entities.</p>
+    <p>Example <c>{ok, PemBin} = file:read_file("cert.pem").</c></p>
   </desc> 
   </func> 
     
-   <func>
-    <name>pem_encode(PemEntries) -> binary()</name>
+  <func>
+    <name name="pem_encode" arity="1"/>
     <fsummary>Creates a PEM binary.</fsummary>
-    <type>
-      <v> PemEntries = [pem_entry()] </v> 
-  </type> 
-  <desc> 
-    <p>Creates a PEM binary.</p> 
-  </desc> 
+    <desc> 
+      <p>Creates a PEM binary.</p> 
+    </desc> 
   </func>
 
-   <func>
-    <name>pem_entry_decode(PemEntry) -> term()</name>
-    <name>pem_entry_decode(PemEntry, Password) -> term()</name>
+  <func>
+    <name name="pem_entry_decode" arity="1"/>
+    <name name="pem_entry_decode" arity="2"/>
     <fsummary>Decodes a PEM entry.</fsummary>
-    <type>
-      <v>PemEntry = pem_entry()</v> 
-      <v>Password = string()</v> 
-  </type> 
   <desc> 
     <p>Decodes a PEM entry. <c>pem_decode/1</c> returns a list of PEM
     entries. Notice that if the PEM entry is of type
@@ -404,51 +295,36 @@
   </desc> 
   </func>
 
-   <func>
-    <name>pem_entry_encode(Asn1Type, Entity) -> pem_entry()</name>
-    <name>pem_entry_encode(Asn1Type, Entity, {CipherInfo, Password}) -> pem_entry()</name>
+  <func>
+    <name name="pem_entry_encode" arity="2"/>
+    <name name="pem_entry_encode" arity="3"/>
     <fsummary>Creates a PEM entry that can be fed to <c>pem_encode/1</c>.</fsummary>
-    <type>
-      <v>Asn1Type = pki_asn1_type()</v>
-      <v>Entity = term()</v>
-      <d>Erlang representation of
-      <c>Asn1Type</c>.  If <c>Asn1Type</c> is 'SubjectPublicKeyInfo',
+    <desc> 
+      <p>Creates a PEM entry that can be feed to <c>pem_encode/1</c>.</p>
+      <p>If <c>Asn1Type</c> is <c>'SubjectPublicKeyInfo'</c>,
       <c>Entity</c> must be either an <c>rsa_public_key()</c>, 
       <c>dsa_public_key()</c> or an <c>ec_public_key()</c>
       and this function creates the appropriate
-      'SubjectPublicKeyInfo' entry.
-      </d>
-      <v>CipherInfo = cipher_info()</v>
-      <v>Password = string()</v> 
-    </type> 
-  <desc> 
-    <p>Creates a PEM entry that can be feed to <c>pem_encode/1</c>.</p>
-  </desc> 
+      <c>'SubjectPublicKeyInfo'</c> entry.
+      </p>
+    </desc> 
   </func>
-  
+
   <func>
-    <name>pkix_decode_cert(Cert, otp|plain) ->  #'Certificate'{} | #'OTPCertificate'{}</name>
+    <name name="pkix_decode_cert" arity="2"/>
     <fsummary>Decodes an ASN.1 DER-encoded PKIX x509 certificate.</fsummary>
-    <type>
-      <v>Cert = der_encoded()</v> 
-  </type> 
-  <desc> 
-    <p>Decodes an ASN.1 DER-encoded PKIX certificate. Option <c>otp</c>
-    uses the customized ASN.1 specification OTP-PKIX.asn1 for
-    decoding and also recursively decode most of the standard
-    parts.</p>
-  </desc> 
+    <desc> 
+      <p>Decodes an ASN.1 DER-encoded PKIX certificate. Option <c>otp</c>
+      uses the customized ASN.1 specification OTP-PKIX.asn1 for
+      decoding and also recursively decode most of the standard
+      parts.</p>
+    </desc> 
   </func>
 
   <func>
-    <name>pkix_encode(Asn1Type, Entity, otp | plain) -> der_encoded()</name>
+    <name name="pkix_encode" arity="3"/>
     <fsummary>DER encodes a PKIX x509 certificate or part of such a
     certificate.</fsummary>
-    <type>
-      <v>Asn1Type = atom()</v>
-      <d>The ASN.1 type can be 'Certificate', 'OTPCertificate' or a subtype of either.</d>
-      <v>Entity = #'Certificate'{} | #'OTPCertificate'{} | a valid subtype</v>
-  </type> 
   <desc> 
     <p>DER encodes a PKIX x509 certificate or part of such a
     certificate. This function must be used for encoding certificates or parts of certificates
@@ -458,69 +334,47 @@
   </func>
 
  <func>
-    <name>pkix_is_issuer(Cert, IssuerCert) -> boolean()</name>
-    <fsummary>Checks if <c>IssuerCert</c> issued <c>Cert</c>.</fsummary>
-    <type>
-      <v>Cert = der_encoded() | #'OTPCertificate'{} | #'CertificateList'{}</v>
-      <v>IssuerCert = der_encoded() | #'OTPCertificate'{}</v>
-  </type> 
-  <desc> 
-    <p>Checks if <c>IssuerCert</c> issued <c>Cert</c>.</p> 
-  </desc> 
-  </func>
+   <name name="pkix_is_issuer" arity="2"/>
+   <fsummary>Checks if <c>IssuerCert</c> issued <c>Cert</c>.</fsummary>
+   <desc> 
+     <p>Checks if <c>IssuerCert</c> issued <c>Cert</c>.</p> 
+   </desc> 
+ </func>
   
-  <func>
-    <name>pkix_is_fixed_dh_cert(Cert) -> boolean()</name>
-    <fsummary>Checks if a certificate is a fixed Diffie-Hellman certificate.</fsummary>
-    <type>
-        <v>Cert = der_encoded() | #'OTPCertificate'{}</v>
-  </type> 
-  <desc> 
-    <p>Checks if a certificate is a fixed Diffie-Hellman certificate.</p> 
-  </desc> 
-  </func>  
+ <func>
+   <name name="pkix_is_fixed_dh_cert" arity="1"/>
+   <fsummary>Checks if a certificate is a fixed Diffie-Hellman certificate.</fsummary>
+   <desc> 
+     <p>Checks if a certificate is a fixed Diffie-Hellman certificate.</p> 
+   </desc> 
+ </func>  
   
-  <func>
-    <name>pkix_is_self_signed(Cert) -> boolean()</name>
-    <fsummary>Checks if a certificate is self-signed.</fsummary>
-    <type>
-       <v>Cert = der_encoded() | #'OTPCertificate'{}</v>
-  </type> 
-  <desc> 
-    <p>Checks if a certificate is self-signed.</p> 
-  </desc> 
-  </func>
+ <func>
+   <name name="pkix_is_self_signed" arity="1"/>
+   <fsummary>Checks if a certificate is self-signed.</fsummary>
+   <desc> 
+     <p>Checks if a certificate is self-signed.</p> 
+   </desc> 
+ </func>
 
-  <func>
-    <name>pkix_issuer_id(Cert, IssuedBy) -> {ok, IssuerID} | {error, Reason}</name>
-    <fsummary>Returns the issuer id.</fsummary>
-    <type>
-        <v>Cert = der_encoded() | #'OTPCertificate'{}</v>
-	<v>IssuedBy = self | other</v>
-	<v>IssuerID = {integer(), issuer_name()}</v>
-	<d>The issuer id consists of the serial number and the issuers name.</d>
-	<v>Reason = term()</v>
-    </type> 
-    <desc> 
-    <p>Returns the issuer id.</p> 
-    </desc> 
-  </func>
-  
+ <func>
+   <name name="pkix_issuer_id" arity="2"/>
+   <fsummary>Returns the issuer id.</fsummary>
+   <desc> 
+     <p>Returns the issuer id.</p> 
+   </desc> 
+ </func>
  
-  <func>
-    <name>pkix_normalize_name(Issuer) -> Normalized</name>
-    <fsummary>Normalizes an issuer name so that it can be easily
-    compared to another issuer name.</fsummary>
-    <type>
-      <v>Issuer = issuer_name()</v>
-      <v>Normalized = issuer_name()</v>
-  </type> 
-  <desc> 
-    <p>Normalizes an issuer name so that it can be easily
-    compared to another issuer name.</p> 
-  </desc> 
-  </func>
-   
+ <func>
+   <name name="pkix_normalize_name" arity="1"/>
+   <fsummary>Normalizes an issuer name so that it can be easily
+   compared to another issuer name.</fsummary>
+   <desc> 
+     <p>Normalizes an issuer name so that it can be easily
+     compared to another issuer name.</p> 
+   </desc> 
+ </func>
+
   <func>
     <name>pkix_path_validation(TrustedCert, CertChain, Options) -> {ok, {PublicKeyInfo, PolicyTree}} | {error, {bad_cert, Reason}} </name>
     <fsummary>Performs a basic path validation according to RFC 5280.</fsummary>
@@ -622,26 +476,16 @@ fun(OtpCert :: #'OTPCertificate'{},
    </func>
 
     <func>  
-      <name>pkix_crl_issuer(CRL) -> issuer_name()</name>
+      <name name="pkix_crl_issuer" arity="1"/>
       <fsummary>Returns the issuer of the <c>CRL</c>.</fsummary>
-      <type>
-	<v>CRL = der_encoded() | #'CertificateList'{} </v> 
-      </type> 
       <desc> 
 	<p>Returns the issuer of the <c>CRL</c>.</p>
       </desc> 
     </func> 
    
    <func>
-     <name>pkix_crls_validate(OTPCertificate, DPAndCRLs, Options) -> CRLStatus()</name>
+     <name name="pkix_crls_validate" arity="3"/>
      <fsummary>Performs CRL validation.</fsummary>
-     <type>
-       <v>OTPCertificate =  #'OTPCertificate'{}</v>
-       <v>DPAndCRLs  = [{DP::#'DistributionPoint'{}, {DerCRL::der_encoded(), CRL::#'CertificateList'{}}}] </v>
-       <v>Options = proplists:proplist()</v>
-       <v>CRLStatus() =  valid | {bad_cert, revocation_status_undetermined} |  {bad_cert, {revocation_status_undetermined,
-       {bad_crls, Details::term()}}} | {bad_cert, {revoked, crl_reason()}}</v>
-     </type>
      <desc>
       <p>Performs CRL validation. It is intended to be called from
       the verify fun of  <seealso marker="#pkix_path_validation-3"> pkix_path_validation/3
@@ -692,24 +536,16 @@ fun(#'DistributionPoint'{}, #'CertificateList'{},
    </func>
    
    <func>  
-     <name>pkix_crl_verify(CRL, Cert) -> boolean()</name>
+     <name name="pkix_crl_verify" arity="2"/>
      <fsummary> Verify that  <c>Cert</c>  is the <c> CRL</c>  signer. </fsummary>
-     <type>
-       <v>CRL = der_encoded() | #'CertificateList'{} </v> 
-       <v>Cert = der_encoded() | #'OTPCertificate'{} </v> 
-     </type> 
      <desc> 
        <p>Verify that <c>Cert</c> is the <c>CRL</c> signer.</p>
      </desc> 
    </func>
 
    <func>  
-     <name>pkix_dist_point(Cert) -> DistPoint</name>
+     <name name="pkix_dist_point" arity="1"/>
      <fsummary>Creates a distribution point for CRLs issued by the same issuer as <c>Cert</c>.</fsummary>
-     <type>
-       <v> Cert  = der_encoded() | #'OTPCertificate'{} </v> 
-       <v> DistPoint =  #'DistributionPoint'{}</v> 
-     </type> 
      <desc> 
        <p>Creates a distribution point for CRLs issued by the same issuer as <c>Cert</c>.
        Can be used as input to <seealso
@@ -719,26 +555,17 @@ fun(#'DistributionPoint'{}, #'CertificateList'{},
    </func>
    
    <func>  
-     <name>pkix_dist_points(Cert) -> DistPoints</name>
+     <name name="pkix_dist_points" arity="1"/>
      <fsummary> Extracts distribution points from the certificates extensions.</fsummary>
-     <type>
-       <v> Cert  = der_encoded() | #'OTPCertificate'{} </v> 
-       <v> DistPoints =  [#'DistributionPoint'{}]</v> 
-     </type> 
      <desc> 
        <p> Extracts distribution points from the certificates extensions.</p>
      </desc> 
  </func>
    
   <func>
-    <name>pkix_match_dist_point(CRL, DistPoint) -> boolean()</name>
+    <name name="pkix_match_dist_point" arity="2"/>
     <fsummary>Checks whether the given distribution point matches the
     Issuing Distribution Point of the CRL.</fsummary>
-
-    <type>
-      <v>CRL = der_encoded() | #'CertificateList'{} </v>
-      <v>DistPoint = #'DistributionPoint'{}</v>
-    </type>
     <desc>
       <p>Checks whether the given distribution point matches the
       Issuing Distribution Point of the CRL, as described in RFC 5280.
@@ -748,11 +575,8 @@ fun(#'DistributionPoint'{}, #'CertificateList'{},
   </func>
 
   <func>
-    <name>pkix_sign(#'OTPTBSCertificate'{}, Key) -> der_encoded()</name>
+    <name name="pkix_sign" arity="2"/>
     <fsummary>Signs certificate.</fsummary>
-    <type>
-      <v>Key = rsa_private_key() | dsa_private_key()</v> 
-    </type> 
     <desc> 
       <p>Signs an 'OTPTBSCertificate'. Returns the corresponding
       DER-encoded certificate.</p> 
@@ -760,17 +584,12 @@ fun(#'DistributionPoint'{}, #'CertificateList'{},
   </func> 
 
   <func>
-    <name>pkix_sign_types(AlgorithmId) -> {DigestType, SignatureType}</name>
+    <name name="pkix_sign_types" arity="1"/>
     <fsummary>Translates signature algorithm OID to Erlang digest and signature algorithm types.</fsummary>
-    <type>
-      <v>AlgorithmId = oid()</v>
-      <d>Signature OID from a certificate or a certificate revocation list.</d>
-      <v>DigestType = rsa_digest_type() | dss_digest_type()</v>
-      <v>SignatureType = rsa | dsa | ecdsa</v>
-    </type>
     <desc>
       <p>Translates signature algorithm OID to Erlang digest and signature types.
       </p>
+      <p>The <c>AlgorithmId</c> is the signature OID from a certificate or a certificate revocation list.</p>
     </desc>
   </func>
 
@@ -938,12 +757,8 @@ fun(#'DistributionPoint'{}, #'CertificateList'{},
   </func>
 
   <func>  
-    <name>pkix_verify(Cert, Key) -> boolean()</name>
+    <name name="pkix_verify" arity="2"/>
     <fsummary>Verifies PKIX x.509 certificate signature.</fsummary>
-    <type>
-      <v>Cert = der_encoded()</v>
-      <v>Key = rsa_public_key() | dsa_public_key() | ec_public_key()</v> 
-    </type> 
   <desc> 
     <p>Verifies PKIX x.509 certificate signature.</p>
   </desc> 
@@ -1059,41 +874,30 @@ end
   
 
   <func>
-    <name>sign(Msg, DigestType, Key) -> binary()</name>
-    <name>sign(Msg, DigestType, Key, Options) -> binary()</name>
+    <name name="sign" arity="3"/>
+    <name name="sign" arity="4"/>
     <fsummary>Creates a digital signature.</fsummary>
-    <type>
-       <v>Msg = binary() | {digest,binary()}</v>
-       <d>The <c>Msg</c> is either the binary "plain text" data to be
-       signed or it is the hashed value of "plain text", that is, the
-       digest.</d>
-       <v>DigestType = rsa_digest_type() | dss_digest_type() | ecdsa_digest_type()</v>
-       <v>Key = rsa_private_key() | dsa_private_key() | ec_private_key()</v>
-       <v>Options = public_sign_options()</v>
-  </type>
   <desc>
     <p>Creates a digital signature.</p> 
+    <p>The <c>Msg</c> is either the binary "plain text" data to be
+    signed or it is the hashed value of "plain text", that is, the
+    digest.</p>
   </desc> 
   </func>   
 
   <func>
-    <name>ssh_decode(SshBin,  Type) -> [{public_key(), Attributes::list()}]</name>
+    <name name="ssh_decode" arity="2"/>
     <fsummary>Decodes an SSH file-binary.</fsummary>
-    <type>
-      <v>SshBin = binary()</v>
-      <d>Example <c>{ok, SshBin} = file:read_file("known_hosts")</c>.</d>
-      <v>Type = public_key | ssh_file()</v>
-      <d>If <c>Type</c> is <c>public_key</c> the binary can be either
-      an RFC4716 public key or an OpenSSH public key.</d>
-    </type>
-  <desc>
-    <p>Decodes an SSH file-binary. In the case of <c>known_hosts</c> or
-    <c>auth_keys</c>, the binary can include one or more lines of the
-    file. Returns a list of public keys and their attributes, possible
-    attribute values depends on the file type represented by the
-    binary.
-    </p>
-
+    <desc>
+      <p>Decodes an SSH file-binary. In the case of <c>known_hosts</c> or
+      <c>auth_keys</c>, the binary can include one or more lines of the
+      file. Returns a list of public keys and their attributes, possible
+      attribute values depends on the file type represented by the
+      binary.
+      </p>
+      <p>If the <c>Type</c> is <c>ssh2_pubkey</c>, the result will be
+      <c>Decoded_ssh2_pubkey</c>. Otherwise it will be <c>Decoded_OtherType</c>.
+      </p>
     <taglist>
       <tag>RFC4716 attributes - see RFC 4716.</tag>
       <item><p>{headers, [{string(), utf8_string()}]}</p></item>
@@ -1106,23 +910,25 @@ end
       <item>{comment, string()}</item>
       <item><p>{bits, integer()} - In SSH version 1 files.</p></item>
     </taglist>
-
+      <p>Example: <c>{ok, SshBin} = file:read_file("known_hosts")</c>.
+      </p>
+      <p>If <c>Type</c> is <c>public_key</c> the binary can be either
+      an RFC4716 public key or an OpenSSH public key.</p>
   </desc>
   </func>
 
   <func>
-    <name>ssh_encode([{Key, Attributes}], Type) -> binary()</name>
+    <name name="ssh_encode" arity="2"/>
     <fsummary>Encodes a list of SSH file entries to a binary.</fsummary>
-    <type>
-      <v>Key = public_key()</v>
-      <v>Attributes = list()</v>
-      <v>Type = ssh_file()</v>
-    </type>
-  <desc>
-    <p>Encodes a list of SSH file entries (public keys and attributes) to a binary. Possible
-    attributes depend on the file type, see <seealso
-    marker="#ssh_decode-2"> ssh_decode/2 </seealso>.</p>
-  </desc>
+    <desc>
+      <p>Encodes a list of SSH file entries (public keys and attributes) to a binary. Possible
+      attributes depend on the file type, see
+      <seealso marker="#ssh_decode-2"> ssh_decode/2 </seealso>.
+      </p>
+      <p>If the <c>Type</c> is <c>ssh2_pubkey</c>, the <c>InData</c> shall be
+      <c>InData_ssh2_pubkey</c>. Otherwise it shall be <c>OtherInData</c>.
+      </p>
+    </desc>
   </func>
 
   <func>
@@ -1131,8 +937,8 @@ end
     <name>ssh_hostkey_fingerprint([DigestType], HostKey) -> [string()]</name>
     <fsummary>Calculates a ssh fingerprint for a hostkey.</fsummary>
     <type>
-      <v>Key = public_key()</v>
-      <v>DigestType = digest_type()</v>
+      <v>HostKey = <seealso marker="#type-public_key">public_key()</seealso></v>
+      <v>DigestType = <seealso marker="#type-digest_type">digest_type()</seealso></v>
     </type>
   <desc>
     <p>Calculates a ssh fingerprint from a public host key as openssh does.</p>
@@ -1161,29 +967,19 @@ end
   </func>
 
   <func>
-    <name>verify(Msg, DigestType, Signature, Key) -> boolean()</name>
-    <name>verify(Msg, DigestType, Signature, Key, Options) -> boolean()</name>
+    <name name="verify" arity="4"/>
+    <name name="verify" arity="5"/>
     <fsummary>Verifies a digital signature.</fsummary>
-    <type>
-      <v>Msg = binary() | {digest,binary()}</v>
-       <d>The <c>Msg</c> is either the binary "plain text" data 
-        or it is the hashed value of "plain text", that is, the digest.</d>
-      <v>DigestType = rsa_digest_type() | dss_digest_type() | ecdsa_digest_type()</v>
-      <v>Signature = binary()</v>
-      <v>Key = rsa_public_key() | dsa_public_key() | ec_public_key()</v>
-      <v>Options = public_sign_options()</v>
-  </type>
   <desc>
     <p>Verifies a digital signature.</p>
+    <p>The <c>Msg</c> is either the binary "plain text" data 
+    or it is the hashed value of "plain text", that is, the digest.</p>
   </desc> 
   </func>
 
   <func>
-    <name>short_name_hash(Name) -> string()</name>
+    <name name="short_name_hash" arity="1"/>
     <fsummary>Generates a short hash of an issuer name.</fsummary>
-    <type>
-      <v>Name = issuer_name()</v>
-    </type>
     <desc>
       <p>Generates a short hash of an issuer name.  The hash is
       returned as a string containing eight hexadecimal digits.</p>
-- 
cgit v1.2.3


From df39504bc6f9b106a20959b969b258db327261a5 Mon Sep 17 00:00:00 2001
From: Hans Nilsson <hans@erlang.org>
Date: Wed, 29 Aug 2018 14:18:41 +0200
Subject: ssh: Use exported crypto types

---
 lib/ssh/src/ssh.hrl | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

(limited to 'lib')

diff --git a/lib/ssh/src/ssh.hrl b/lib/ssh/src/ssh.hrl
index 66dbf0b144..94b9f3a196 100644
--- a/lib/ssh/src/ssh.hrl
+++ b/lib/ssh/src/ssh.hrl
@@ -260,13 +260,7 @@
                       | accept_callback()
                       | {HashAlgoSpec::fp_digest_alg(), accept_callback()}.
 
--type fp_digest_alg() :: 'md5' |
-                        'sha' |
-                        'sha224' |
-                        'sha256' |
-                        'sha384' |
-                        'sha512'
-                        .
+-type fp_digest_alg() :: 'md5' | crypto:sha1() | crypto:sha2() .
 
 -type accept_callback() :: fun((PeerName::string(), fingerprint() ) -> boolean()) .
 -type fingerprint() :: string() | [string()].
-- 
cgit v1.2.3