aboutsummaryrefslogtreecommitdiffstats
path: root/lib/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'lib/crypto')
-rw-r--r--lib/crypto/c_src/crypto.c192
-rw-r--r--lib/crypto/c_src/otp_test_engine.c3
-rw-r--r--lib/crypto/doc/specs/.gitignore1
-rw-r--r--lib/crypto/doc/src/Makefile9
-rw-r--r--lib/crypto/doc/src/algorithm_details.xml290
-rw-r--r--lib/crypto/doc/src/crypto.xml1124
-rw-r--r--lib/crypto/doc/src/engine_keys.xml2
-rw-r--r--lib/crypto/doc/src/notes.xml31
-rw-r--r--lib/crypto/doc/src/specs.xml4
-rw-r--r--lib/crypto/doc/src/usersguide.xml1
-rw-r--r--lib/crypto/src/crypto.erl1016
-rw-r--r--lib/crypto/test/crypto_SUITE.erl199
-rw-r--r--lib/crypto/vsn.mk2
13 files changed, 1978 insertions, 896 deletions
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index ba50dd4a53..6949df4b8e 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -172,12 +172,11 @@
# define HAVE_EC
#endif
-// (test for == 1.1.1pre8)
-#if OPENSSL_VERSION_NUMBER == (PACKED_OPENSSL_VERSION_PLAIN(1,1,1) - 7) \
+// (test for >= 1.1.1pre8)
+#if OPENSSL_VERSION_NUMBER >= (PACKED_OPENSSL_VERSION_PLAIN(1,1,1) - 7) \
&& !defined(HAS_LIBRESSL) \
&& defined(HAVE_EC)
-// EXPERIMENTAL:
-# define HAVE_EDDH
+# define HAVE_ED_CURVE_DH
#endif
#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION(0,9,8,'c')
@@ -195,11 +194,19 @@
#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,1,0)
# ifndef HAS_LIBRESSL
+# define HAVE_CHACHA20
# define HAVE_CHACHA20_POLY1305
# define HAVE_RSA_OAEP_MD
# endif
#endif
+// OPENSSL_VERSION_NUMBER >= 1.1.1-pre8
+#if OPENSSL_VERSION_NUMBER >= (PACKED_OPENSSL_VERSION_PLAIN(1,1,1)-7)
+# ifndef HAS_LIBRESSL
+# define HAVE_POLY1305
+# endif
+#endif
+
#if OPENSSL_VERSION_NUMBER <= PACKED_OPENSSL_VERSION(0,9,8,'l')
# define HAVE_ECB_IVEC_BUG
#endif
@@ -541,6 +548,11 @@ static ERL_NIF_TERM aes_gcm_decrypt_NO_EVP(ErlNifEnv* env, int argc, const ERL_N
static ERL_NIF_TERM chacha20_poly1305_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM chacha20_poly1305_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM chacha20_stream_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM chacha20_stream_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+
+static ERL_NIF_TERM poly1305_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+
static ERL_NIF_TERM engine_by_id_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM engine_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM engine_finish_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
@@ -631,6 +643,12 @@ static ErlNifFunc nif_funcs[] = {
{"chacha20_poly1305_encrypt", 4, chacha20_poly1305_encrypt},
{"chacha20_poly1305_decrypt", 5, chacha20_poly1305_decrypt},
+ {"chacha20_stream_init", 2, chacha20_stream_init},
+ {"chacha20_stream_encrypt", 2, chacha20_stream_crypt},
+ {"chacha20_stream_decrypt", 2, chacha20_stream_crypt},
+
+ {"poly1305_nif", 2, poly1305_nif},
+
{"engine_by_id_nif", 1, engine_by_id_nif},
{"engine_init_nif", 1, engine_init_nif},
{"engine_finish_nif", 1, engine_finish_nif},
@@ -704,8 +722,7 @@ static ERL_NIF_TERM atom_rsa;
static ERL_NIF_TERM atom_dss;
static ERL_NIF_TERM atom_ecdsa;
-#ifdef HAVE_EDDH
-static ERL_NIF_TERM atom_eddh;
+#ifdef HAVE_ED_CURVE_DH
static ERL_NIF_TERM atom_x25519;
static ERL_NIF_TERM atom_x448;
#endif
@@ -1150,8 +1167,7 @@ static int initialize(ErlNifEnv* env, ERL_NIF_TERM load_info)
atom_rsa = enif_make_atom(env,"rsa");
atom_dss = enif_make_atom(env,"dss");
atom_ecdsa = enif_make_atom(env,"ecdsa");
-#ifdef HAVE_EDDH
- atom_eddh = enif_make_atom(env,"eddh");
+#ifdef HAVE_ED_CURVE_DH
atom_x25519 = enif_make_atom(env,"x25519");
atom_x448 = enif_make_atom(env,"x448");
#endif
@@ -1300,7 +1316,7 @@ static ERL_NIF_TERM algo_pubkey[11]; /* increase when extending the list */
static int algo_cipher_cnt, algo_cipher_fips_cnt;
static ERL_NIF_TERM algo_cipher[24]; /* increase when extending the list */
static int algo_mac_cnt, algo_mac_fips_cnt;
-static ERL_NIF_TERM algo_mac[2]; /* increase when extending the list */
+static ERL_NIF_TERM algo_mac[3]; /* increase when extending the list */
static int algo_curve_cnt, algo_curve_fips_cnt;
static ERL_NIF_TERM algo_curve[87]; /* increase when extending the list */
@@ -1352,9 +1368,6 @@ static void init_algorithms_types(ErlNifEnv* env)
#endif
// Non-validated algorithms follow
algo_pubkey_fips_cnt = algo_pubkey_cnt;
-#ifdef HAVE_EDDH
- algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "eddh");
-#endif
algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "srp");
// Validated algorithms first
@@ -1400,13 +1413,19 @@ static void init_algorithms_types(ErlNifEnv* env)
#if defined(HAVE_CHACHA20_POLY1305)
algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"chacha20_poly1305");
#endif
-
+#if defined(HAVE_CHACHA20)
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"chacha20");
+#endif
+
// Validated algorithms first
algo_mac_cnt = 0;
algo_mac[algo_mac_cnt++] = enif_make_atom(env,"hmac");
#ifdef HAVE_CMAC
algo_mac[algo_mac_cnt++] = enif_make_atom(env,"cmac");
#endif
+#ifdef HAVE_POLY1305
+ algo_mac[algo_mac_cnt++] = enif_make_atom(env,"poly1305");
+#endif
// Non-validated algorithms follow
algo_mac_fips_cnt = algo_mac_cnt;
@@ -1506,7 +1525,7 @@ static void init_algorithms_types(ErlNifEnv* env)
#endif
#endif
//--
-#ifdef HAVE_EDDH
+#ifdef HAVE_ED_CURVE_DH
algo_curve[algo_curve_cnt++] = enif_make_atom(env,"x25519");
algo_curve[algo_curve_cnt++] = enif_make_atom(env,"x448");
#endif
@@ -2148,6 +2167,62 @@ static ERL_NIF_TERM cmac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]
#endif
}
+/* For OpenSSL >= 1.1.1 the hmac_nif and cmac_nif could be integrated into poly1305 (with 'type' as parameter) */
+static ERL_NIF_TERM poly1305_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Key, Text) */
+#ifdef HAVE_POLY1305
+ ErlNifBinary key_bin, text, ret_bin;
+ ERL_NIF_TERM ret = atom_error;
+ EVP_PKEY *key = NULL;
+ EVP_MD_CTX *mctx = NULL;
+ EVP_PKEY_CTX *pctx = NULL;
+ const EVP_MD *md = NULL;
+ size_t size;
+ int type;
+
+ type = EVP_PKEY_POLY1305;
+
+ if (!enif_inspect_binary(env, argv[0], &key_bin) ||
+ !(key_bin.size == 32) ) {
+ return enif_make_badarg(env);
+ }
+
+ if (!enif_inspect_binary(env, argv[1], &text) ) {
+ return enif_make_badarg(env);
+ }
+
+ key = EVP_PKEY_new_raw_private_key(type, /*engine*/ NULL, key_bin.data, key_bin.size);
+
+ if (!key ||
+ !(mctx = EVP_MD_CTX_new()) ||
+ !EVP_DigestSignInit(mctx, &pctx, md, /*engine*/ NULL, key) ||
+ !EVP_DigestSignUpdate(mctx, text.data, text.size)) {
+ goto err;
+ }
+
+ if (!EVP_DigestSignFinal(mctx, NULL, &size) ||
+ !enif_alloc_binary(size, &ret_bin) ||
+ !EVP_DigestSignFinal(mctx, ret_bin.data, &size)) {
+ goto err;
+ }
+
+ if ((size != ret_bin.size) &&
+ !enif_realloc_binary(&ret_bin, size)) {
+ goto err;
+ }
+
+ ret = enif_make_binary(env, &ret_bin);
+
+ err:
+ EVP_MD_CTX_free(mctx);
+ EVP_PKEY_free(key);
+ return ret;
+
+#else
+ return atom_notsup;
+#endif
+}
+
static ERL_NIF_TERM block_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Type, Key, Ivec, Text, IsEncrypt) or (Type, Key, Text, IsEncrypt) */
struct cipher_type_t *cipherp = NULL;
@@ -2732,6 +2807,69 @@ out_err:
#endif
}
+
+static ERL_NIF_TERM chacha20_stream_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Key, IV) */
+#if defined(HAVE_CHACHA20)
+ ErlNifBinary key_bin, ivec_bin;
+ struct evp_cipher_ctx *ctx;
+ const EVP_CIPHER *cipher;
+ ERL_NIF_TERM ret;
+
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
+ || !enif_inspect_binary(env, argv[1], &ivec_bin)
+ || key_bin.size != 32
+ || ivec_bin.size != 16) {
+ return enif_make_badarg(env);
+ }
+
+ cipher = EVP_chacha20();
+
+ ctx = enif_alloc_resource(evp_cipher_ctx_rtype, sizeof(struct evp_cipher_ctx));
+ ctx->ctx = EVP_CIPHER_CTX_new();
+
+
+ EVP_CipherInit_ex(ctx->ctx, cipher, NULL,
+ key_bin.data, ivec_bin.data, 1);
+ EVP_CIPHER_CTX_set_padding(ctx->ctx, 0);
+ ret = enif_make_resource(env, ctx);
+ enif_release_resource(ctx);
+ return ret;
+#else
+ return enif_raise_exception(env, atom_notsup);
+#endif
+};
+
+static ERL_NIF_TERM chacha20_stream_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (State, Data) */
+#if defined(HAVE_CHACHA20)
+ struct evp_cipher_ctx *ctx, *new_ctx;
+ ErlNifBinary data_bin;
+ ERL_NIF_TERM ret, cipher_term;
+ unsigned char *out;
+ int outl = 0;
+
+ if (!enif_get_resource(env, argv[0], evp_cipher_ctx_rtype, (void**)&ctx)
+ || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
+ return enif_make_badarg(env);
+ }
+ new_ctx = enif_alloc_resource(evp_cipher_ctx_rtype, sizeof(struct evp_cipher_ctx));
+ new_ctx->ctx = EVP_CIPHER_CTX_new();
+ EVP_CIPHER_CTX_copy(new_ctx->ctx, ctx->ctx);
+ out = enif_make_new_binary(env, data_bin.size, &cipher_term);
+ EVP_CipherUpdate(new_ctx->ctx, out, &outl, data_bin.data, data_bin.size);
+ ASSERT(outl == data_bin.size);
+
+ ret = enif_make_tuple2(env, enif_make_resource(env, new_ctx), cipher_term);
+ enif_release_resource(new_ctx);
+ CONSUME_REDS(env,data_bin);
+ return ret;
+#else
+ return enif_raise_exception(env, atom_notsup);
+#endif
+};
+
+
static ERL_NIF_TERM strong_rand_bytes_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Bytes) */
unsigned bytes;
@@ -4012,11 +4150,10 @@ out_err:
#endif
}
-// EXPERIMENTAL!
static ERL_NIF_TERM evp_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
/* (Curve, PeerBin, MyBin) */
{
-#ifdef HAVE_EDDH
+#ifdef HAVE_ED_CURVE_DH
int type;
EVP_PKEY_CTX *ctx;
ErlNifBinary peer_bin, my_bin, key_bin;
@@ -4068,11 +4205,10 @@ static ERL_NIF_TERM evp_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_
#endif
}
-// EXPERIMENTAL!
static ERL_NIF_TERM evp_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
/* (Curve) */
{
-#ifdef HAVE_EDDH
+#ifdef HAVE_ED_CURVE_DH
int type;
EVP_PKEY_CTX *ctx;
EVP_PKEY *pkey = NULL;
@@ -4085,22 +4221,20 @@ static ERL_NIF_TERM evp_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF
if (!(ctx = EVP_PKEY_CTX_new_id(type, NULL))) return enif_make_badarg(env);
- if (!EVP_PKEY_keygen_init(ctx)) return enif_make_atom(env,"EVP_PKEY_keygen_init failed");
- if (!EVP_PKEY_keygen(ctx, &pkey)) return enif_make_atom(env,"EVP_PKEY_keygen failed");
+ if (!EVP_PKEY_keygen_init(ctx)) return atom_error;
+ if (!EVP_PKEY_keygen(ctx, &pkey)) return atom_error;
- if (!EVP_PKEY_get_raw_public_key(pkey, NULL, &key_len))
- return enif_make_atom(env,"EVP_PKEY_get_raw_public_key 1 failed");
+ if (!EVP_PKEY_get_raw_public_key(pkey, NULL, &key_len)) return atom_error;
if (!EVP_PKEY_get_raw_public_key(pkey,
enif_make_new_binary(env, key_len, &ret_pub),
&key_len))
- return enif_make_atom(env,"EVP_PKEY_get_raw_public_key 2 failed");
+ return atom_error;
- if (!EVP_PKEY_get_raw_private_key(pkey, NULL, &key_len))
- return enif_make_atom(env,"EVP_PKEY_get_raw_private_key 1 failed");
+ if (!EVP_PKEY_get_raw_private_key(pkey, NULL, &key_len)) return atom_error;
if (!EVP_PKEY_get_raw_private_key(pkey,
enif_make_new_binary(env, key_len, &ret_prv),
&key_len))
- return enif_make_atom(env,"EVP_PKEY_get_raw_private_key 2 failed");
+ return atom_error;
return enif_make_tuple2(env, ret_pub, ret_prv);
#else
@@ -5072,7 +5206,10 @@ static ERL_NIF_TERM pkey_crypt_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM
unsigned char *p;
if (rsa == NULL) goto badarg;
tmplen = RSA_size(rsa);
- if (!enif_alloc_binary(tmplen, &tmp_bin)) goto badarg;
+ if (!enif_alloc_binary(tmplen, &tmp_bin)) {
+ RSA_free(rsa);
+ goto badarg;
+ }
p = out_bin.data;
p++;
i = RSA_padding_check_SSLv23(tmp_bin.data, tmplen, p, out_bin.size - 1, tmplen);
@@ -5083,6 +5220,7 @@ static ERL_NIF_TERM pkey_crypt_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM
tmp_bin = in_bin;
i = 1;
}
+ RSA_free(rsa);
}
#endif
}
diff --git a/lib/crypto/c_src/otp_test_engine.c b/lib/crypto/c_src/otp_test_engine.c
index b6c9067964..34c825059f 100644
--- a/lib/crypto/c_src/otp_test_engine.c
+++ b/lib/crypto/c_src/otp_test_engine.c
@@ -64,7 +64,8 @@ static int test_init(ENGINE *e) {
printf("OTP Test Engine Initializatzion!\r\n");
/* Load all digest and cipher algorithms. Needed for password protected private keys */
- OpenSSL_add_all_algorithms();
+ OpenSSL_add_all_ciphers();
+ OpenSSL_add_all_digests();
return 111;
}
diff --git a/lib/crypto/doc/specs/.gitignore b/lib/crypto/doc/specs/.gitignore
new file mode 100644
index 0000000000..322eebcb06
--- /dev/null
+++ b/lib/crypto/doc/specs/.gitignore
@@ -0,0 +1 @@
+specs_*.xml
diff --git a/lib/crypto/doc/src/Makefile b/lib/crypto/doc/src/Makefile
index 2148062e78..cbcafb7375 100644
--- a/lib/crypto/doc/src/Makefile
+++ b/lib/crypto/doc/src/Makefile
@@ -39,7 +39,7 @@ XML_REF3_FILES = crypto.xml
XML_REF6_FILES = crypto_app.xml
XML_PART_FILES = usersguide.xml
-XML_CHAPTER_FILES = notes.xml licenses.xml fips.xml engine_load.xml engine_keys.xml
+XML_CHAPTER_FILES = notes.xml licenses.xml fips.xml engine_load.xml engine_keys.xml algorithm_details.xml
BOOK_FILES = book.xml
@@ -62,11 +62,17 @@ HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
+SPECS_FILES = $(XML_REF3_FILES:%.xml=$(SPECDIR)/specs_%.xml)
+
+TOP_SPECS_FILE = specs.xml
+
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
XML_FLAGS +=
+#in ssh it looks like this: SPECS_FLAGS = -I../../../public_key/include -I../../../public_key/src -I../../..
+
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
@@ -93,6 +99,7 @@ clean clean_docs clean_tex:
rm -f $(MAN3DIR)/*
rm -f $(MAN6DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
+ rm -f $(SPECS_FILES)
rm -f errs core *~
# ----------------------------------------------------
diff --git a/lib/crypto/doc/src/algorithm_details.xml b/lib/crypto/doc/src/algorithm_details.xml
new file mode 100644
index 0000000000..088f5e8e97
--- /dev/null
+++ b/lib/crypto/doc/src/algorithm_details.xml
@@ -0,0 +1,290 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>2014</year><year>2017</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ The contents of this file are subject to the Erlang Public License,
+ Version 1.1, (the "License"); you may not use this file except in
+ compliance with the License. You should have received a copy of the
+ Erlang Public License along with this software. If not, it can be
+ retrieved online at http://www.erlang.org/.
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and limitations
+ under the License.
+
+ </legalnotice>
+
+ <title>Algorithm Details</title>
+ <prepared>Hans Nilsson</prepared>
+ <docno></docno>
+ <date>2018-08-22</date>
+ <rev>A</rev>
+ <file>algorithm_details.xml</file>
+ </header>
+ <p>
+ This chapter describes details of algorithms in the crypto application.
+ </p>
+ <p>The tables only documents the supported cryptos and key lengths. The user should not draw any conclusion
+ on security from the supplied tables.
+ </p>
+
+ <section>
+ <title>Ciphers</title>
+ <section>
+ <title>Block Ciphers</title>
+ <p>To be used in
+ <seealso marker="crypto#block_encrypt-3">block_encrypt/3</seealso>,
+ <seealso marker="crypto#block_encrypt-4">block_encrypt/4</seealso>,
+ <seealso marker="crypto#block_decrypt-3">block_decrypt/3</seealso> and
+ <seealso marker="crypto#block_decrypt-4">block_decrypt/4</seealso>.
+ </p>
+ <p>Available in all OpenSSL compatible with Erlang CRYPTO if not disabled by configuration.
+ </p>
+ <p>To dynamically check availability, check that the name in the <i>Cipher and Mode</i> column is present in the
+ list with the <c>cipher</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+ <table>
+ <row><cell><strong>Cipher and Mode</strong></cell><cell><strong>Key length</strong><br/><strong>[bytes]</strong></cell><cell><strong>IV length</strong><br/><strong>[bytes]</strong></cell><cell><strong>Block size</strong><br/><strong>[bytes]</strong></cell></row>
+ <row><cell><c>aes_cbc</c></cell> <cell>16, 24, 32</cell><cell>16</cell><cell>16</cell></row>
+ <row><cell><c>aes_cbc128</c></cell><cell>16</cell><cell>16</cell><cell>16</cell></row>
+ <row><cell><c>aes_cbc256</c></cell><cell>32</cell><cell>16</cell><cell>16</cell></row>
+
+ <row><cell><c>aes_cfb8</c></cell> <cell>16, 24, 32</cell><cell>16</cell><cell>any</cell></row>
+
+ <row><cell><c>aes_ecb</c></cell><cell>16, 24, 32</cell><cell> </cell><cell>16</cell></row>
+
+ <row><cell><c>aes_ige256</c></cell><cell>16</cell><cell>32</cell><cell>16</cell></row>
+ <row><cell><c>blowfish_cbc</c></cell> <cell>4-56</cell> <cell>8</cell> <cell>8</cell></row>
+ <row><cell><c>blowfish_cfb64</c></cell> <cell>1-</cell> <cell>8</cell> <cell>any</cell></row>
+ <row><cell><c>blowfish_ecb</c></cell><cell>1-</cell><cell> </cell><cell>8</cell></row>
+ <row><cell><c>blowfish_ofb64</c></cell><cell>1-</cell><cell>8</cell><cell>any</cell></row>
+
+ <row><cell><c>des3_cbc</c><br/><i>(=DES EDE3 CBC)</i></cell><cell>[8,8,8]</cell><cell>8</cell><cell>8</cell></row>
+ <row><cell><c>des3_cfb</c><br/><i>(=DES EDE3 CFB)</i></cell><cell>[8,8,8]</cell><cell>8</cell><cell>any</cell></row>
+
+ <row><cell><c>des_cbc</c></cell><cell>8</cell><cell>8</cell> <cell>8</cell></row>
+ <row><cell><c>des_cfb</c></cell><cell>8</cell><cell>8</cell><cell>any</cell></row>
+ <row><cell><c>des_ecb</c></cell><cell>8</cell><cell> </cell><cell>8</cell></row>
+ <row><cell><c>des_ede3</c><br/><i>(=DES EDE3 CBC)</i></cell><cell>[8,8,8]</cell><cell>8</cell><cell>8</cell></row>
+ <row><cell><c>rc2_cbc</c></cell><cell>1-</cell><cell>8</cell><cell>8</cell></row>
+ <tcaption>Block cipher key lengths</tcaption>
+ </table>
+ </section>
+
+ <section>
+ <title>AEAD Ciphers</title>
+ <p>To be used in <seealso marker="crypto#block_encrypt-4">block_encrypt/4</seealso> and
+ <seealso marker="crypto#block_decrypt-4">block_decrypt/4</seealso>.
+ </p>
+ <p>To dynamically check availability, check that the name in the <i>Cipher and Mode</i> column is present in the
+ list with the <c>cipher</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+ <table>
+ <row><cell><strong>Cipher and Mode</strong></cell><cell><strong>Key length</strong><br/><strong>[bytes]</strong></cell><cell><strong>IV length</strong><br/><strong>[bytes]</strong></cell><cell><strong>AAD length</strong><br/><strong>[bytes]</strong></cell><cell><strong>Block size</strong><br/><strong>[bytes]</strong></cell><cell><strong>Supported with</strong><br/><strong>OpenSSL versions</strong></cell></row>
+ <row><cell><c>aes_gcm</c></cell> <cell>16</cell> <cell>16</cell> <cell>0-16</cell> <cell>any</cell><cell>1.0.1 -</cell></row>
+ <row><cell><c>chacha20_poly1305</c></cell><cell>32</cell> <cell>1-16</cell> <cell>any</cell> <cell>any</cell><cell>1.1.0 -</cell></row>
+ <tcaption>AEAD cipher key lengths</tcaption>
+ </table>
+ </section>
+
+ <section>
+ <title>Stream Ciphers</title>
+ <p>To be used in <seealso marker="crypto#stream_init-2">stream_init/2</seealso> and
+ <seealso marker="crypto#stream_init/3">stream_init/3</seealso>.
+ </p>
+ <p>To dynamically check availability, check that the name in the <i>Cipher and Mode</i> column is present in the
+ list with the <c>cipher</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+ <table>
+ <row><cell><strong>Cipher and Mode</strong></cell><cell><strong>Key length</strong><br/><strong>[bytes]</strong></cell><cell><strong>IV length</strong><br/><strong>[bytes]</strong></cell><cell><strong>Supported with</strong><br/><strong>OpenSSL versions</strong></cell></row>
+ <row><cell><c>aes_ctr</c></cell><cell>16, 24, 32</cell><cell>16</cell><cell>1.0.1 -</cell></row>
+ <row><cell><c>rc4</c></cell><cell>1-</cell><cell> </cell> <cell>all</cell></row>
+ <tcaption>Stream cipher key lengths</tcaption>
+ </table>
+ </section>
+ </section>
+
+ <section>
+ <title>Message Authentication Codes (MACs)</title>
+
+ <section>
+ <title>CMAC</title>
+ <p>To be used in <seealso marker="crypto#cmac-3">cmac/3</seealso> and
+ <seealso marker="crypto#cmac-3">cmac/4</seealso>.
+ </p>
+ <p>CMAC with the following ciphers are available with OpenSSL 1.0.1 or later if not disabled by configuration.
+ </p>
+
+ <p>To dynamically check availability, check that the name <c>cmac</c> is present in the
+ list with the <c>macs</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ Also check that the name in the <i>Cipher and Mode</i> column is present in the
+ list with the <c>cipher</c> tag in the return value.
+ </p>
+ <table>
+ <row><cell><strong>Cipher and Mode</strong></cell><cell><strong>Key length</strong><br/><strong>[bytes]</strong></cell><cell><strong>Max Mac Length</strong><br/><strong>[bytes]</strong></cell></row>
+ <row><cell><c>aes_cbc</c></cell> <cell>16, 24, 32</cell><cell>16</cell></row>
+ <row><cell><c>aes_cbc128</c></cell><cell>16</cell><cell>16</cell></row>
+ <row><cell><c>aes_cbc256</c></cell><cell>32</cell><cell>16</cell></row>
+
+ <row><cell><c>aes_cfb8</c></cell> <cell>16</cell><cell>1</cell></row>
+
+ <row><cell><c>blowfish_cbc</c></cell> <cell>4-56</cell> <cell>8</cell></row>
+ <row><cell><c>blowfish_cfb64</c></cell> <cell>1-</cell> <cell>1</cell></row>
+ <row><cell><c>blowfish_ecb</c></cell><cell>1-</cell> <cell>8</cell></row>
+ <row><cell><c>blowfish_ofb64</c></cell><cell>1-</cell> <cell>1</cell></row>
+
+ <row><cell><c>des3_cbc</c><br/><i>(=DES EDE3 CBC)</i></cell><cell>[8,8,8]</cell><cell>8</cell></row>
+ <row><cell><c>des3_cfb</c><br/><i>(=DES EDE3 CFB)</i></cell><cell>[8,8,8]</cell><cell>1</cell></row>
+
+ <row><cell><c>des_cbc</c></cell><cell>8</cell><cell>8</cell></row>
+
+ <row><cell><c>des_cfb</c></cell><cell>8</cell><cell>1</cell></row>
+ <row><cell><c>des_ecb</c></cell><cell>8</cell><cell>1</cell></row>
+ <row><cell><c>rc2_cbc</c></cell><cell>1-</cell><cell>8</cell></row>
+ <tcaption>CMAC cipher key lengths</tcaption>
+ </table>
+ </section>
+
+ <section>
+ <title>HMAC</title>
+ <p>Available in all OpenSSL compatible with Erlang CRYPTO if not disabled by configuration.
+ </p>
+ <p>To dynamically check availability, check that the name <c>hmac</c> is present in the
+ list with the <c>macs</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+ </section>
+
+ <section>
+ <title>POLY1305</title>
+ <p>POLY1305 is available with OpenSSL 1.1.1 or later if not disabled by configuration.
+ </p>
+ <p>To dynamically check availability, check that the name <c>poly1305</c> is present in the
+ list with the <c>macs</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+ </section>
+
+ </section>
+
+ <section>
+ <title>Hash</title>
+
+ <p>To dynamically check availability, check that the wanted name in the <i>Names</i> column is present in the
+ list with the <c>hashs</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+
+
+ <table>
+ <row><cell><strong>Type</strong></cell>
+ <cell><strong>Names</strong></cell>
+ <cell><strong>Supported with</strong><br/><strong>OpenSSL versions</strong></cell>
+ </row>
+ <row><cell>SHA1</cell><cell>sha</cell><cell>all</cell></row>
+ <row><cell>SHA2</cell><cell>sha224, sha256, sha384, sha512</cell><cell>all</cell></row>
+ <row><cell>SHA3</cell><cell>sha3_224, sha3_256, sha3_384, sha3_512</cell><cell>1.1.1 -</cell></row>
+ <row><cell>MD4</cell><cell>md4</cell><cell>all</cell></row>
+ <row><cell>MD5</cell><cell>md5</cell><cell>all</cell></row>
+ <row><cell>RIPEMD</cell><cell>ripemd160</cell><cell>all</cell></row>
+ <tcaption></tcaption>
+ </table>
+ </section>
+
+ <section>
+ <title>Public Key Cryptography</title>
+
+ <section>
+ <title>RSA</title>
+ <p>RSA is available with all OpenSSL versions compatible with Erlang CRYPTO if not disabled by configuration.
+ To dynamically check availability, check that the atom <c>rsa</c> is present in the
+ list with the <c>public_keys</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+
+ <table>
+ <row><cell><strong>Option</strong></cell> <cell><strong>sign/verify</strong></cell> <cell><strong>encrypt/decrypt</strong></cell> <cell><strong>Supported with</strong><br/><strong>OpenSSL versions</strong></cell> </row>
+ <row><cell>{rsa_mgf1_md,atom()}</cell> <cell>x</cell> <cell>x</cell> <cell>1.0.1</cell></row>
+ <row><cell>{rsa_oaep_label, binary()}</cell> <cell> </cell> <cell>x</cell> <cell></cell></row>
+ <row><cell>{rsa_oaep_md, atom()}</cell> <cell> </cell> <cell>x</cell> <cell></cell></row>
+ <row><cell>{rsa_padding,rsa_pkcs1_pss_padding}</cell> <cell>x</cell> <cell> </cell> <cell>1.0.0</cell></row>
+ <row><cell>{rsa_pss_saltlen, -2..}</cell> <cell>x</cell> <cell> </cell> <cell>1.0.0</cell></row>
+ <row><cell>{rsa_padding,rsa_no_padding}</cell> <cell>x</cell> <cell>x</cell> <cell></cell></row>
+ <row><cell>{rsa_padding,rsa_pkcs1_padding}</cell> <cell>x</cell> <cell>x</cell> <cell></cell></row>
+ <row><cell>{rsa_padding,rsa_sslv23_padding}</cell> <cell> </cell> <cell>x</cell> <cell></cell></row>
+ <row><cell>{rsa_padding,rsa_x931_padding}</cell> <cell>x</cell> <cell> </cell> <cell></cell></row>
+ <tcaption></tcaption>
+ </table>
+ </section>
+
+ <section>
+ <title>DSS</title>
+ <p>DSS is available with OpenSSL versions compatible with Erlang CRYPTO if not disabled by configuration.
+ To dynamically check availability, check that the atom <c>dss</c> is present in the
+ list with the <c>public_keys</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+ </section>
+
+ <section>
+ <title>ECDSA</title>
+ <p>ECDSA is available with OpenSSL 0.9.8o or later if not disabled by configuration.
+ To dynamically check availability, check that the atom <c>ecdsa</c> is present in the
+ list with the <c>public_keys</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ If the atom <c>ec_gf2m</c> characteristic two field curves are available.
+ </p>
+ <p>The actual supported named curves could be checked by examining the list with the
+ <c>curves</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+ </section>
+
+ <section>
+ <title>Diffie-Hellman</title>
+ <p>Diffie-Hellman computations are available with OpenSSL versions compatible with Erlang CRYPTO
+ if not disabled by configuration.
+ To dynamically check availability, check that the atom <c>dh</c> is present in the
+ list with the <c>public_keys</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+ </section>
+
+ <section>
+ <title>Elliptic Curve Diffie-Hellman</title>
+ <p>Elliptic Curve Diffie-Hellman is available with OpenSSL 0.9.8o or later if not disabled by configuration.
+ To dynamically check availability, check that the atom <c>ecdh</c> is present in the
+ list with the <c>public_keys</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+
+ <p>The Edward curves <c>x25519</c> and <c>x448</c> are supported with OpenSSL 1.1.1 or later
+ if not disabled by configuration.
+ </p>
+
+ <p>The actual supported named curves could be checked by examining the list with the
+ <c>curves</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+ </section>
+
+ </section>
+
+
+</chapter>
+
+
+
+
+
diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml
index af689d3ddb..d5f5009297 100644
--- a/lib/crypto/doc/src/crypto.xml
+++ b/lib/crypto/doc/src/crypto.xml
@@ -47,6 +47,12 @@
Block Cipher Modes - <url href="http://csrc.nist.gov/groups/ST/toolkit/BCM/index.html"> ECB, CBC, CFB, OFB, CTR and GCM </url></p>
</item>
<item>
+ <p>GCM: <url href="https://csrc.nist.gov/publications/detail/sp/800-38d/final">Dworkin, M.,
+ "Recommendation for Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC",
+ National Institute of Standards and Technology SP 800-38D, November 2007</url>.
+ </p>
+ </item>
+ <item>
<p><url href="http://www.ietf.org/rfc/rfc1321.txt"> RSA encryption RFC 1321 </url> </p>
</item>
<item>
@@ -56,189 +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>
+ <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>key_value() = integer() | binary() </code>
- <p>Always <c>binary()</c> when used as return value</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_public() = [key_value()] = [E, N] </code>
- <p> Where E is the public exponent and N is public modulus. </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>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>
+ <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_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_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>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="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_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_title>Digests</datatype_title>
+ <datatype>
+ <name name="sha1"/>
+ <name name="sha2"/>
+ <name name="sha3"/>
+ <desc>
+ </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>
+ <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>
- <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="rsa_digest_type"/>
+ <desc>
+ </desc>
+ </datatype>
- <code>dh_public() = key_value() </code>
+ <datatype>
+ <name name="dss_digest_type"/>
+ <desc>
+ </desc>
+ </datatype>
- <code>dh_private() = key_value() </code>
+ <datatype>
+ <name name="ecdsa_digest_type"/>
+ <desc>
+ </desc>
+ </datatype>
- <code>dh_params() = [key_value()] = [P, G] | [P, G, PrivateKeyBitLength]</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_public() = 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_private() = key_value() </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>ecdh_params() = ec_named_curve() | ec_explicit_curve()</code>
+ <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 </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_poly1305 | des_cbc |
- des_cfb | des3_cbc | des3_cfb | des_ede3 | rc2_cbc | rc4 </code>
- <code> mac_algorithms() = hmac | cmac</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>
@@ -248,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>
@@ -261,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>
@@ -271,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>
@@ -284,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>
@@ -304,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() | 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>
@@ -323,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() | 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>
@@ -410,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>.
@@ -425,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>
@@ -443,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
@@ -458,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
@@ -476,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>
@@ -493,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>
@@ -506,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>
@@ -524,20 +635,21 @@
</func>
<func>
- <name>info_fips() -> Status</name>
+ <name name="info_fips" arity="0"/>
<fsummary>Provides information about the FIPS operating status.</fsummary>
- <type>
- <v>Status = enabled | not_enabled | not_supported</v>
- </type>
<desc>
<p>Provides information about the FIPS operating status of
- crypto and the underlying OpenSSL library. If crypto was built
+ crypto and the underlying libcrypto library. If crypto was built
with FIPS support this can be either <c>enabled</c> (when
running in FIPS mode) or <c>not_enabled</c>. For other builds
- this value is always <c>not_supported</c>.</p>
+ this value is always <c>not_supported</c>.
+ </p>
+ <p>See <seealso marker="#enable_fips_mode-1">enable_fips_mode/1</seealso> about how to enable
+ FIPS mode.
+ </p>
<warning>
<p>In FIPS mode all non-FIPS compliant algorithms are
- disabled and throw exception <c>not_supported</c>. Check
+ disabled and raise exception <c>error:notsup</c>. Check
<seealso marker="#supports-0">supports</seealso> that in
FIPS mode returns the restricted list of available
algorithms.</p>
@@ -546,13 +658,23 @@
</func>
<func>
- <name>info_lib() -> [{Name,VerNum,VerStr}]</name>
+ <name name="enable_fips_mode" arity="1"/>
+ <fsummary>Change FIPS mode.</fsummary>
+ <desc>
+ <p>Enables (<c>Enable = true</c>) or disables (<c>Enable = false</c>) FIPS mode. Returns <c>true</c> if
+ the operation was successful or <c>false</c> otherwise.
+ </p>
+ <p>Note that to enable FIPS mode succesfully, OTP must be built with the configure option <c>--enable-fips</c>,
+ and the underlying libcrypto must also support FIPS.
+ </p>
+ <p>See also <seealso marker="#info_fips-0">info_fips/0</seealso>.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="info_lib" arity="0"/>
<fsummary>Provides information about the libraries used by crypto.</fsummary>
- <type>
- <v>Name = binary()</v>
- <v>VerNum = integer()</v>
- <v>VerStr = binary()</v>
- </type>
<desc>
<p>Provides the name and version of the libraries used by crypto.</p>
<p><c>Name</c> is the name of the library. <c>VerNum</c> is
@@ -565,52 +687,45 @@
<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 name="poly1305" arity="2"/>
+ <fsummary></fsummary>
+ <desc>
+ <p>Computes a POLY1305 message authentication code (<c>Mac</c>) from <c>Data</c> using
+ <c>Key</c> as the authentication key.</p>
+ </desc>
</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)
@@ -623,34 +738,8 @@
</func>
<func>
- <name>privkey_to_pubkey(Type, EnginePrivateKeyRef) -> PublicKey</name>
- <fsummary>Fetches a public key from an Engine stored private key.</fsummary>
- <type>
- <v>Type = rsa | dss</v>
- <v>EnginePrivateKeyRef = engine_key_ref()</v>
- <v>PublicKey = rsa_public() | dss_public()</v>
- </type>
- <desc>
- <p>Fetches the corresponding public key from a private key stored in an Engine.
- The key must be of the type indicated by the Type parameter.
- </p>
- </desc>
- </func>
-
- <func>
- <name>private_encrypt(Type, PlainText, PrivateKey, Padding) -> CipherText</name>
+ <name name="private_encrypt" arity="4"/>
<fsummary>Encrypts PlainText using the private Key.</fsummary>
- <type>
- <v>Type = rsa</v>
- <v>PlainText = binary()</v>
- <d> The size of the <c>PlainText</c> must be less
- than <c>byte_size(N)-11</c> if <c>rsa_pkcs1_padding</c> is
- used, and <c>byte_size(N)</c> if <c>rsa_no_padding</c> is
- used, where N is public modulus of the RSA key.</d>
- <v>PrivateKey = rsa_private() | engine_key_ref()</v>
- <v>Padding = rsa_pkcs1_padding | rsa_no_padding</v>
- <v>CipherText = binary()</v>
- </type>
<desc>
<p>Encrypts the <c>PlainText</c> using the <c>PrivateKey</c>
and returns the ciphertext. This is a low level signature operation
@@ -660,16 +749,10 @@
</p>
</desc>
</func>
+
<func>
- <name>public_decrypt(Type, CipherText, PublicKey, Padding) -> PlainText</name>
+ <name name="public_decrypt" arity="4"/>
<fsummary>Decrypts CipherText using the public Key.</fsummary>
- <type>
- <v>Type = rsa</v>
- <v>CipherText = binary()</v>
- <v>PublicKey = rsa_public() | engine_key_ref()</v>
- <v>Padding = rsa_pkcs1_padding | rsa_no_padding</v>
- <v>PlainText = binary()</v>
- </type>
<desc>
<p>Decrypts the <c>CipherText</c>, encrypted with
<seealso marker="#private_encrypt-4">private_encrypt/4</seealso>(or equivalent function)
@@ -682,19 +765,8 @@
</func>
<func>
- <name>public_encrypt(Type, PlainText, PublicKey, Padding) -> CipherText</name>
+ <name name="public_encrypt" arity="4"/>
<fsummary>Encrypts PlainText using the public Key.</fsummary>
- <type>
- <v>Type = rsa</v>
- <v>PlainText = binary()</v>
- <d> The size of the <c>PlainText</c> must be less
- than <c>byte_size(N)-11</c> if <c>rsa_pkcs1_padding</c> is
- used, and <c>byte_size(N)</c> if <c>rsa_no_padding</c> is
- used, where N is public modulus of the RSA key.</d>
- <v>PublicKey = rsa_public() | engine_key_ref()</v>
- <v>Padding = rsa_pkcs1_padding | rsa_pkcs1_oaep_padding | rsa_no_padding</v>
- <v>CipherText = binary()</v>
- </type>
<desc>
<p>Encrypts the <c>PlainText</c> (message digest) using the <c>PublicKey</c>
and returns the <c>CipherText</c>. This is a low level signature operation
@@ -705,18 +777,15 @@
</func>
<func>
- <name>rand_seed(Seed) -> ok</name>
+ <name name="rand_seed" arity="1"/>
<fsummary>Set the seed for random bytes generation</fsummary>
- <type>
- <v>Seed = binary()</v>
- </type>
<desc>
<p>Set the seed for PRNG to the given binary. This calls the
RAND_seed function from openssl. Only use this if the system
you are running on does not have enough "randomness" built in.
Normally this is when
<seealso marker="#strong_rand_bytes/1">strong_rand_bytes/1</seealso>
- throws <c>low_entropy</c></p>
+ raises <c>error:low_entropy</c></p>
</desc>
</func>
@@ -734,36 +803,15 @@
</func>
<func>
- <name>sign(Algorithm, DigestType, Msg, Key) -> binary()</name>
- <name>sign(Algorithm, DigestType, Msg, Key, Options) -> binary()</name>
- <fsummary> Create digital signature.</fsummary>
- <type>
- <v>Algorithm = rsa | dss | ecdsa </v>
- <v>Msg = binary() | {digest,binary()}</v>
- <d>The msg is either the binary "cleartext" data to be
- signed or it is the hashed value of "cleartext" i.e. the
- digest (plaintext).</d>
- <v>DigestType = rsa_digest_type() | dss_digest_type() | ecdsa_digest_type()</v>
- <v>Key = rsa_private() | dss_private() | [ecdh_private(),ecdh_params()] | engine_key_ref()</v>
- <v>Options = sign_options()</v>
- </type>
- <desc>
- <p>Creates a digital signature.</p>
- <p>Algorithm <c>dss</c> can only be used together with digest type
- <c>sha</c>.</p>
- <p>See also <seealso marker="public_key:public_key#sign-3">public_key:sign/3</seealso>.</p>
- </desc>
- </func>
-
- <func>
- <name>start() -> ok</name>
+ <name name="start" arity="0"/>
<fsummary> Equivalent to application:start(crypto). </fsummary>
<desc>
<p> Equivalent to application:start(crypto).</p>
</desc>
</func>
+
<func>
- <name>stop() -> ok</name>
+ <name name="stop" arity="0"/>
<fsummary> Equivalent to application:stop(crypto).</fsummary>
<desc>
<p> Equivalent to application:stop(crypto).</p>
@@ -771,23 +819,20 @@
</func>
<func>
- <name>strong_rand_bytes(N) -> binary()</name>
+ <name name="strong_rand_bytes" arity="1"/>
<fsummary>Generate a binary of random bytes</fsummary>
- <type>
- <v>N = integer()</v>
- </type>
<desc>
<p>Generates N bytes randomly uniform 0..255, and returns the
result in a binary. Uses a cryptographically secure prng seeded and
periodically mixed with operating system provided entropy. By default
this is the <c>RAND_bytes</c> method from OpenSSL.</p>
- <p>May throw exception <c>low_entropy</c> in case the random generator
+ <p>May raise exception <c>error:low_entropy</c> in case the random generator
failed due to lack of secure "randomness".</p>
</desc>
</func>
<func>
- <name>rand_seed() -> rand:state()</name>
+ <name name="rand_seed" arity="0"/>
<fsummary>Strong random number generation plugin state</fsummary>
<desc>
<p>
@@ -803,7 +848,7 @@
<p>
When using the state object from this function the
<seealso marker="stdlib:rand">rand</seealso> functions using it
- may throw exception <c>low_entropy</c> in case the random generator
+ may raise exception <c>error:low_entropy</c> in case the random generator
failed due to lack of secure "randomness".
</p>
<p><em>Example</em></p>
@@ -815,7 +860,7 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</func>
<func>
- <name>rand_seed_s() -> rand:state()</name>
+ <name name="rand_seed_s" arity="0"/>
<fsummary>Strong random number generation plugin state</fsummary>
<desc>
<p>
@@ -829,7 +874,7 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
<p>
When using the state object from this function the
<seealso marker="stdlib:rand">rand</seealso> functions using it
- may throw exception <c>low_entropy</c> in case the random generator
+ may raise exception <c>error:low_entropy</c> in case the random generator
failed due to lack of secure "randomness".
</p>
<note>
@@ -868,7 +913,7 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
<p>
When using the state object from this function the
<seealso marker="stdlib:rand">rand</seealso> functions using it
- may throw exception <c>low_entropy</c> in case the random generator
+ may raise exception <c>error:low_entropy</c> in case the random generator
failed due to lack of secure "randomness".
</p>
<p>
@@ -913,7 +958,7 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
<p>
When using the state object from this function the
<seealso marker="stdlib:rand">rand</seealso> functions using it
- may throw exception <c>low_entropy</c> in case the random generator
+ may raise exception <c>error:low_entropy</c> in case the random generator
failed due to lack of secure "randomness".
</p>
<p>
@@ -944,45 +989,36 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</func>
<func>
- <name>stream_init(Type, Key) -> State</name>
+ <name name="stream_init" arity="2"/>
<fsummary></fsummary>
- <type>
- <v>Type = rc4 </v>
- <v>State = opaque() </v>
- <v>Key = iodata()</v>
- </type>
<desc>
<p>Initializes the state for use in RC4 stream encryption
<seealso marker="#stream_encrypt-2">stream_encrypt</seealso> and
<seealso marker="#stream_decrypt-2">stream_decrypt</seealso></p>
+ <p>For keylengths see the
+ <seealso marker="crypto:algorithm_details#stream-ciphers">User's Guide</seealso>.
+ </p>
</desc>
</func>
<func>
- <name>stream_init(Type, Key, IVec) -> State</name>
+ <name name="stream_init" arity="3"/>
<fsummary></fsummary>
- <type>
- <v>Type = aes_ctr </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
@@ -992,12 +1028,8 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</func>
<func>
- <name>stream_decrypt(State, CipherText) -> { NewState, PlainText }</name>
+ <name name="stream_decrypt" arity="2"/>
<fsummary></fsummary>
- <type>
- <v>CipherText = iodata()</v>
- <v>PlainText = binary()</v>
- </type>
<desc>
<p>Decrypts <c>CipherText</c> according to the stream cipher <c>Type</c> specified in stream_init/3.
<c>PlainText</c> can be any number of bytes. The initial <c>State</c> is created using
@@ -1007,60 +1039,54 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</func>
<func>
- <name>supports() -> AlgorithmList </name>
+ <name name="supports" arity="0"/>
<fsummary>Provide a list of available crypto algorithms.</fsummary>
- <type>
- <v> AlgorithmList = [{hashs, [hash_algorithms()]},
- {ciphers, [cipher_algorithms()]},
- {public_keys, [public_key_algorithms()]},
- {macs, [mac_algorithms()]}]
- </v>
- </type>
<desc>
<p> Can be used to determine which crypto algorithms that are supported
- by the underlying OpenSSL library</p>
+ by the underlying libcrypto library</p>
</desc>
</func>
<func>
- <name>ec_curves() -> EllipticCurveList </name>
+ <name name="ec_curves" arity="0"/>
<fsummary>Provide a list of available named elliptic curves.</fsummary>
- <type>
- <v>EllipticCurveList = [ec_named_curve()]</v>
- </type>
<desc>
<p>Can be used to determine which named elliptic curves are supported.</p>
</desc>
</func>
<func>
- <name>ec_curve(NamedCurve) -> EllipticCurve </name>
+ <name name="ec_curve" arity="1"/>
<fsummary>Get the defining parameters of a elliptic curve.</fsummary>
- <type>
- <v>NamedCurve = ec_named_curve()</v>
- <v>EllipticCurve = ec_explicit_curve()</v>
- </type>
<desc>
<p>Return the defining parameters of a elliptic curve.</p>
</desc>
</func>
- <func>
- <name>verify(Algorithm, DigestType, Msg, Signature, Key) -> boolean()</name>
- <name>verify(Algorithm, DigestType, Msg, Signature, Key, Options) -> boolean()</name>
+ <func>
+ <name name="sign" arity="4"/>
+ <name name="sign" arity="5"/>
+ <fsummary> Create digital signature.</fsummary>
+ <desc>
+ <p>Creates a digital signature.</p>
+ <p>The msg is either the binary "cleartext" data to be
+ signed or it is the hashed value of "cleartext" i.e. the
+ digest (plaintext).</p>
+ <p>Algorithm <c>dss</c> can only be used together with digest type
+ <c>sha</c>.</p>
+ <p>See also <seealso marker="public_key:public_key#sign-3">public_key:sign/3</seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="verify" arity="5"/>
+ <name name="verify" arity="6"/>
<fsummary>Verifies a digital signature.</fsummary>
- <type>
- <v> Algorithm = rsa | dss | ecdsa </v>
- <v>Msg = binary() | {digest,binary()}</v>
- <d>The msg is either the binary "cleartext" data
- or it is the hashed value of "cleartext" i.e. the digest (plaintext).</d>
- <v>DigestType = rsa_digest_type() | dss_digest_type() | ecdsa_digest_type()</v>
- <v>Signature = binary()</v>
- <v>Key = rsa_public() | dss_public() | [ecdh_public(),ecdh_params()] | engine_key_ref()</v>
- <v>Options = sign_options()</v>
- </type>
<desc>
<p>Verifies a digital signature</p>
+ <p>The msg is either the binary "cleartext" data to be
+ signed or it is the hashed value of "cleartext" i.e. the
+ digest (plaintext).</p>
<p>Algorithm <c>dss</c> can only be used together with digest type
<c>sha</c>.</p>
@@ -1070,17 +1096,24 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
<!-- Engine functions -->
<func>
- <name>engine_get_all_methods() -> Result</name>
+ <name name="privkey_to_pubkey" arity="2"/>
+ <fsummary>Fetches a public key from an Engine stored private key.</fsummary>
+ <desc>
+ <p>Fetches the corresponding public key from a private key stored in an Engine.
+ The key must be of the type indicated by the Type parameter.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="engine_get_all_methods" arity="0"/>
<fsummary>Return list of all possible engine methods</fsummary>
- <type>
- <v>Result = [EngineMethod::atom()]</v>
- </type>
<desc>
<p>
Returns a list of all possible engine methods.
</p>
<p>
- May throw exception notsup in case there is
+ May raise exception <c>error:notsup</c> in case there is
no engine support in the underlying OpenSSL implementation.
</p>
<p>
@@ -1091,13 +1124,8 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</func>
<func>
- <name>engine_load(EngineId, PreCmds, PostCmds) -> Result</name>
+ <name name="engine_load" arity="3"/>
<fsummary>Dynamical load an encryption engine</fsummary>
- <type>
- <v>EngineId = unicode:chardata()</v>
- <v>PreCmds, PostCmds = [{unicode:chardata(), unicode:chardata()}]</v>
- <v>Result = {ok, Engine::engine_ref()} | {error, Reason::term()}</v>
- </type>
<desc>
<p>
Loads the OpenSSL engine given by <c>EngineId</c> if it is available and then returns ok and
@@ -1106,8 +1134,8 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
returned if the engine can't be loaded.
</p>
<p>
- The function throws a badarg if the parameters are in wrong format.
- It may also throw the exception notsup in case there is
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
no engine support in the underlying OpenSSL implementation.
</p>
<p>
@@ -1118,22 +1146,16 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</func>
<func>
- <name>engine_load(EngineId, PreCmds, PostCmds, EngineMethods) -> Result</name>
+ <name name="engine_load" arity="4"/>
<fsummary>Dynamical load an encryption engine</fsummary>
- <type>
- <v>EngineId = unicode:chardata()</v>
- <v>PreCmds, PostCmds = [{unicode:chardata(), unicode:chardata()}]</v>
- <v>EngineMethods = [engine_method_type()]</v>
- <v>Result = {ok, Engine::engine_ref()} | {error, Reason::term()}</v>
- </type>
<desc>
<p>
Loads the OpenSSL engine given by <c>EngineId</c> if it is available and then returns ok and
an engine handle. An error tuple is returned if the engine can't be loaded.
</p>
<p>
- The function throws a badarg if the parameters are in wrong format.
- It may also throw the exception notsup in case there is
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
no engine support in the underlying OpenSSL implementation.
</p>
<p>
@@ -1144,20 +1166,16 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</func>
<func>
- <name>engine_unload(Engine) -> Result</name>
+ <name name="engine_unload" arity="1"/>
<fsummary>Dynamical load an encryption engine</fsummary>
- <type>
- <v>Engine = engine_ref()</v>
- <v>Result = ok | {error, Reason::term()}</v>
- </type>
<desc>
<p>
Unloads the OpenSSL engine given by <c>Engine</c>.
An error tuple is returned if the engine can't be unloaded.
</p>
<p>
- The function throws a badarg if the parameter is in wrong format.
- It may also throw the exception notsup in case there is
+ The function raises a <c>error:badarg</c> if the parameter is in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
no engine support in the underlying OpenSSL implementation.
</p>
<p>
@@ -1168,20 +1186,16 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</func>
<func>
- <name>engine_by_id(EngineId) -> Result</name>
+ <name name="engine_by_id" arity="1"/>
<fsummary>Get a reference to an already loaded engine</fsummary>
- <type>
- <v>EngineID = unicode:chardata()engine_ref()</v>
- <v>Result = {ok, Engine::engine_ref()} | {error, Reason::term()}</v>
- </type>
<desc>
<p>
Get a reference to an already loaded engine with <c>EngineId</c>.
An error tuple is returned if the engine can't be unloaded.
</p>
<p>
- The function throws a badarg if the parameter is in wrong format.
- It may also throw the exception notsup in case there is
+ The function raises a <c>error:badarg</c> if the parameter is in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
no engine support in the underlying OpenSSL implementation.
</p>
<p>
@@ -1192,14 +1206,8 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</func>
<func>
- <name>engine_ctrl_cmd_string(Engine, CmdName, CmdArg) -> Result</name>
+ <name name="engine_ctrl_cmd_string" arity="3"/>
<fsummary>Sends ctrl commands to an OpenSSL engine</fsummary>
- <type>
- <v>Engine = engine_ref()</v>
- <v>CmdName = unicode:chardata()</v>
- <v>CmdArg = unicode:chardata()</v>
- <v>Result = ok | {error, Reason::term()}</v>
- </type>
<desc>
<p>
Sends ctrl commands to the OpenSSL engine given by <c>Engine</c>.
@@ -1207,23 +1215,16 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
<c>Optional</c> set to <c>false</c>.
</p>
<p>
- The function throws a badarg if the parameters are in wrong format.
- It may also throw the exception notsup in case there is
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
no engine support in the underlying OpenSSL implementation.
</p>
</desc>
</func>
<func>
- <name>engine_ctrl_cmd_string(Engine, CmdName, CmdArg, Optional) -> Result</name>
+ <name name="engine_ctrl_cmd_string" arity="4"/>
<fsummary>Sends ctrl commands to an OpenSSL engine</fsummary>
- <type>
- <v>Engine = engine_ref()</v>
- <v>CmdName = unicode:chardata()</v>
- <v>CmdArg = unicode:chardata()</v>
- <v>Optional = boolean()</v>
- <v>Result = ok | {error, Reason::term()}</v>
- </type>
<desc>
<p>
Sends ctrl commands to the OpenSSL engine given by <c>Engine</c>.
@@ -1235,91 +1236,72 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
<c>false</c>.
</p>
<p>
- The function throws a badarg if the parameters are in wrong format.
- It may also throw the exception notsup in case there is
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
no engine support in the underlying OpenSSL implementation.
</p>
</desc>
</func>
<func>
- <name>engine_add(Engine) -> Result</name>
+ <name name="engine_add" arity="1"/>
<fsummary>Add engine to OpenSSL internal list</fsummary>
- <type>
- <v>Engine = engine_ref()</v>
- <v>Result = ok | {error, Reason::term()}</v>
- </type>
<desc>
<p>Add the engine to OpenSSL's internal list.</p>
<p>
- The function throws a badarg if the parameters are in wrong format.
- It may also throw the exception notsup in case there is
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
no engine support in the underlying OpenSSL implementation.
</p>
</desc>
</func>
<func>
- <name>engine_remove(Engine) -> Result</name>
+ <name name="engine_remove" arity="1"/>
<fsummary>Remove engine to OpenSSL internal list</fsummary>
- <type>
- <v>Engine = engine_ref()</v>
- <v>Result = ok | {error, Reason::term()}</v>
- </type>
<desc>
<p>Remove the engine from OpenSSL's internal list.</p>
<p>
- The function throws a badarg if the parameters are in wrong format.
- It may also throw the exception notsup in case there is
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
no engine support in the underlying OpenSSL implementation.
</p>
</desc>
</func>
<func>
- <name>engine_get_id(Engine) -> EngineId</name>
+ <name name="engine_get_id" arity="1"/>
<fsummary>Fetch engine ID</fsummary>
- <type>
- <v>Engine = engine_ref()</v>
- <v>EngineId = unicode:chardata()</v>
- </type>
<desc>
<p>Return the ID for the engine, or an empty binary if there is no id set.</p>
<p>
- The function throws a badarg if the parameters are in wrong format.
- It may also throw the exception notsup in case there is
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
no engine support in the underlying OpenSSL implementation.
</p>
</desc>
</func>
<func>
- <name>engine_get_name(Engine) -> EngineName</name>
+ <name name="engine_get_name" arity="1"/>
<fsummary>Fetch engine name</fsummary>
- <type>
- <v>Engine = engine_ref()</v>
- <v>EngineName = unicode:chardata()</v>
- </type>
<desc>
<p>Return the name (eg a description) for the engine, or an empty binary if there is no name set.</p>
<p>
- The function throws a badarg if the parameters are in wrong format.
- It may also throw the exception notsup in case there is
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
no engine support in the underlying OpenSSL implementation.
</p>
</desc>
</func>
<func>
- <name>engine_list() -> Result</name>
+ <name name="engine_list" arity="0"/>
<fsummary>List the known engine ids</fsummary>
- <type>
- <v>Result = [EngineId::unicode:chardata()]</v>
- </type>
<desc>
<p>List the id's of all engines in OpenSSL's internal list.</p>
<p>
- It may also throw the exception notsup in case there is
+ It may also raise the exception <c>error:notsup</c> in case there is
no engine support in the underlying OpenSSL implementation.
</p>
<p>
@@ -1327,20 +1309,15 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
in the User's Guide.
</p>
<p>
- May throw exception notsup in case engine functionality is not supported by the underlying
+ May raise exception <c>error:notsup</c> in case engine functionality is not supported by the underlying
OpenSSL implementation.
</p>
</desc>
</func>
<func>
- <name>ensure_engine_loaded(EngineId, LibPath) -> Result</name>
+ <name name="ensure_engine_loaded" arity="2"/>
<fsummary>Ensure encryption engine just loaded once</fsummary>
- <type>
- <v>EngineId = unicode:chardata()</v>
- <v>LibPath = unicode:chardata()</v>
- <v>Result = {ok, Engine::engine_ref()} | {error, Reason::term()}</v>
- </type>
<desc>
<p>
Loads the OpenSSL engine given by <c>EngineId</c> and the path to the dynamic library
@@ -1349,8 +1326,8 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
returned if the engine can't be loaded.
</p>
<p>
- The function throws a badarg if the parameters are in wrong format.
- It may also throw the exception notsup in case there is
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
no engine support in the underlying OpenSSL implementation.
</p>
<p>
@@ -1361,14 +1338,8 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</func>
<func>
- <name>ensure_engine_loaded(EngineId, LibPath, EngineMethods) -> Result</name>
+ <name name="ensure_engine_loaded" arity="3"/>
<fsummary>Ensure encryption engine just loaded once</fsummary>
- <type>
- <v>EngineId = unicode:chardata()</v>
- <v>LibPath = unicode:chardata()</v>
- <v>EngineMethods = [engine_method_type()]</v>
- <v>Result = {ok, Engine::engine_ref()} | {error, Reason::term()}</v>
- </type>
<desc>
<p>
Loads the OpenSSL engine given by <c>EngineId</c> and the path to the dynamic library
@@ -1378,8 +1349,8 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
An error tuple is returned if the engine can't be loaded.
</p>
<p>
- The function throws a badarg if the parameters are in wrong format.
- It may also throw the exception notsup in case there is
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
no engine support in the underlying OpenSSL implementation.
</p>
<p>
@@ -1390,12 +1361,8 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</func>
<func>
- <name>ensure_engine_unloaded(Engine) -> Result</name>
+ <name name="ensure_engine_unloaded" arity="1"/>
<fsummary>Unload an engine loaded with the ensure function</fsummary>
- <type>
- <v>Engine = engine_ref()</v>
- <v>Result = ok | {error, Reason::term()}</v>
- </type>
<desc>
<p>
Unloads an engine loaded with the <c>ensure_engine_loaded</c> function.
@@ -1405,8 +1372,8 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
returned if the engine can't be unloaded.
</p>
<p>
- The function throws a badarg if the parameters are in wrong format.
- It may also throw the exception notsup in case there is
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
no engine support in the underlying OpenSSL implementation.
</p>
<p>
@@ -1417,13 +1384,8 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</func>
<func>
- <name>ensure_engine_unloaded(Engine, EngineMethods) -> Result</name>
+ <name name="ensure_engine_unloaded" arity="2"/>
<fsummary>Unload an engine loaded with the ensure function</fsummary>
- <type>
- <v>Engine = engine_ref()</v>
- <v>EngineMethods = [engine_method_type()]</v>
- <v>Result = ok | {error, Reason::term()}</v>
- </type>
<desc>
<p>
Unloads an engine loaded with the <c>ensure_engine_loaded</c> function.
@@ -1431,8 +1393,8 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
An error tuple is returned if the engine can't be unloaded.
</p>
<p>
- The function throws a badarg if the parameters are in wrong format.
- It may also throw the exception notsup in case there is
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
no engine support in the underlying OpenSSL implementation.
</p>
<p>
@@ -1444,75 +1406,5 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</funcs>
- <!-- Maybe put this in the users guide -->
- <!-- <section> -->
- <!-- <title>DES in CBC mode</title> -->
- <!-- <p>The Data Encryption Standard (DES) defines an algorithm for -->
- <!-- encrypting and decrypting an 8 byte quantity using an 8 byte key -->
- <!-- (actually only 56 bits of the key is used). -->
- <!-- </p> -->
- <!-- <p>When it comes to encrypting and decrypting blocks that are -->
- <!-- multiples of 8 bytes various modes are defined (NIST SP -->
- <!-- 800-38A). One of those modes is the Cipher Block Chaining (CBC) -->
- <!-- mode, where the encryption of an 8 byte segment depend not only -->
- <!-- of the contents of the segment itself, but also on the result of -->
- <!-- encrypting the previous segment: the encryption of the previous -->
- <!-- segment becomes the initializing vector of the encryption of the -->
- <!-- current segment. -->
- <!-- </p> -->
- <!-- <p>Thus the encryption of every segment depends on the encryption -->
- <!-- key (which is secret) and the encryption of the previous -->
- <!-- segment, except the first segment which has to be provided with -->
- <!-- an initial initializing vector. That vector could be chosen at -->
- <!-- random, or be a counter of some kind. It does not have to be -->
- <!-- secret. -->
- <!-- </p> -->
- <!-- <p>The following example is drawn from the old FIPS 81 standard -->
- <!-- (replaced by NIST SP 800-38A), where both the plain text and the -->
- <!-- resulting cipher text is settled. The following code fragment -->
- <!-- returns `true'. -->
- <!-- </p> -->
- <!-- <pre><![CDATA[ -->
-
- <!-- Key = <<16#01,16#23,16#45,16#67,16#89,16#ab,16#cd,16#ef>>, -->
- <!-- IVec = <<16#12,16#34,16#56,16#78,16#90,16#ab,16#cd,16#ef>>, -->
- <!-- P = "Now is the time for all ", -->
- <!-- C = crypto:des_cbc_encrypt(Key, IVec, P), -->
- <!-- % Which is the same as -->
- <!-- P1 = "Now is t", P2 = "he time ", P3 = "for all ", -->
- <!-- C1 = crypto:des_cbc_encrypt(Key, IVec, P1), -->
- <!-- C2 = crypto:des_cbc_encrypt(Key, C1, P2), -->
- <!-- C3 = crypto:des_cbc_encrypt(Key, C2, P3), -->
-
- <!-- C = <<C1/binary, C2/binary, C3/binary>>, -->
- <!-- C = <<16#e5,16#c7,16#cd,16#de,16#87,16#2b,16#f2,16#7c, -->
- <!-- 16#43,16#e9,16#34,16#00,16#8c,16#38,16#9c,16#0f, -->
- <!-- 16#68,16#37,16#88,16#49,16#9a,16#7c,16#05,16#f6>>, -->
- <!-- <<"Now is the time for all ">> == -->
- <!-- crypto:des_cbc_decrypt(Key, IVec, C). -->
- <!-- ]]></pre> -->
- <!-- <p>The following is true for the DES CBC mode. For all -->
- <!-- decompositions <c>P1 ++ P2 = P</c> of a plain text message -->
- <!-- <c>P</c> (where the length of all quantities are multiples of 8 -->
- <!-- bytes), the encryption <c>C</c> of <c>P</c> is equal to <c>C1 ++ -->
- <!-- C2</c>, where <c>C1</c> is obtained by encrypting <c>P1</c> with -->
- <!-- <c>Key</c> and the initializing vector <c>IVec</c>, and where -->
- <!-- <c>C2</c> is obtained by encrypting <c>P2</c> with <c>Key</c> -->
- <!-- and the initializing vector <c>last8(C1)</c>, -->
- <!-- where <c>last(Binary)</c> denotes the last 8 bytes of the -->
- <!-- binary <c>Binary</c>. -->
- <!-- </p> -->
- <!-- <p>Similarly, for all decompositions <c>C1 ++ C2 = C</c> of a -->
- <!-- cipher text message <c>C</c> (where the length of all quantities -->
- <!-- are multiples of 8 bytes), the decryption <c>P</c> of <c>C</c> -->
- <!-- is equal to <c>P1 ++ P2</c>, where <c>P1</c> is obtained by -->
- <!-- decrypting <c>C1</c> with <c>Key</c> and the initializing vector -->
- <!-- <c>IVec</c>, and where <c>P2</c> is obtained by decrypting -->
- <!-- <c>C2</c> with <c>Key</c> and the initializing vector -->
- <!-- <c>last8(C1)</c>, where <c>last8(Binary)</c> is as above. -->
- <!-- </p> -->
- <!-- <p>For DES3 (which uses three 64 bit keys) the situation is the -->
- <!-- same. -->
- <!-- </p> -->
- <!-- </section> -->
+
</erlref>
diff --git a/lib/crypto/doc/src/engine_keys.xml b/lib/crypto/doc/src/engine_keys.xml
index 38714fed8a..4f7b0243fb 100644
--- a/lib/crypto/doc/src/engine_keys.xml
+++ b/lib/crypto/doc/src/engine_keys.xml
@@ -62,7 +62,7 @@
on the Engine loaded
</item>
<item>an Erlang map is constructed with the Engine reference, the key reference and possibly a key passphrase if
- needed by the Engine. See the <seealso marker="crypto:crypto#engine_key_ref_type">Reference Manual</seealso> for
+ needed by the Engine. See the <seealso marker="crypto:crypto#type-engine_key_ref">Reference Manual</seealso> for
details of the map.
</item>
</list>
diff --git a/lib/crypto/doc/src/notes.xml b/lib/crypto/doc/src/notes.xml
index 5e0851f6b8..9207d09821 100644
--- a/lib/crypto/doc/src/notes.xml
+++ b/lib/crypto/doc/src/notes.xml
@@ -31,6 +31,37 @@
</header>
<p>This document describes the changes made to the Crypto application.</p>
+<section><title>Crypto 4.3.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Update the crypto engine functions to handle multiple
+ loads of an engine. </p> <p><c>engine_load/3/4</c> is
+ updated so it doesn't add the engine ID to OpenSSLs
+ internal list of engines which makes it possible to run
+ the engine_load more than once if it doesn't contain
+ global data.</p> <p>Added <c>ensure_engine_loaded/2/3</c>
+ which guarantees that the engine just is loaded once and
+ the following calls just returns a reference to it. This
+ is done by add the ID to the internal OpenSSL list and
+ check if it is already registered when the function is
+ called.</p> <p>Added <c>ensure_engine_unloaded/1/2</c> to
+ unload engines loaded with ensure_engine_loaded.</p>
+ <p>Then some more utility functions are added.</p>
+ <p><c>engine_add/1</c>, adds the engine to OpenSSL
+ internal list</p> <p><c>engine_remove/1</c>, remove the
+ engine from OpenSSL internal list</p>
+ <p><c>engine_get_id/1</c>, fetch the engines id</p>
+ <p><c>engine_get_name/1</c>, fetch the engine name</p>
+ <p>
+ Own Id: OTP-15233</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Crypto 4.3.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/crypto/doc/src/specs.xml b/lib/crypto/doc/src/specs.xml
new file mode 100644
index 0000000000..66c79a906b
--- /dev/null
+++ b/lib/crypto/doc/src/specs.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<specs xmlns:xi="http://www.w3.org/2001/XInclude">
+ <xi:include href="../specs/specs_crypto.xml"/>
+</specs>
diff --git a/lib/crypto/doc/src/usersguide.xml b/lib/crypto/doc/src/usersguide.xml
index 0124121433..2dfc966609 100644
--- a/lib/crypto/doc/src/usersguide.xml
+++ b/lib/crypto/doc/src/usersguide.xml
@@ -50,4 +50,5 @@
<xi:include href="fips.xml"/>
<xi:include href="engine_load.xml"/>
<xi:include href="engine_keys.xml"/>
+ <xi:include href="algorithm_details.xml"/>
</part>
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index c788e890a8..c64586897e 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -29,6 +29,7 @@
-export([generate_key/2, generate_key/3, compute_key/4]).
-export([hmac/3, hmac/4, hmac_init/2, hmac_update/2, hmac_final/1, hmac_final_n/2]).
-export([cmac/3, cmac/4]).
+-export([poly1305/2]).
-export([exor/2, strong_rand_bytes/1, mod_pow/3]).
-export([rand_seed/0, rand_seed_alg/1]).
-export([rand_seed_s/0, rand_seed_alg_s/1]).
@@ -65,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]).
@@ -82,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).
@@ -107,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},
@@ -124,90 +337,163 @@ supports()->
{curves, Curves}
].
+-spec info_lib() -> [{Name,VerNum,VerStr}] when Name :: binary(),
+ VerNum :: integer(),
+ VerStr :: binary() .
info_lib() -> ?nif_stub.
-spec info_fips() -> not_supported | not_enabled | enabled.
info_fips() -> ?nif_stub.
--spec enable_fips_mode(boolean()) -> boolean().
-
+-spec enable_fips_mode(Enable) -> Result when Enable :: boolean(),
+ Result :: boolean().
enable_fips_mode(_) -> ?nif_stub.
--spec hash(_, iodata()) -> binary().
+%%%================================================================
+%%%
+%%% Hashing
+%%%
+%%%================================================================
-hash(Hash, Data0) ->
- Data = iolist_to_binary(Data0),
- MaxBytes = max_bytes(),
- hash(Hash, Data, erlang:byte_size(Data), MaxBytes).
+-define(HASH_HASH_ALGORITHM, sha1() | sha2() | sha3() | ripemd160 | compatibility_only_hash() ).
--spec hash_init('md5'|'md4'|'ripemd160'|
- 'sha'|'sha224'|'sha256'|'sha384'|'sha512'|
- 'sha3_224' | 'sha3_256' | 'sha3_384' | 'sha3_512') -> any().
+-spec hash(Type, Data) -> Digest when Type :: ?HASH_HASH_ALGORITHM,
+ Data :: iodata(),
+ Digest :: binary().
+hash(Type, Data) ->
+ Data1 = iolist_to_binary(Data),
+ MaxBytes = max_bytes(),
+ hash(Type, Data1, erlang:byte_size(Data1), MaxBytes).
-hash_init(Hash) ->
- notsup_to_error(hash_init_nif(Hash)).
+-opaque hash_state() :: reference().
--spec hash_update(_, iodata()) -> any().
+-spec hash_init(Type) -> State when Type :: ?HASH_HASH_ALGORITHM,
+ State :: hash_state().
+hash_init(Type) ->
+ notsup_to_error(hash_init_nif(Type)).
-hash_update(State, Data0) ->
- Data = iolist_to_binary(Data0),
+-spec hash_update(State, Data) -> NewState when State :: hash_state(),
+ NewState :: hash_state(),
+ Data :: iodata() .
+hash_update(Context, Data) ->
+ Data1 = iolist_to_binary(Data),
MaxBytes = max_bytes(),
- hash_update(State, Data, erlang:byte_size(Data), MaxBytes).
+ hash_update(Context, Data1, erlang:byte_size(Data1), MaxBytes).
--spec hash_final(_) -> binary().
+-spec hash_final(State) -> Digest when State :: hash_state(),
+ Digest :: binary().
+hash_final(Context) ->
+ notsup_to_error(hash_final_nif(Context)).
-hash_final(State) ->
- notsup_to_error(hash_final_nif(State)).
+%%%================================================================
+%%%
+%%% MACs (Message Authentication Codes)
+%%%
+%%%================================================================
+%%%---- HMAC
--spec hmac(_, iodata(), iodata()) -> binary().
--spec hmac(_, iodata(), iodata(), integer()) -> binary().
--spec hmac_init(atom(), iodata()) -> binary().
--spec hmac_update(binary(), iodata()) -> binary().
--spec hmac_final(binary()) -> binary().
--spec hmac_final_n(binary(), integer()) -> binary().
+-define(HMAC_HASH_ALGORITHM, sha1() | sha2() | sha3() | compatibility_only_hash()).
-hmac(Type, Key, Data0) ->
- Data = iolist_to_binary(Data0),
- hmac(Type, Key, Data, undefined, erlang:byte_size(Data), max_bytes()).
-hmac(Type, Key, Data0, MacSize) ->
- Data = iolist_to_binary(Data0),
- hmac(Type, Key, Data, MacSize, erlang:byte_size(Data), max_bytes()).
+%%%---- hmac/3,4
+
+-spec hmac(Type, Key, Data) ->
+ Mac when Type :: ?HMAC_HASH_ALGORITHM,
+ Key :: iodata(),
+ Data :: iodata(),
+ Mac :: binary() .
+hmac(Type, Key, Data) ->
+ Data1 = iolist_to_binary(Data),
+ hmac(Type, Key, Data1, undefined, erlang:byte_size(Data1), max_bytes()).
+
+-spec hmac(Type, Key, Data, MacLength) ->
+ Mac when Type :: ?HMAC_HASH_ALGORITHM,
+ Key :: iodata(),
+ Data :: iodata(),
+ MacLength :: integer(),
+ Mac :: binary() .
+
+hmac(Type, Key, Data, MacLength) ->
+ Data1 = iolist_to_binary(Data),
+ hmac(Type, Key, Data1, MacLength, erlang:byte_size(Data1), max_bytes()).
+%%%---- hmac_init, hamc_update, hmac_final
+
+-opaque hmac_state() :: binary().
+
+-spec hmac_init(Type, Key) ->
+ State when Type :: ?HMAC_HASH_ALGORITHM,
+ Key :: iodata(),
+ State :: hmac_state() .
hmac_init(Type, Key) ->
notsup_to_error(hmac_init_nif(Type, Key)).
+%%%---- hmac_update
+
+-spec hmac_update(State, Data) -> NewState when Data :: iodata(),
+ State :: hmac_state(),
+ NewState :: hmac_state().
hmac_update(State, Data0) ->
Data = iolist_to_binary(Data0),
hmac_update(State, Data, erlang:byte_size(Data), max_bytes()).
+%%%---- hmac_final
+
+-spec hmac_final(State) -> Mac when State :: hmac_state(),
+ Mac :: binary().
hmac_final(Context) ->
notsup_to_error(hmac_final_nif(Context)).
+
+-spec hmac_final_n(State, HashLen) -> Mac when State :: hmac_state(),
+ HashLen :: integer(),
+ Mac :: binary().
hmac_final_n(Context, HashLen) ->
notsup_to_error(hmac_final_nif(Context, HashLen)).
--spec cmac(_, iodata(), iodata()) -> binary().
--spec cmac(_, iodata(), iodata(), integer()) -> binary().
+%%%---- CMAC
+
+-define(CMAC_CIPHER_ALGORITHM, cbc_cipher() | cfb_cipher() | blowfish_cbc | des_ede3 | rc2_cbc ).
+-spec cmac(Type, Key, Data) ->
+ Mac when Type :: ?CMAC_CIPHER_ALGORITHM,
+ Key :: iodata(),
+ Data :: iodata(),
+ Mac :: binary().
cmac(Type, Key, Data) ->
notsup_to_error(cmac_nif(Type, Key, Data)).
-cmac(Type, Key, Data, MacSize) ->
- erlang:binary_part(cmac(Type, Key, Data), 0, MacSize).
-
-%% Ecrypt/decrypt %%%
-
--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()}.
-
-block_encrypt(Type, Key, Ivec, Data) when Type =:= des_cbc;
+
+-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).
+
+%%%================================================================
+%%%
+%%% Encrypt/decrypt
+%%%
+%%%================================================================
+
+%%%---- Block ciphers
+
+-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, PlainText) when Type =:= des_cbc;
Type =:= des_cfb;
Type =:= blowfish_cbc;
Type =:= blowfish_cfb64;
@@ -218,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;
@@ -263,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) ->
@@ -276,31 +556,40 @@ 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;
des3_cbc -> 8;
+ blowfish_cbc -> 8;
aes_cbc -> 16;
- aes_ige -> 32
+ aes_ige -> 32; % For compatibility if someone has bug-adapted code
+ aes_ige256 -> 32 % The name used in block_encrypt et al
end,
{_, IVec} = split_binary(Data, size(Data) - IVecSize),
IVec;
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]),
@@ -309,38 +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)}.
+ {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);
@@ -349,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,
@@ -416,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>>;
@@ -451,116 +769,228 @@ rand_seed(Seed) when is_binary(Seed) ->
rand_seed_nif(_Seed) -> ?nif_stub.
--spec mod_pow(binary()|integer(), binary()|integer(), binary()|integer()) -> binary() | error.
-mod_pow(Base, Exponent, Prime) ->
- case mod_exp_nif(ensure_int_as_bin(Base), ensure_int_as_bin(Exponent), ensure_int_as_bin(Prime), 0) of
- <<0>> -> error;
- R -> R
- end.
+%%%================================================================
+%%%
+%%% Sign/verify
+%%%
+%%%================================================================
+-type pk_sign_verify_algs() :: rsa | dss | ecdsa .
-verify(Algorithm, Type, Data, Signature, Key) ->
- verify(Algorithm, Type, Data, Signature, Key, []).
+-type pk_sign_verify_opts() :: [ rsa_sign_verify_opt() ] .
+
+-type rsa_sign_verify_opt() :: {rsa_padding, rsa_sign_verify_padding()}
+ | {rsa_pss_saltlen, integer()} .
+
+-type rsa_sign_verify_padding() :: rsa_pkcs1_padding | rsa_pkcs1_pss_padding
+ | rsa_x931_padding | rsa_no_padding
+ .
-%% Backwards compatible
-verify(Algorithm = dss, none, Digest, Signature, Key, Options) ->
- verify(Algorithm, sha, {digest, Digest}, Signature, Key, Options);
-verify(Algorithm, Type, Data, Signature, Key, Options) ->
- case pkey_verify_nif(Algorithm, Type, Data, Signature, format_pkey(Algorithm, Key), Options) of
- notsup -> erlang:error(notsup);
- Boolean -> Boolean
- end.
+%%%----------------------------------------------------------------
+%%% Sign
+
+-spec sign(Algorithm, DigestType, Msg, Key)
+ -> Signature
+ when Algorithm :: pk_sign_verify_algs(),
+ DigestType :: rsa_digest_type()
+ | dss_digest_type()
+ | ecdsa_digest_type(),
+ Msg :: binary() | {digest,binary()},
+ Key :: rsa_private()
+ | dss_private()
+ | [ecdsa_private()|ecdsa_params()]
+ | engine_key_ref(),
+ Signature :: binary() .
sign(Algorithm, Type, Data, Key) ->
sign(Algorithm, Type, Data, Key, []).
-%% Backwards compatible
-sign(Algorithm = dss, none, Digest, Key, Options) ->
- sign(Algorithm, sha, {digest, Digest}, Key, Options);
-sign(Algorithm, Type, Data, Key, Options) ->
+
+-spec sign(Algorithm, DigestType, Msg, Key, Options)
+ -> Signature
+ when Algorithm :: pk_sign_verify_algs(),
+ DigestType :: rsa_digest_type()
+ | dss_digest_type()
+ | ecdsa_digest_type()
+ | none,
+ Msg :: binary() | {digest,binary()},
+ Key :: rsa_private()
+ | dss_private()
+ | [ecdsa_private() | ecdsa_params()]
+ | engine_key_ref(),
+ Options :: pk_sign_verify_opts(),
+ Signature :: binary() .
+
+sign(Algorithm0, Type0, Data, Key, Options) ->
+ {Algorithm, Type} = sign_verify_compatibility(Algorithm0, Type0, Data),
case pkey_sign_nif(Algorithm, Type, Data, format_pkey(Algorithm, Key), Options) of
error -> erlang:error(badkey, [Algorithm, Type, Data, Key, Options]);
notsup -> erlang:error(notsup);
Signature -> Signature
end.
+pkey_sign_nif(_Algorithm, _Type, _Digest, _Key, _Options) -> ?nif_stub.
+%%%----------------------------------------------------------------
+%%% Verify
+
+-spec verify(Algorithm, DigestType, Msg, Signature, Key)
+ -> Result
+ when Algorithm :: pk_sign_verify_algs(),
+ DigestType :: rsa_digest_type()
+ | dss_digest_type()
+ | ecdsa_digest_type(),
+ Msg :: binary() | {digest,binary()},
+ Signature :: binary(),
+ Key :: rsa_private()
+ | dss_private()
+ | [ecdsa_private() | ecdsa_params()]
+ | engine_key_ref(),
+ Result :: boolean().
--type key_id() :: string() | binary() .
--type password() :: string() | binary() .
-
--type engine_key_ref() :: #{engine := engine_ref(),
- key_id := key_id(),
- password => password(),
- term() => term()
- }.
-
--type pk_algs() :: rsa | ecdsa | dss .
--type pk_key() :: engine_key_ref() | [integer() | binary()] .
--type pk_opt() :: list() | rsa_padding() .
-
--spec public_encrypt(pk_algs(), binary(), pk_key(), pk_opt()) -> binary().
--spec public_decrypt(pk_algs(), binary(), pk_key(), pk_opt()) -> binary().
--spec private_encrypt(pk_algs(), binary(), pk_key(), pk_opt()) -> binary().
--spec private_decrypt(pk_algs(), binary(), pk_key(), pk_opt()) -> binary().
+verify(Algorithm, Type, Data, Signature, Key) ->
+ verify(Algorithm, Type, Data, Signature, Key, []).
-public_encrypt(Algorithm, In, Key, Options) when is_list(Options) ->
- case pkey_crypt_nif(Algorithm, In, format_pkey(Algorithm, Key), Options, false, true) of
- error -> erlang:error(encrypt_failed, [Algorithm, In, Key, Options]);
+-spec verify(Algorithm, DigestType, Msg, Signature, Key, Options)
+ -> Result
+ when Algorithm :: pk_sign_verify_algs(),
+ DigestType :: rsa_digest_type()
+ | dss_digest_type()
+ | ecdsa_digest_type(),
+ Msg :: binary() | {digest,binary()},
+ Signature :: binary(),
+ Key :: rsa_public()
+ | dss_public()
+ | [ecdsa_public() | ecdsa_params()]
+ | engine_key_ref(),
+ Options :: pk_sign_verify_opts(),
+ Result :: boolean().
+
+verify(Algorithm0, Type0, Data, Signature, Key, Options) ->
+ {Algorithm, Type} = sign_verify_compatibility(Algorithm0, Type0, Data),
+ case pkey_verify_nif(Algorithm, Type, Data, Signature, format_pkey(Algorithm, Key), Options) of
notsup -> erlang:error(notsup);
- Out -> Out
- end;
-%% Backwards compatible
-public_encrypt(Algorithm = rsa, In, Key, Padding) when is_atom(Padding) ->
- public_encrypt(Algorithm, In, Key, [{rsa_padding, Padding}]).
+ Boolean -> Boolean
+ end.
-private_decrypt(Algorithm, In, Key, Options) when is_list(Options) ->
- case pkey_crypt_nif(Algorithm, In, format_pkey(Algorithm, Key), Options, true, false) of
- error -> erlang:error(decrypt_failed, [Algorithm, In, Key, Options]);
- notsup -> erlang:error(notsup);
- Out -> Out
- end;
-%% Backwards compatible
-private_decrypt(Algorithm = rsa, In, Key, Padding) when is_atom(Padding) ->
- private_decrypt(Algorithm, In, Key, [{rsa_padding, Padding}]).
+pkey_verify_nif(_Algorithm, _Type, _Data, _Signature, _Key, _Options) -> ?nif_stub.
-private_encrypt(Algorithm, In, Key, Options) when is_list(Options) ->
- case pkey_crypt_nif(Algorithm, In, format_pkey(Algorithm, Key), Options, true, true) of
- error -> erlang:error(encrypt_failed, [Algorithm, In, Key, Options]);
- notsup -> erlang:error(notsup);
- Out -> Out
- end;
-%% Backwards compatible
-private_encrypt(Algorithm = rsa, In, Key, Padding) when is_atom(Padding) ->
- private_encrypt(Algorithm, In, Key, [{rsa_padding, Padding}]).
+%% Backwards compatible:
+sign_verify_compatibility(dss, none, Digest) ->
+ {sha, {digest, Digest}};
+sign_verify_compatibility(Algorithm0, Type0, _Digest) ->
+ {Algorithm0, Type0}.
-public_decrypt(Algorithm, In, Key, Options) when is_list(Options) ->
- case pkey_crypt_nif(Algorithm, In, format_pkey(Algorithm, Key), Options, false, false) of
- error -> erlang:error(decrypt_failed, [Algorithm, In, Key, Options]);
+%%%================================================================
+%%%
+%%% Public/private encrypt/decrypt
+%%%
+%%% Only rsa works so far (although ecdsa | dss should do it)
+%%%================================================================
+-type pk_encrypt_decrypt_algs() :: rsa .
+
+-type pk_encrypt_decrypt_opts() :: [rsa_opt()] | rsa_compat_opts().
+
+-type rsa_compat_opts() :: [{rsa_pad, rsa_padding()}]
+ | rsa_padding() .
+
+-type rsa_padding() :: rsa_pkcs1_padding
+ | rsa_pkcs1_oaep_padding
+ | rsa_sslv23_padding
+ | rsa_x931_padding
+ | rsa_no_padding.
+
+-type rsa_opt() :: {rsa_padding, rsa_padding()}
+ | {signature_md, atom()}
+ | {rsa_mgf1_md, sha}
+ | {rsa_oaep_label, binary()}
+ | {rsa_oaep_md, sha} .
+
+%%%---- Encrypt with public key
+
+-spec public_encrypt(Algorithm, PlainText, PublicKey, Options) ->
+ CipherText when Algorithm :: pk_encrypt_decrypt_algs(),
+ PlainText :: binary(),
+ PublicKey :: rsa_public() | engine_key_ref(),
+ Options :: pk_encrypt_decrypt_opts(),
+ CipherText :: binary().
+public_encrypt(Algorithm, PlainText, PublicKey, Options) ->
+ pkey_crypt(Algorithm, PlainText, PublicKey, Options, false, true).
+
+%%%---- Decrypt with private key
+
+-spec private_decrypt(Algorithm, CipherText, PrivateKey, Options) ->
+ PlainText when Algorithm :: pk_encrypt_decrypt_algs(),
+ CipherText :: binary(),
+ PrivateKey :: rsa_private() | engine_key_ref(),
+ Options :: pk_encrypt_decrypt_opts(),
+ PlainText :: binary() .
+private_decrypt(Algorithm, CipherText, PrivateKey, Options) ->
+ pkey_crypt(Algorithm, CipherText, PrivateKey, Options, true, false).
+
+%%%---- Encrypt with private key
+
+-spec private_encrypt(Algorithm, PlainText, PrivateKey, Options) ->
+ CipherText when Algorithm :: pk_encrypt_decrypt_algs(),
+ PlainText :: binary(),
+ PrivateKey :: rsa_private() | engine_key_ref(),
+ Options :: pk_encrypt_decrypt_opts(),
+ CipherText :: binary().
+private_encrypt(Algorithm, PlainText, PrivateKey, Options) ->
+ pkey_crypt(Algorithm, PlainText, PrivateKey, Options, true, true).
+
+%%%---- Decrypt with public key
+
+-spec public_decrypt(Algorithm, CipherText, PublicKey, Options) ->
+ PlainText when Algorithm :: pk_encrypt_decrypt_algs(),
+ CipherText :: binary(),
+ PublicKey :: rsa_public() | engine_key_ref(),
+ Options :: pk_encrypt_decrypt_opts(),
+ PlainText :: binary() .
+public_decrypt(Algorithm, CipherText, PublicKey, Options) ->
+ pkey_crypt(Algorithm, CipherText, PublicKey, Options, false, false).
+
+%%%---- Call the nif, but fix a compatibility issue first
+
+%% Backwards compatible (rsa_pad -> rsa_padding is handled by the pkey_crypt_nif):
+pkey_crypt(rsa, Text, Key, Padding, PubPriv, EncDec) when is_atom(Padding) ->
+ pkey_crypt(rsa, Text, Key, [{rsa_padding, Padding}], PubPriv, EncDec);
+
+pkey_crypt(Alg, Text, Key, Options, PubPriv, EncDec) ->
+ case pkey_crypt_nif(Alg, Text, format_pkey(Alg,Key), Options, PubPriv, EncDec) of
+ error when EncDec==true -> erlang:error(encrypt_failed, [Alg, Text, Key, Options]);
+ error when EncDec==false -> erlang:error(decrypt_failed, [Alg, Text, Key, Options]);
notsup -> erlang:error(notsup);
Out -> Out
- end;
-%% Backwards compatible
-public_decrypt(Algorithm = rsa, In, Key, Padding) when is_atom(Padding) ->
- public_decrypt(Algorithm, In, Key, [{rsa_padding, Padding}]).
-
-
-%%
-%% XOR - xor to iolists and return a binary
-%% NB doesn't check that they are the same size, just concatenates
-%% them and sends them to the driver
-%%
--spec exor(iodata(), iodata()) -> binary().
+ end.
-exor(Bin1, Bin2) ->
- Data1 = iolist_to_binary(Bin1),
- Data2 = iolist_to_binary(Bin2),
- MaxBytes = max_bytes(),
- exor(Data1, Data2, erlang:byte_size(Data1), MaxBytes, []).
+pkey_crypt_nif(_Algorithm, _In, _Key, _Options, _IsPrivate, _IsEncrypt) -> ?nif_stub.
+%%%================================================================
+%%%
+%%%
+%%%
+%%%================================================================
+
+-spec generate_key(Type, Params)
+ -> {PublicKey, PrivKeyOut}
+ when Type :: dh | ecdh | rsa | srp,
+ PublicKey :: dh_public() | ecdh_public() | rsa_public() | srp_public(),
+ PrivKeyOut :: dh_private() | ecdh_private() | rsa_private() | {srp_public(),srp_private()},
+ Params :: dh_params() | ecdh_params() | rsa_params() | srp_gen_params()
+ .
generate_key(Type, Params) ->
generate_key(Type, Params, undefined).
+-spec generate_key(Type, Params, PrivKeyIn)
+ -> {PublicKey, PrivKeyOut}
+ when Type :: dh | ecdh | rsa | srp,
+ PublicKey :: dh_public() | ecdh_public() | rsa_public() | srp_public(),
+ PrivKeyIn :: undefined | dh_private() | ecdh_private() | rsa_private() | {srp_public(),srp_private()},
+ PrivKeyOut :: dh_private() | ecdh_private() | rsa_private() | {srp_public(),srp_private()},
+ Params :: dh_params() | ecdh_params() | rsa_params() | srp_comp_params()
+ .
+
generate_key(dh, DHParameters0, PrivateKey) ->
{DHParameters, Len} =
case DHParameters0 of
@@ -607,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),
@@ -659,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
%%----------------------------------------------------------------------
@@ -673,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()).
@@ -692,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
@@ -741,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))) ||
@@ -764,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)))
@@ -775,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, <<>>} ->
@@ -830,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}]),
@@ -861,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()).
@@ -868,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(),
@@ -919,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 ->
@@ -999,9 +1515,13 @@ path2bin(Path) when is_list(Path) ->
Bin
end.
-%%--------------------------------------------------------------------
+%%%================================================================
+%%%================================================================
+%%%
%%% Internal functions
-%%--------------------------------------------------------------------
+%%%
+%%%================================================================
+
max_bytes() ->
?MAX_BYTES_TO_NIF.
@@ -1061,9 +1581,12 @@ hmac_final_nif(_Context) -> ?nif_stub.
hmac_final_nif(_Context, _MacSize) -> ?nif_stub.
%% CMAC
-
cmac_nif(_Type, _Key, _Data) -> ?nif_stub.
+%% POLY1305
+poly1305_nif(_Key, _Data) -> ?nif_stub.
+
+
%% CIPHERS --------------------------------------------------------------------
block_crypt_nif(_Type, _Key, _Ivec, _Text, _IsEncrypt) -> ?nif_stub.
@@ -1118,27 +1641,25 @@ do_stream_encrypt({aes_ctr, State0}, Data) ->
{{aes_ctr, State}, Cipher};
do_stream_encrypt({rc4, State0}, Data) ->
{State, Cipher} = rc4_encrypt_with_state(State0, Data),
- {{rc4, State}, Cipher}.
+ {{rc4, State}, Cipher};
+do_stream_encrypt({chacha20, State0}, Data) ->
+ {State, Cipher} = chacha20_stream_encrypt(State0, Data),
+ {{chacha20, State}, Cipher}.
do_stream_decrypt({aes_ctr, State0}, Data) ->
{State, Text} = aes_ctr_stream_decrypt(State0, Data),
{{aes_ctr, State}, Text};
do_stream_decrypt({rc4, State0}, Data) ->
{State, Text} = rc4_encrypt_with_state(State0, Data),
- {{rc4, State}, Text}.
+ {{rc4, State}, Text};
+do_stream_decrypt({chacha20, State0}, Data) ->
+ {State, Cipher} = chacha20_stream_decrypt(State0, Data),
+ {{chacha20, State}, Cipher}.
%%
%% 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.
@@ -1149,6 +1670,13 @@ aes_ctr_stream_decrypt(_State, _Cipher) -> ?nif_stub.
rc4_set_key(_Key) -> ?nif_stub.
rc4_encrypt_with_state(_State, _Data) -> ?nif_stub.
+%%
+%% CHACHA20 - stream cipher
+%%
+chacha20_stream_init(_Key, _IVec) -> ?nif_stub.
+chacha20_stream_encrypt(_State, _Data) -> ?nif_stub.
+chacha20_stream_decrypt(_State, _Data) -> ?nif_stub.
+
%% Secure remote password -------------------------------------------------------------------
user_srp_gen_key(Private, Generator, Prime) ->
@@ -1215,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
%%
@@ -1241,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
@@ -1273,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
@@ -1316,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).
@@ -1363,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)
diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl
index da2fd7a30e..170a97aecb 100644
--- a/lib/crypto/test/crypto_SUITE.erl
+++ b/lib/crypto/test/crypto_SUITE.erl
@@ -81,6 +81,8 @@ groups() ->
{group, aes_ctr},
{group, aes_gcm},
{group, chacha20_poly1305},
+ {group, chacha20},
+ {group, poly1305},
{group, aes_cbc}]},
{fips, [], [{group, no_md4},
{group, no_md5},
@@ -116,6 +118,7 @@ groups() ->
{group, aes_ctr},
{group, aes_gcm},
{group, no_chacha20_poly1305},
+ {group, no_chacha20},
{group, aes_cbc}]},
{md4, [], [hash]},
{md5, [], [hash, hmac]},
@@ -165,6 +168,8 @@ groups() ->
{aes_ctr, [], [stream]},
{aes_gcm, [], [aead]},
{chacha20_poly1305, [], [aead]},
+ {chacha20, [], [stream]},
+ {poly1305, [], [poly1305]},
{aes_cbc, [], [block]},
{no_md4, [], [no_support, no_hash]},
{no_md5, [], [no_support, no_hash, no_hmac]},
@@ -178,6 +183,7 @@ groups() ->
{no_blowfish_ofb64, [], [no_support, no_block]},
{no_aes_ige256, [], [no_support, no_block]},
{no_chacha20_poly1305, [], [no_support, no_aead]},
+ {no_chacha20, [], [no_support, no_stream_ivec]},
{no_rc2_cbc, [], [no_support, no_block]},
{no_rc4, [], [no_support, no_stream]},
{api_errors, [], [api_errors_ecdh]}
@@ -364,6 +370,20 @@ cmac(Config) when is_list(Config) ->
lists:foreach(fun cmac_check/1, Pairs),
lists:foreach(fun cmac_check/1, cmac_iolistify(Pairs)).
%%--------------------------------------------------------------------
+poly1305() ->
+ [{doc, "Test poly1305 function"}].
+poly1305(Config) ->
+ lists:foreach(
+ fun({Key, Txt, Expect}) ->
+ case crypto:poly1305(Key,Txt) of
+ Expect ->
+ ok;
+ Other ->
+ ct:fail({{crypto, poly1305, [Key, Txt]}, {expected, Expect}, {got, Other}})
+ end
+ end, proplists:get_value(poly1305, Config)).
+
+%%--------------------------------------------------------------------
block() ->
[{doc, "Test block ciphers"}].
block(Config) when is_list(Config) ->
@@ -428,6 +448,13 @@ no_stream(Config) when is_list(Config) ->
notsup(fun crypto:stream_init/2, [Type, <<"Key">>]).
%%--------------------------------------------------------------------
+no_stream_ivec() ->
+ [{doc, "Test disabled stream ciphers that uses ivec"}].
+no_stream_ivec(Config) when is_list(Config) ->
+ Type = ?config(type, Config),
+ notsup(fun crypto:stream_init/3, [Type, <<"Key">>, <<"Ivec">>]).
+
+%%--------------------------------------------------------------------
aead() ->
[{doc, "Test AEAD ciphers"}].
aead(Config) when is_list(Config) ->
@@ -763,16 +790,33 @@ stream_cipher({Type, Key, IV, PlainText}) ->
ok;
Other ->
ct:fail({{crypto, stream_decrypt, [State, CipherText]}, {expected, PlainText}, {got, Other}})
+ end;
+stream_cipher({Type, Key, IV, PlainText, CipherText}) ->
+ Plain = iolist_to_binary(PlainText),
+ State = crypto:stream_init(Type, Key, IV),
+ case crypto:stream_encrypt(State, PlainText) of
+ {_, CipherText} ->
+ ok;
+ {_, Other0} ->
+ ct:fail({{crypto, stream_encrypt, [State, Type, Key, IV, Plain]}, {expected, CipherText}, {got, Other0}})
+ end,
+ case crypto:stream_decrypt(State, CipherText) of
+ {_, Plain} ->
+ ok;
+ Other1 ->
+ ct:fail({{crypto, stream_decrypt, [State, CipherText]}, {expected, PlainText}, {got, Other1}})
end.
stream_cipher_incment({Type, Key, PlainTexts}) ->
State = crypto:stream_init(Type, Key),
- stream_cipher_incment(State, State, PlainTexts, [], iolist_to_binary(PlainTexts));
+ stream_cipher_incment_loop(State, State, PlainTexts, [], iolist_to_binary(PlainTexts));
stream_cipher_incment({Type, Key, IV, PlainTexts}) ->
State = crypto:stream_init(Type, Key, IV),
- stream_cipher_incment(State, State, PlainTexts, [], iolist_to_binary(PlainTexts)).
+ stream_cipher_incment_loop(State, State, PlainTexts, [], iolist_to_binary(PlainTexts));
+stream_cipher_incment({Type, Key, IV, PlainTexts, _CipherText}) ->
+ stream_cipher_incment({Type, Key, IV, PlainTexts}).
-stream_cipher_incment(_State, OrigState, [], Acc, Plain) ->
+stream_cipher_incment_loop(_State, OrigState, [], Acc, Plain) ->
CipherText = iolist_to_binary(lists:reverse(Acc)),
case crypto:stream_decrypt(OrigState, CipherText) of
{_, Plain} ->
@@ -780,9 +824,9 @@ stream_cipher_incment(_State, OrigState, [], Acc, Plain) ->
Other ->
ct:fail({{crypto, stream_decrypt, [OrigState, CipherText]}, {expected, Plain}, {got, Other}})
end;
-stream_cipher_incment(State0, OrigState, [PlainText | PlainTexts], Acc, Plain) ->
+stream_cipher_incment_loop(State0, OrigState, [PlainText | PlainTexts], Acc, Plain) ->
{State, CipherText} = crypto:stream_encrypt(State0, PlainText),
- stream_cipher_incment(State, OrigState, PlainTexts, [CipherText | Acc], Plain).
+ stream_cipher_incment_loop(State, OrigState, PlainTexts, [CipherText | Acc], Plain).
aead_cipher({Type, Key, PlainText, IV, AAD, CipherText, CipherTag}) ->
Plain = iolist_to_binary(PlainText),
@@ -1035,7 +1079,9 @@ do_cmac_iolistify({Type, Key, Text, Size, CMac}) ->
do_stream_iolistify({Type, Key, PlainText}) ->
{Type, iolistify(Key), iolistify(PlainText)};
do_stream_iolistify({Type, Key, IV, PlainText}) ->
- {Type, iolistify(Key), IV, iolistify(PlainText)}.
+ {Type, iolistify(Key), IV, iolistify(PlainText)};
+do_stream_iolistify({Type, Key, IV, PlainText, CipherText}) ->
+ {Type, iolistify(Key), IV, iolistify(PlainText), CipherText}.
do_block_iolistify({des_cbc = Type, Key, IV, PlainText}) ->
{Type, Key, IV, des_iolistify(PlainText)};
@@ -1452,6 +1498,18 @@ group_config(aes_gcm, Config) ->
group_config(chacha20_poly1305, Config) ->
AEAD = chacha20_poly1305(),
[{aead, AEAD} | Config];
+group_config(chacha20, Config) ->
+ Stream = chacha20(),
+ [{stream, Stream} | Config];
+group_config(poly1305, Config) ->
+ V = [%% {Key, Txt, Expect}
+ {%% RFC7539 2.5.2
+ crypto_SUITE:hexstr2bin("85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b"),
+ <<"Cryptographic Forum Research Group">>,
+ crypto_SUITE:hexstr2bin("a8061dc1305136c6c22b8baf0c0127a9")
+ }
+ ],
+ [{poly1305,V} | Config];
group_config(aes_cbc, Config) ->
Block = aes_cbc(Config),
[{block, Block} | Config];
@@ -2243,6 +2301,7 @@ aes_gcm(Config) ->
"gcmEncryptExtIV192.rsp",
"gcmEncryptExtIV256.rsp"]).
+
%% https://tools.ietf.org/html/rfc7539#appendix-A.5
chacha20_poly1305() ->
[
@@ -2288,6 +2347,103 @@ chacha20_poly1305() ->
hexstr2bin("eead9d67890cbb22392336fea1851f38")} %% CipherTag
].
+
+chacha20() ->
+%%% chacha20 (no mode) test vectors from RFC 7539 A.2
+ [
+ %% Test Vector #1:
+ {chacha20,
+ hexstr2bin("00000000000000000000000000000000"
+ "00000000000000000000000000000000"), %% Key
+ hexstr2bin("00000000" % Initial counter = 0, little-endian
+ "000000000000000000000000"), %% IV
+ hexstr2bin("00000000000000000000000000000000" %% PlainText
+ "00000000000000000000000000000000"
+ "00000000000000000000000000000000"
+ "00000000000000000000000000000000"),
+ hexstr2bin("76b8e0ada0f13d90405d6ae55386bd28" %% CipherText
+ "bdd219b8a08ded1aa836efcc8b770dc7"
+ "da41597c5157488d7724e03fb8d84a37"
+ "6a43b8f41518a11cc387b669b2ee6586")},
+ %% Test Vector #2:
+ {chacha20,
+ hexstr2bin("00000000000000000000000000000000"
+ "00000000000000000000000000000001"), %% Key
+ hexstr2bin("01000000" % Initial counter = 1, little-endian
+ "000000000000000000000002"), %% IV
+ hexstr2bin("416e79207375626d697373696f6e2074" %% PlainText
+ "6f20746865204945544620696e74656e"
+ "6465642062792074686520436f6e7472"
+ "696275746f7220666f72207075626c69"
+ "636174696f6e20617320616c6c206f72"
+ "2070617274206f6620616e2049455446"
+ "20496e7465726e65742d447261667420"
+ "6f722052464320616e6420616e792073"
+ "746174656d656e74206d616465207769"
+ "7468696e2074686520636f6e74657874"
+ "206f6620616e20494554462061637469"
+ "7669747920697320636f6e7369646572"
+ "656420616e20224945544620436f6e74"
+ "7269627574696f6e222e205375636820"
+ "73746174656d656e747320696e636c75"
+ "6465206f72616c2073746174656d656e"
+ "747320696e2049455446207365737369"
+ "6f6e732c2061732077656c6c20617320"
+ "7772697474656e20616e6420656c6563"
+ "74726f6e696320636f6d6d756e696361"
+ "74696f6e73206d61646520617420616e"
+ "792074696d65206f7220706c6163652c"
+ "20776869636820617265206164647265"
+ "7373656420746f"),
+ hexstr2bin("a3fbf07df3fa2fde4f376ca23e827370" %% CipherText
+ "41605d9f4f4f57bd8cff2c1d4b7955ec"
+ "2a97948bd3722915c8f3d337f7d37005"
+ "0e9e96d647b7c39f56e031ca5eb6250d"
+ "4042e02785ececfa4b4bb5e8ead0440e"
+ "20b6e8db09d881a7c6132f420e527950"
+ "42bdfa7773d8a9051447b3291ce1411c"
+ "680465552aa6c405b7764d5e87bea85a"
+ "d00f8449ed8f72d0d662ab052691ca66"
+ "424bc86d2df80ea41f43abf937d3259d"
+ "c4b2d0dfb48a6c9139ddd7f76966e928"
+ "e635553ba76c5c879d7b35d49eb2e62b"
+ "0871cdac638939e25e8a1e0ef9d5280f"
+ "a8ca328b351c3c765989cbcf3daa8b6c"
+ "cc3aaf9f3979c92b3720fc88dc95ed84"
+ "a1be059c6499b9fda236e7e818b04b0b"
+ "c39c1e876b193bfe5569753f88128cc0"
+ "8aaa9b63d1a16f80ef2554d7189c411f"
+ "5869ca52c5b83fa36ff216b9c1d30062"
+ "bebcfd2dc5bce0911934fda79a86f6e6"
+ "98ced759c3ff9b6477338f3da4f9cd85"
+ "14ea9982ccafb341b2384dd902f3d1ab"
+ "7ac61dd29c6f21ba5b862f3730e37cfd"
+ "c4fd806c22f221")},
+ %%Test Vector #3:
+ {chacha20,
+ hexstr2bin("1c9240a5eb55d38af333888604f6b5f0"
+ "473917c1402b80099dca5cbc207075c0"), %% Key
+ hexstr2bin("2a000000" % Initial counter = 42 (decimal), little-endian
+ "000000000000000000000002"), %% IV
+ hexstr2bin("2754776173206272696c6c69672c2061" %% PlainText
+ "6e642074686520736c6974687920746f"
+ "7665730a446964206779726520616e64"
+ "2067696d626c6520696e207468652077"
+ "6162653a0a416c6c206d696d73792077"
+ "6572652074686520626f726f676f7665"
+ "732c0a416e6420746865206d6f6d6520"
+ "7261746873206f757467726162652e"),
+ hexstr2bin("62e6347f95ed87a45ffae7426f27a1df" %% CipherText
+ "5fb69110044c0d73118effa95b01e5cf"
+ "166d3df2d721caf9b21e5fb14c616871"
+ "fd84c54f9d65b283196c7fe4f60553eb"
+ "f39c6402c42234e32a356b3e764312a6"
+ "1a5532055716ead6962568f87d3f3f77"
+ "04c6a8d1bcd1bf4d50d6154b6da731b1"
+ "87b58dfd728afa36757a797ac188d1")}
+ ].
+
+
rsa_plain() ->
<<"7896345786348756234 Hejsan Svejsan, erlang crypto debugger"
"09812312908312378623487263487623412039812 huagasd">>.
@@ -2483,7 +2639,9 @@ srp(ClientPrivate, Generator, Prime, Version, Verifier, ServerPublic, ServerPriv
SessionKey}.
ecdh() ->
%% http://csrc.nist.gov/groups/STM/cavp/
- Curves = crypto:ec_curves(),
+ Curves = crypto:ec_curves() ++
+ [X || X <- proplists:get_value(curves, crypto:supports(), []),
+ lists:member(X, [x25519,x448])],
TestCases =
[{ecdh, hexstr2point("42ea6dd9969dd2a61fea1aac7f8e98edcc896c6e55857cc0", "dfbe5d7c61fac88b11811bde328e8a0d12bf01a9d204b523"),
hexstr2bin("f17d3fea367b74d340851ca4270dcb24c271f445bed9d527"),
@@ -2566,7 +2724,32 @@ ecdh() ->
"2FDC313095BCDD5FB3A91636F07A959C8E86B5636A1E930E8396049CB481961D365CC11453A06C719835475B12CB52FC3C383BCE35E27EF194512B71876285FA"),
hexstr2bin("16302FF0DBBB5A8D733DAB7141C1B45ACBC8715939677F6A56850A38BD87BD59B09E80279609FF333EB9D4C061231FB26F92EEB04982A5F1D1764CAD57665422"),
brainpoolP512r1,
- hexstr2bin("A7927098655F1F9976FA50A9D566865DC530331846381C87256BAF3226244B76D36403C024D7BBF0AA0803EAFF405D3D24F11A9B5C0BEF679FE1454B21C4CD1F")}],
+ hexstr2bin("A7927098655F1F9976FA50A9D566865DC530331846381C87256BAF3226244B76D36403C024D7BBF0AA0803EAFF405D3D24F11A9B5C0BEF679FE1454B21C4CD1F")},
+
+ %% RFC 7748, 6.1
+ {ecdh,
+ 16#8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a,
+ 16#5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb,
+ x25519,
+ hexstr2bin("4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742")},
+ {ecdh,
+ 16#de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f,
+ 16#77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a,
+ x25519,
+ hexstr2bin("4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742")},
+
+ %% RFC 7748, 6.2
+ {ecdh,
+ 16#9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0,
+ 16#1c306a7ac2a0e2e0990b294470cba339e6453772b075811d8fad0d1d6927c120bb5ee8972b0d3e21374c9c921b09d1b0366f10b65173992d,
+ x448,
+ hexstr2bin("07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b56fd2464c335543936521c24403085d59a449a5037514a879d")},
+ {ecdh,
+ 16#3eb7a829b0cd20f5bcfc0b599b6feccf6da4627107bdb0d4f345b43027d8b972fc3e34fb4232a13ca706dcb57aec3dae07bdc1c67bf33609,
+ 16#9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b,
+ x448,
+ hexstr2bin("07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b56fd2464c335543936521c24403085d59a449a5037514a879d")}
+ ],
lists:filter(fun ({_Type, _Pub, _Priv, Curve, _SharedSecret}) ->
lists:member(Curve, Curves)
end,
diff --git a/lib/crypto/vsn.mk b/lib/crypto/vsn.mk
index 0d7b0e5575..d262492668 100644
--- a/lib/crypto/vsn.mk
+++ b/lib/crypto/vsn.mk
@@ -1 +1 @@
-CRYPTO_VSN = 4.3.1
+CRYPTO_VSN = 4.3.2