aboutsummaryrefslogtreecommitdiffstats
path: root/lib/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'lib/crypto')
-rw-r--r--lib/crypto/Makefile6
-rw-r--r--lib/crypto/c_src/Makefile.in9
-rw-r--r--lib/crypto/c_src/crypto.c3049
-rw-r--r--lib/crypto/c_src/crypto_callback.c10
-rw-r--r--lib/crypto/c_src/crypto_callback.h2
-rw-r--r--lib/crypto/doc/src/book.xml2
-rw-r--r--lib/crypto/doc/src/crypto.xml34
-rw-r--r--lib/crypto/doc/src/crypto_app.xml2
-rw-r--r--lib/crypto/doc/src/licenses.xml2
-rw-r--r--lib/crypto/doc/src/notes.xml150
-rw-r--r--lib/crypto/doc/src/ref_man.xml2
-rw-r--r--lib/crypto/doc/src/release_notes.xml2
-rw-r--r--lib/crypto/doc/src/usersguide.xml2
-rw-r--r--lib/crypto/src/Makefile2
-rw-r--r--lib/crypto/src/crypto.app.src2
-rw-r--r--lib/crypto/src/crypto.appup.src2
-rw-r--r--lib/crypto/src/crypto.erl914
-rw-r--r--lib/crypto/test/Makefile2
-rw-r--r--lib/crypto/test/blowfish_SUITE.erl5
-rw-r--r--lib/crypto/test/crypto_SUITE.erl178
-rw-r--r--lib/crypto/test/old_crypto_SUITE.erl59
-rw-r--r--lib/crypto/vsn.mk2
22 files changed, 1863 insertions, 2575 deletions
diff --git a/lib/crypto/Makefile b/lib/crypto/Makefile
index 24db75bf91..afe56aa7d6 100644
--- a/lib/crypto/Makefile
+++ b/lib/crypto/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1999-2009. All Rights Reserved.
+# Copyright Ericsson AB 1999-2016. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -24,11 +24,7 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk
# Macros
#
-ifneq ($(findstring ose,$(TARGET)),ose)
SUB_DIRECTORIES = src c_src doc/src
-else
-SUB_DIRECTORIES = src doc/src
-endif
static_lib: SUB_DIRECTORIES = c_src
include vsn.mk
diff --git a/lib/crypto/c_src/Makefile.in b/lib/crypto/c_src/Makefile.in
index e66c0ca916..c62f25b3ee 100644
--- a/lib/crypto/c_src/Makefile.in
+++ b/lib/crypto/c_src/Makefile.in
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1999-2012. All Rights Reserved.
+# Copyright Ericsson AB 1999-2016. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -127,12 +127,7 @@ ALL_STATIC_CFLAGS = $(DED_STATIC_CFLAGS) $(INCLUDES)
_create_dirs := $(shell mkdir -p $(OBJDIR) $(LIBDIR))
-ifneq ($(findstring ose,$(TARGET)),ose)
debug opt valgrind: $(NIF_LIB) $(CALLBACK_LIB)
-else
-# Do not build dynamic files on OSE
-debug opt valgrind:
-endif
static_lib: $(NIF_ARCHIVE)
@@ -203,14 +198,12 @@ release_spec: opt
$(INSTALL_DIR) "$(RELSYSDIR)/priv/obj"
$(INSTALL_DIR) "$(RELSYSDIR)/priv/lib"
$(INSTALL_DATA) $(NIF_MAKEFILE) "$(RELSYSDIR)/priv/obj"
-ifneq ($(findstring ose,$(TARGET)),ose)
$(INSTALL_PROGRAM) $(CRYPTO_OBJS) "$(RELSYSDIR)/priv/obj"
$(INSTALL_PROGRAM) $(NIF_LIB) "$(RELSYSDIR)/priv/lib"
ifeq ($(DYNAMIC_CRYPTO_LIB),yes)
$(INSTALL_PROGRAM) $(CALLBACK_OBJS) "$(RELSYSDIR)/priv/obj"
$(INSTALL_PROGRAM) $(CALLBACK_LIB) "$(RELSYSDIR)/priv/lib"
endif
-endif
release_docs_spec:
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index 4966701e41..d4264335b6 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010-2014. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2017. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -37,7 +37,9 @@
#include <openssl/opensslconf.h>
#include <openssl/crypto.h>
+#ifndef OPENSSL_NO_DES
#include <openssl/des.h>
+#endif /* #ifndef OPENSSL_NO_DES */
/* #include <openssl/idea.h> This is not supported on the openssl OTP requires */
#include <openssl/dsa.h>
#include <openssl/rsa.h>
@@ -48,56 +50,82 @@
#include <openssl/ripemd.h>
#include <openssl/bn.h>
#include <openssl/objects.h>
-#include <openssl/rc4.h>
-#include <openssl/rc2.h>
+#ifndef OPENSSL_NO_RC4
+ #include <openssl/rc4.h>
+#endif /* OPENSSL_NO_RC4 */
+#ifndef OPENSSL_NO_RC2
+ #include <openssl/rc2.h>
+#endif
#include <openssl/blowfish.h>
#include <openssl/rand.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
-#if OPENSSL_VERSION_NUMBER >= 0x1000000fL
+/* Helper macro to construct a OPENSSL_VERSION_NUMBER.
+ * See openssl/opensslv.h
+ */
+#define OpenSSL_version(MAJ, MIN, FIX, P) \
+ ((((((((MAJ << 8) | MIN) << 8 ) | FIX) << 8) | (P-'a'+1)) << 4) | 0xf)
+
+#define OpenSSL_version_plain(MAJ, MIN, FIX) \
+ OpenSSL_version(MAJ,MIN,FIX,('a'-1))
+
+
+#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(1,0,0)
#include <openssl/modes.h>
#endif
#include "crypto_callback.h"
-#if OPENSSL_VERSION_NUMBER >= 0x00908000L && !defined(OPENSSL_NO_SHA224) && defined(NID_sha224)\
- && !defined(OPENSSL_NO_SHA256) /* disabled like this in my sha.h (?) */
+#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(0,9,8) \
+ && !defined(OPENSSL_NO_SHA224) && defined(NID_sha224) \
+ && !defined(OPENSSL_NO_SHA256) /* disabled like this in my sha.h (?) */
# define HAVE_SHA224
#endif
-#if OPENSSL_VERSION_NUMBER >= 0x00908000L && !defined(OPENSSL_NO_SHA256) && defined(NID_sha256)
+#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(0,9,8) \
+ && !defined(OPENSSL_NO_SHA256) && defined(NID_sha256)
# define HAVE_SHA256
#endif
-#if OPENSSL_VERSION_NUMBER >= 0x00908000L && !defined(OPENSSL_NO_SHA384) && defined(NID_sha384)\
- && !defined(OPENSSL_NO_SHA512) /* disabled like this in my sha.h (?) */
+#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(0,9,8) \
+ && !defined(OPENSSL_NO_SHA384) && defined(NID_sha384)\
+ && !defined(OPENSSL_NO_SHA512) /* disabled like this in my sha.h (?) */
# define HAVE_SHA384
#endif
-#if OPENSSL_VERSION_NUMBER >= 0x00908000L && !defined(OPENSSL_NO_SHA512) && defined(NID_sha512)
+#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(0,9,8) \
+ && !defined(OPENSSL_NO_SHA512) && defined(NID_sha512)
# define HAVE_SHA512
#endif
-#if OPENSSL_VERSION_NUMBER >= 0x0090705FL
+#if OPENSSL_VERSION_NUMBER >= OpenSSL_version(0,9,7,'e')
# define HAVE_DES_ede3_cfb_encrypt
#endif
-#if OPENSSL_VERSION_NUMBER >= 0x009080ffL \
+#if OPENSSL_VERSION_NUMBER >= OpenSSL_version(0,9,8,'o') \
&& !defined(OPENSSL_NO_EC) \
&& !defined(OPENSSL_NO_ECDH) \
&& !defined(OPENSSL_NO_ECDSA)
# define HAVE_EC
#endif
-#if OPENSSL_VERSION_NUMBER >= 0x0090803fL
+#if OPENSSL_VERSION_NUMBER >= OpenSSL_version(0,9,8,'c')
# define HAVE_AES_IGE
#endif
-#if OPENSSL_VERSION_NUMBER >= 0x1000100fL
+#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(1,0,1)
+# define HAVE_EVP_AES_CTR
# define HAVE_GCM
+# if OPENSSL_VERSION_NUMBER < OpenSSL_version(1,0,1,'d')
+# define HAVE_GCM_EVP_DECRYPT_BUG
+# endif
#endif
#if defined(NID_chacha20) && !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
# define HAVE_CHACHA20_POLY1305
#endif
+#if OPENSSL_VERSION_NUMBER <= OpenSSL_version(0,9,8,'l')
+# define HAVE_ECB_IVEC_BUG
+#endif
+
#if defined(HAVE_EC)
#include <openssl/ec.h>
#include <openssl/ecdh.h>
@@ -193,72 +221,32 @@ static void unload(ErlNifEnv* env, void* priv_data);
/* The NIFs: */
static ERL_NIF_TERM info_lib(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM algorithms(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM md5(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM md5_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM md5_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM md5_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM ripemd160(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM ripemd160_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM ripemd160_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM ripemd160_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha224_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha224_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha224_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha224_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha256_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha256_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha256_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha256_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha384_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha384_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha384_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha384_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha512_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha512_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha512_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha512_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM md4(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM md4_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM md4_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM md4_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM md5_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha224_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha256_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha384_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM sha512_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM hmac_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM hmac_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM hmac_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM des_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM des_cfb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM des_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM des_ede3_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM des_ede3_cfb_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM hash_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM hash_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM hash_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM hmac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM hmac_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM hmac_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM hmac_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM block_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM aes_cfb_8_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM aes_cfb_128_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM aes_cfb_128_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM aes_ige_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM aes_ctr_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM aes_ctr_stream_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM aes_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rand_bytes_1(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM strong_rand_bytes_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM rand_bytes_3(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM strong_rand_mpint_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rand_uniform_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM mod_exp_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM dss_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM aes_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM aes_ige_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM do_exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rc4_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rc4_set_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rc4_encrypt_with_state(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM rc2_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM dss_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rsa_public_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
@@ -270,10 +258,6 @@ static ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_T
static ERL_NIF_TERM srp_value_B_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM srp_user_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM srp_host_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM bf_cfb64_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM bf_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM bf_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM blowfish_ofb64_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM ecdsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
@@ -284,6 +268,9 @@ static ERL_NIF_TERM rand_seed_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
static ERL_NIF_TERM aes_gcm_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM aes_gcm_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+#ifdef HAVE_GCM_EVP_DECRYPT_BUG
+static ERL_NIF_TERM aes_gcm_decrypt_NO_EVP(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+#endif
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[]);
@@ -291,32 +278,7 @@ static ERL_NIF_TERM chacha20_poly1305_decrypt(ErlNifEnv* env, int argc, const ER
/* helpers */
static void init_algorithms_types(ErlNifEnv*);
static void init_digest_types(ErlNifEnv* env);
-static void hmac_md5(unsigned char *key, int klen,
- unsigned char *dbuf, int dlen,
- unsigned char *hmacbuf);
-static void hmac_sha1(unsigned char *key, int klen,
- unsigned char *dbuf, int dlen,
- unsigned char *hmacbuf);
-#ifdef HAVE_SHA224
-static void hmac_sha224(unsigned char *key, int klen,
- unsigned char *dbuf, int dlen,
- unsigned char *hmacbuf);
-#endif
-#ifdef HAVE_SHA256
-static void hmac_sha256(unsigned char *key, int klen,
- unsigned char *dbuf, int dlen,
- unsigned char *hmacbuf);
-#endif
-#ifdef HAVE_SHA384
-static void hmac_sha384(unsigned char *key, int klen,
- unsigned char *dbuf, int dlen,
- unsigned char *hmacbuf);
-#endif
-#ifdef HAVE_SHA512
-static void hmac_sha512(unsigned char *key, int klen,
- unsigned char *dbuf, int dlen,
- unsigned char *hmacbuf);
-#endif
+static void init_cipher_types(ErlNifEnv* env);
#ifdef HAVE_EC
static EC_KEY* ec_key_new(ErlNifEnv* env, ERL_NIF_TERM curve_arg);
static int term2point(ErlNifEnv* env, ERL_NIF_TERM term,
@@ -328,90 +290,48 @@ static int library_refc = 0; /* number of users of this dynamic library */
static ErlNifFunc nif_funcs[] = {
{"info_lib", 0, info_lib},
{"algorithms", 0, algorithms},
- {"md5", 1, md5},
- {"md5_init", 0, md5_init},
- {"md5_update", 2, md5_update},
- {"md5_final", 1, md5_final},
- {"ripemd160", 1, ripemd160},
- {"ripemd160_init", 0, ripemd160_init},
- {"ripemd160_update", 2, ripemd160_update},
- {"ripemd160_final", 1, ripemd160_final},
- {"sha", 1, sha},
- {"sha_init", 0, sha_init},
- {"sha_update", 2, sha_update},
- {"sha_final", 1, sha_final},
- {"sha224_nif", 1, sha224_nif},
- {"sha224_init_nif", 0, sha224_init_nif},
- {"sha224_update_nif", 2, sha224_update_nif},
- {"sha224_final_nif", 1, sha224_final_nif},
- {"sha256_nif", 1, sha256_nif},
- {"sha256_init_nif", 0, sha256_init_nif},
- {"sha256_update_nif", 2, sha256_update_nif},
- {"sha256_final_nif", 1, sha256_final_nif},
- {"sha384_nif", 1, sha384_nif},
- {"sha384_init_nif", 0, sha384_init_nif},
- {"sha384_update_nif", 2, sha384_update_nif},
- {"sha384_final_nif", 1, sha384_final_nif},
- {"sha512_nif", 1, sha512_nif},
- {"sha512_init_nif", 0, sha512_init_nif},
- {"sha512_update_nif", 2, sha512_update_nif},
- {"sha512_final_nif", 1, sha512_final_nif},
- {"md4", 1, md4},
- {"md4_init", 0, md4_init},
- {"md4_update", 2, md4_update},
- {"md4_final", 1, md4_final},
- {"md5_mac_n", 3, md5_mac_n},
- {"sha_mac_n", 3, sha_mac_n},
- {"sha224_mac_nif", 3, sha224_mac_nif},
- {"sha256_mac_nif", 3, sha256_mac_nif},
- {"sha384_mac_nif", 3, sha384_mac_nif},
- {"sha512_mac_nif", 3, sha512_mac_nif},
- {"hmac_init", 2, hmac_init},
- {"hmac_update", 2, hmac_update},
- {"hmac_final", 1, hmac_final},
- {"hmac_final_n", 2, hmac_final},
- {"des_cbc_crypt", 4, des_cbc_crypt},
- {"des_cfb_crypt", 4, des_cfb_crypt},
- {"des_ecb_crypt", 3, des_ecb_crypt},
- {"des_ede3_cbc_crypt", 6, des_ede3_cbc_crypt},
- {"des_ede3_cfb_crypt_nif", 6, des_ede3_cfb_crypt_nif},
- {"aes_cfb_8_crypt", 4, aes_cfb_8_crypt},
- {"aes_cfb_128_crypt", 4, aes_cfb_128_crypt},
+ {"hash_nif", 2, hash_nif},
+ {"hash_init_nif", 1, hash_init_nif},
+ {"hash_update_nif", 2, hash_update_nif},
+ {"hash_final_nif", 1, hash_final_nif},
+ {"hmac_nif", 3, hmac_nif},
+ {"hmac_nif", 4, hmac_nif},
+ {"hmac_init_nif", 2, hmac_init_nif},
+ {"hmac_update_nif", 2, hmac_update_nif},
+ {"hmac_final_nif", 1, hmac_final_nif},
+ {"hmac_final_nif", 2, hmac_final_nif},
+ {"block_crypt_nif", 5, block_crypt_nif},
+ {"block_crypt_nif", 4, block_crypt_nif},
+ {"aes_cfb_128_crypt_nif", 4, aes_cfb_128_crypt_nif},
+ {"aes_ige_crypt_nif", 4, aes_ige_crypt_nif},
+
{"aes_ctr_encrypt", 3, aes_ctr_encrypt},
{"aes_ctr_decrypt", 3, aes_ctr_encrypt},
+ {"aes_ctr_stream_init", 2, aes_ctr_stream_init},
{"aes_ctr_stream_encrypt", 2, aes_ctr_stream_encrypt},
{"aes_ctr_stream_decrypt", 2, aes_ctr_stream_encrypt},
- {"aes_ecb_crypt", 3, aes_ecb_crypt},
{"rand_bytes", 1, rand_bytes_1},
{"strong_rand_bytes_nif", 1, strong_rand_bytes_nif},
- {"rand_bytes", 3, rand_bytes_3},
{"strong_rand_mpint_nif", 3, strong_rand_mpint_nif},
{"rand_uniform_nif", 2, rand_uniform_nif},
{"mod_exp_nif", 4, mod_exp_nif},
{"dss_verify_nif", 4, dss_verify_nif},
{"rsa_verify_nif", 4, rsa_verify_nif},
- {"aes_cbc_crypt", 4, aes_cbc_crypt},
- {"aes_ige_crypt_nif", 4, aes_ige_crypt_nif},
{"do_exor", 2, do_exor},
{"rc4_encrypt", 2, rc4_encrypt},
{"rc4_set_key", 1, rc4_set_key},
{"rc4_encrypt_with_state", 2, rc4_encrypt_with_state},
- {"rc2_cbc_crypt", 4, rc2_cbc_crypt},
{"rsa_sign_nif", 3, rsa_sign_nif},
{"dss_sign_nif", 3, dss_sign_nif},
{"rsa_public_crypt", 4, rsa_public_crypt},
{"rsa_private_crypt", 4, rsa_private_crypt},
{"dh_generate_parameters_nif", 2, dh_generate_parameters_nif},
{"dh_check", 1, dh_check},
- {"dh_generate_key_nif", 3, dh_generate_key_nif},
+ {"dh_generate_key_nif", 4, dh_generate_key_nif},
{"dh_compute_key_nif", 3, dh_compute_key_nif},
{"srp_value_B_nif", 5, srp_value_B_nif},
{"srp_user_secret_nif", 7, srp_user_secret_nif},
{"srp_host_secret_nif", 5, srp_host_secret_nif},
- {"bf_cfb64_crypt", 4, bf_cfb64_crypt},
- {"bf_cbc_crypt", 4, bf_cbc_crypt},
- {"bf_ecb_crypt", 3, bf_ecb_crypt},
- {"blowfish_ofb64_encrypt", 3, blowfish_ofb64_encrypt},
{"ec_key_generate", 2, ec_key_generate},
{"ecdsa_sign_nif", 4, ecdsa_sign_nif},
@@ -420,7 +340,7 @@ static ErlNifFunc nif_funcs[] = {
{"rand_seed_nif", 1, rand_seed_nif},
- {"aes_gcm_encrypt", 4, aes_gcm_encrypt},
+ {"aes_gcm_encrypt", 5, aes_gcm_encrypt},
{"aes_gcm_decrypt", 5, aes_gcm_decrypt},
{"chacha20_poly1305_encrypt", 4, chacha20_poly1305_encrypt},
@@ -432,37 +352,14 @@ static ErlNifFunc nif_funcs[] = {
ERL_NIF_INIT(crypto,nif_funcs,load,NULL,upgrade,unload)
-#define MD5_CTX_LEN (sizeof(MD5_CTX))
-#define MD5_LEN 16
-#define MD5_LEN_96 12
-#define MD4_CTX_LEN (sizeof(MD4_CTX))
-#define MD4_LEN 16
+#define MD5_CTX_LEN (sizeof(MD5_CTX))
+#define MD4_CTX_LEN (sizeof(MD4_CTX))
#define RIPEMD160_CTX_LEN (sizeof(RIPEMD160_CTX))
-#define RIPEMD160_LEN 20
-#define SHA_CTX_LEN (sizeof(SHA_CTX))
-#define SHA_LEN 20
-#define SHA_LEN_96 12
-#define SHA224_LEN (224/8)
-#define SHA256_LEN (256/8)
-#define SHA384_LEN (384/8)
-#define SHA512_LEN (512/8)
-#define HMAC_INT_LEN 64
-#define HMAC_INT2_LEN 128
-
-#define HMAC_IPAD 0x36
-#define HMAC_OPAD 0x5c
static ERL_NIF_TERM atom_true;
static ERL_NIF_TERM atom_false;
static ERL_NIF_TERM atom_sha;
-static ERL_NIF_TERM atom_sha224;
-static ERL_NIF_TERM atom_sha256;
-static ERL_NIF_TERM atom_sha384;
-static ERL_NIF_TERM atom_sha512;
-static ERL_NIF_TERM atom_md5;
-static ERL_NIF_TERM atom_md4;
-static ERL_NIF_TERM atom_ripemd160;
static ERL_NIF_TERM atom_error;
static ERL_NIF_TERM atom_rsa_pkcs1_padding;
static ERL_NIF_TERM atom_rsa_pkcs1_oaep_padding;
@@ -489,6 +386,14 @@ static ERL_NIF_TERM atom_ppbasis;
static ERL_NIF_TERM atom_onbasis;
#endif
+static ERL_NIF_TERM atom_aes_cfb8;
+static ERL_NIF_TERM atom_aes_cfb128;
+#ifdef HAVE_ECB_IVEC_BUG
+static ERL_NIF_TERM atom_aes_ecb;
+static ERL_NIF_TERM atom_des_ecb;
+static ERL_NIF_TERM atom_blowfish_ecb;
+#endif
+
static ErlNifResourceType* hmac_context_rtype;
struct hmac_context
{
@@ -498,6 +403,120 @@ struct hmac_context
};
static void hmac_context_dtor(ErlNifEnv* env, struct hmac_context*);
+struct digest_type_t {
+ union {
+ const char* str; /* before init, NULL for end-of-table */
+ ERL_NIF_TERM atom; /* after init, 'false' for end-of-table */
+ }type;
+ union {
+ const EVP_MD* (*funcp)(void); /* before init, NULL if notsup */
+ const EVP_MD* p; /* after init, NULL if notsup */
+ }md;
+};
+
+struct digest_type_t digest_types[] =
+{
+ {{"md4"}, {&EVP_md4}},
+ {{"md5"}, {&EVP_md5}},
+ {{"ripemd160"}, {&EVP_ripemd160}},
+ {{"sha"}, {&EVP_sha1}},
+ {{"sha224"},
+#ifdef HAVE_SHA224
+ {&EVP_sha224}
+#else
+ {NULL}
+#endif
+ },
+ {{"sha256"},
+#ifdef HAVE_SHA256
+ {&EVP_sha256}
+#else
+ {NULL}
+#endif
+ },
+ {{"sha384"},
+#ifdef HAVE_SHA384
+ {&EVP_sha384}
+#else
+ {NULL}
+#endif
+ },
+ {{"sha512"},
+#ifdef HAVE_SHA512
+ {&EVP_sha512}
+#else
+ {NULL}
+#endif
+ },
+ {{NULL}}
+};
+
+static struct digest_type_t* get_digest_type(ERL_NIF_TERM type);
+
+struct cipher_type_t {
+ union {
+ const char* str; /* before init */
+ ERL_NIF_TERM atom; /* after init */
+ }type;
+ union {
+ const EVP_CIPHER* (*funcp)(void); /* before init, NULL if notsup */
+ const EVP_CIPHER* p; /* after init, NULL if notsup */
+ }cipher;
+ const size_t key_len; /* != 0 to also match on key_len */
+};
+
+#ifdef OPENSSL_NO_DES
+#define COND_NO_DES_PTR(Ptr) (NULL)
+#else
+#define COND_NO_DES_PTR(Ptr) (Ptr)
+#endif
+
+struct cipher_type_t cipher_types[] =
+{
+ {{"rc2_cbc"},
+#ifndef OPENSSL_NO_RC2
+ {&EVP_rc2_cbc}
+#else
+ {NULL}
+#endif
+ },
+ {{"des_cbc"}, {COND_NO_DES_PTR(&EVP_des_cbc)}},
+ {{"des_cfb"}, {COND_NO_DES_PTR(&EVP_des_cfb8)}},
+ {{"des_ecb"}, {COND_NO_DES_PTR(&EVP_des_ecb)}},
+ {{"des_ede3_cbc"}, {COND_NO_DES_PTR(&EVP_des_ede3_cbc)}},
+ {{"des_ede3_cbf"}, /* Misspelled, retained */
+#ifdef HAVE_DES_ede3_cfb_encrypt
+ {COND_NO_DES_PTR(&EVP_des_ede3_cfb8)}
+#else
+ {NULL}
+#endif
+ },
+ {{"des_ede3_cfb"},
+#ifdef HAVE_DES_ede3_cfb_encrypt
+ {COND_NO_DES_PTR(&EVP_des_ede3_cfb8)}
+#else
+ {NULL}
+#endif
+ },
+ {{"blowfish_cbc"}, {&EVP_bf_cbc}},
+ {{"blowfish_cfb64"}, {&EVP_bf_cfb64}},
+ {{"blowfish_ofb64"}, {&EVP_bf_ofb}},
+ {{"blowfish_ecb"}, {&EVP_bf_ecb}},
+ {{"aes_cbc"}, {&EVP_aes_128_cbc}, 16},
+ {{"aes_cbc"}, {&EVP_aes_192_cbc}, 24},
+ {{"aes_cbc"}, {&EVP_aes_256_cbc}, 32},
+ {{"aes_cbc128"}, {&EVP_aes_128_cbc}},
+ {{"aes_cbc256"}, {&EVP_aes_256_cbc}},
+ {{"aes_cfb8"}, {&EVP_aes_128_cfb8}},
+ {{"aes_cfb128"}, {&EVP_aes_128_cfb128}},
+ {{"aes_ecb"}, {&EVP_aes_128_ecb}, 16},
+ {{"aes_ecb"}, {&EVP_aes_192_ecb}, 24},
+ {{"aes_ecb"}, {&EVP_aes_256_ecb}, 32},
+ {{NULL}}
+};
+
+static struct cipher_type_t* get_cipher_type(ERL_NIF_TERM type, size_t key_len);
+
/*
#define PRINTF_ERR0(FMT) enif_fprintf(stderr, FMT "\n")
#define PRINTF_ERR1(FMT, A1) enif_fprintf(stderr, FMT "\n", A1)
@@ -507,47 +526,21 @@ static void hmac_context_dtor(ErlNifEnv* env, struct hmac_context*);
#define PRINTF_ERR1(FMT,A1)
#define PRINTF_ERR2(FMT,A1,A2)
-#ifdef __OSE__
-
-/* For crypto on OSE we have to initialize the crypto library on each
- process that uses it. So since we do not know which scheduler is going
- to execute the nif we have to check before each nif call that we have
- initialized crypto in that process. */
-
-#include "ose.h"
-#include "openssl/osessl.h"
-
-static ErlNifTSDKey crypto_init_key;
-static int check_ose_crypto(void);
-static int init_ose_crypto(void);
-
-static int check_ose_crypto() {
- int key = (int)enif_tsd_get(crypto_init_key);
- if (!key) {
- if (!CRYPTO_OSE5_init()) {
- PRINTF_ERR0("CRYPTO: Call to CRYPTO_OSE5_init failed");
- return 0;
- }
- enif_tsd_set(crypto_init_key,1);
- }
- return 1;
+#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(1,0,0)
+/* Define resource types for OpenSSL context structures. */
+static ErlNifResourceType* evp_md_ctx_rtype;
+static void evp_md_ctx_dtor(ErlNifEnv* env, EVP_MD_CTX* ctx) {
+ EVP_MD_CTX_cleanup(ctx);
}
+#endif
-static int init_ose_crypto() {
- /* Crypto nif upgrade does not work on OSE so no need to
- destroy this key */
- enif_tsd_key_create("crypto_init_key", &crypto_init_key);
- return check_ose_crypto();
+#ifdef HAVE_EVP_AES_CTR
+static ErlNifResourceType* evp_cipher_ctx_rtype;
+static void evp_cipher_ctx_dtor(ErlNifEnv* env, EVP_CIPHER_CTX* ctx) {
+ EVP_CIPHER_CTX_cleanup(ctx);
}
-
-#define INIT_OSE_CRYPTO() init_ose_crypto()
-#define CHECK_OSE_CRYPTO() check_ose_crypto()
-#else
-#define INIT_OSE_CRYPTO() 1
-#define CHECK_OSE_CRYPTO()
#endif
-
static int verify_lib_version(void)
{
const unsigned long libv = SSLeay();
@@ -563,7 +556,6 @@ static int verify_lib_version(void)
return 1;
}
-
#ifdef HAVE_DYNAMIC_CRYPTO_LIB
# if defined(DEBUG)
@@ -597,9 +589,11 @@ static void error_handler(void* null, const char* errstr)
}
#endif /* HAVE_DYNAMIC_CRYPTO_LIB */
-static int init(ErlNifEnv* env, ERL_NIF_TERM load_info)
+static int initialize(ErlNifEnv* env, ERL_NIF_TERM load_info)
{
+#ifdef OPENSSL_THREADS
ErlNifSysInfo sys_info;
+#endif
get_crypto_callbacks_t* funcp;
struct crypto_callbacks* ccb;
int nlocks = 0;
@@ -609,11 +603,8 @@ static int init(ErlNifEnv* env, ERL_NIF_TERM load_info)
ErlNifBinary lib_bin;
char lib_buf[1000];
- if (!INIT_OSE_CRYPTO())
- return 0;
-
if (!verify_lib_version())
- return 0;
+ return __LINE__;
/* load_info: {301, <<"/full/path/of/this/library">>} */
if (!enif_get_tuple(env, load_info, &tpl_arity, &tpl_array)
@@ -623,7 +614,7 @@ static int init(ErlNifEnv* env, ERL_NIF_TERM load_info)
|| !enif_inspect_binary(env, tpl_array[1], &lib_bin)) {
PRINTF_ERR1("CRYPTO: Invalid load_info '%T'", load_info);
- return 0;
+ return __LINE__;
}
hmac_context_rtype = enif_open_resource_type(env, NULL, "hmac_context",
@@ -632,26 +623,38 @@ static int init(ErlNifEnv* env, ERL_NIF_TERM load_info)
NULL);
if (!hmac_context_rtype) {
PRINTF_ERR0("CRYPTO: Could not open resource type 'hmac_context'");
- return 0;
+ return __LINE__;
}
-
+#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(1,0,0)
+ evp_md_ctx_rtype = enif_open_resource_type(env, NULL, "EVP_MD_CTX",
+ (ErlNifResourceDtor*) evp_md_ctx_dtor,
+ ERL_NIF_RT_CREATE|ERL_NIF_RT_TAKEOVER,
+ NULL);
+ if (!evp_md_ctx_rtype) {
+ PRINTF_ERR0("CRYPTO: Could not open resource type 'EVP_MD_CTX'");
+ return __LINE__;
+ }
+#endif
+#ifdef HAVE_EVP_AES_CTR
+ evp_cipher_ctx_rtype = enif_open_resource_type(env, NULL, "EVP_CIPHER_CTX",
+ (ErlNifResourceDtor*) evp_cipher_ctx_dtor,
+ ERL_NIF_RT_CREATE|ERL_NIF_RT_TAKEOVER,
+ NULL);
+ if (!evp_cipher_ctx_rtype) {
+ PRINTF_ERR0("CRYPTO: Could not open resource type 'EVP_CIPHER_CTX'");
+ return __LINE__;
+ }
+#endif
if (library_refc > 0) {
/* Repeated loading of this library (module upgrade).
* Atoms and callbacks are already set, we are done.
*/
- return 1;
+ return 0;
}
- atom_true = enif_make_atom(env,"true");
+ atom_true = enif_make_atom(env,"true");
atom_false = enif_make_atom(env,"false");
atom_sha = enif_make_atom(env,"sha");
- atom_sha224 = enif_make_atom(env,"sha224");
- atom_sha256 = enif_make_atom(env,"sha256");
- atom_sha384 = enif_make_atom(env,"sha384");
- atom_sha512 = enif_make_atom(env,"sha512");
- atom_md4 = enif_make_atom(env,"md4");
- atom_md5 = enif_make_atom(env,"md5");
- atom_ripemd160 = enif_make_atom(env,"ripemd160");
atom_error = enif_make_atom(env,"error");
atom_rsa_pkcs1_padding = enif_make_atom(env,"rsa_pkcs1_padding");
atom_rsa_pkcs1_oaep_padding = enif_make_atom(env,"rsa_pkcs1_oaep_padding");
@@ -676,22 +679,30 @@ static int init(ErlNifEnv* env, ERL_NIF_TERM load_info)
atom_ppbasis = enif_make_atom(env,"ppbasis");
atom_onbasis = enif_make_atom(env,"onbasis");
#endif
+ atom_aes_cfb8 = enif_make_atom(env, "aes_cfb8");
+ atom_aes_cfb128 = enif_make_atom(env, "aes_cfb128");
+#ifdef HAVE_ECB_IVEC_BUG
+ atom_aes_ecb = enif_make_atom(env, "aes_ecb");
+ atom_des_ecb = enif_make_atom(env, "des_ecb");
+ atom_blowfish_ecb = enif_make_atom(env, "blowfish_ecb");
+#endif
init_digest_types(env);
+ init_cipher_types(env);
init_algorithms_types(env);
#ifdef HAVE_DYNAMIC_CRYPTO_LIB
{
void* handle;
if (!change_basename(&lib_bin, lib_buf, sizeof(lib_buf), crypto_callback_name)) {
- return 0;
+ return __LINE__;
}
if (!(handle = enif_dlopen(lib_buf, &error_handler, NULL))) {
- return 0;
+ return __LINE__;
}
if (!(funcp = (get_crypto_callbacks_t*) enif_dlsym(handle, "get_crypto_callbacks",
&error_handler, NULL))) {
- return 0;
+ return __LINE__;
}
}
#else /* !HAVE_DYNAMIC_CRYPTO_LIB */
@@ -710,7 +721,7 @@ static int init(ErlNifEnv* env, ERL_NIF_TERM load_info)
if (!ccb || ccb->sizeof_me != sizeof(*ccb)) {
PRINTF_ERR0("Invalid 'crypto_callbacks'");
- return 0;
+ return __LINE__;
}
CRYPTO_set_mem_functions(ccb->crypto_alloc, ccb->crypto_realloc, ccb->crypto_free);
@@ -724,13 +735,14 @@ static int init(ErlNifEnv* env, ERL_NIF_TERM load_info)
CRYPTO_set_dynlock_destroy_callback(ccb->dyn_destroy_function);
}
#endif /* OPENSSL_THREADS */
- return 1;
+ return 0;
}
static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
{
- if (!init(env, load_info)) {
- return -1;
+ int errline = initialize(env, load_info);
+ if (errline) {
+ return errline;
}
*priv_data = NULL;
@@ -741,14 +753,16 @@ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data,
ERL_NIF_TERM load_info)
{
+ int errline;
if (*old_priv_data != NULL) {
- return -1; /* Don't know how to do that */
+ return __LINE__; /* Don't know how to do that */
}
if (*priv_data != NULL) {
- return -1; /* Don't know how to do that */
+ return __LINE__; /* Don't know how to do that */
}
- if (!init(env, load_info)) {
- return -1;
+ errline = initialize(env, load_info);
+ if (errline) {
+ return errline;
}
library_refc++;
return 0;
@@ -762,46 +776,77 @@ static void unload(ErlNifEnv* env, void* priv_data)
static int algo_hash_cnt;
static ERL_NIF_TERM algo_hash[8]; /* increase when extending the list */
static int algo_pubkey_cnt;
-static ERL_NIF_TERM algo_pubkey[3]; /* increase when extending the list */
+static ERL_NIF_TERM algo_pubkey[7]; /* increase when extending the list */
static int algo_cipher_cnt;
-static ERL_NIF_TERM algo_cipher[4]; /* increase when extending the list */
+static ERL_NIF_TERM algo_cipher[23]; /* increase when extending the list */
static void init_algorithms_types(ErlNifEnv* env)
{
algo_hash_cnt = 0;
- algo_hash[algo_hash_cnt++] = atom_md4;
- algo_hash[algo_hash_cnt++] = atom_md5;
algo_hash[algo_hash_cnt++] = atom_sha;
- algo_hash[algo_hash_cnt++] = atom_ripemd160;
#ifdef HAVE_SHA224
- algo_hash[algo_hash_cnt++] = atom_sha224;
+ algo_hash[algo_hash_cnt++] = enif_make_atom(env, "sha224");
#endif
#ifdef HAVE_SHA256
- algo_hash[algo_hash_cnt++] = atom_sha256;
+ algo_hash[algo_hash_cnt++] = enif_make_atom(env, "sha256");
#endif
#ifdef HAVE_SHA384
- algo_hash[algo_hash_cnt++] = atom_sha384;
+ algo_hash[algo_hash_cnt++] = enif_make_atom(env, "sha384");
#endif
#ifdef HAVE_SHA512
- algo_hash[algo_hash_cnt++] = atom_sha512;
+ algo_hash[algo_hash_cnt++] = enif_make_atom(env, "sha512");
#endif
+ algo_hash[algo_hash_cnt++] = enif_make_atom(env, "md4");
+ algo_hash[algo_hash_cnt++] = enif_make_atom(env, "md5");
+ algo_hash[algo_hash_cnt++] = enif_make_atom(env, "ripemd160");
algo_pubkey_cnt = 0;
+ algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "rsa");
+ algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "dss");
+ algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "dh");
#if defined(HAVE_EC)
#if !defined(OPENSSL_NO_EC2M)
- algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env,"ec_gf2m");
+ algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "ec_gf2m");
#endif
- algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env,"ecdsa");
- algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env,"ecdh");
+ algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "ecdsa");
+ algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "ecdh");
#endif
+ algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "srp");
algo_cipher_cnt = 0;
+#ifndef OPENSSL_NO_DES
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "des3_cbc");
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "des_ede3");
#ifdef HAVE_DES_ede3_cfb_encrypt
algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "des3_cbf");
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "des3_cfb");
+#endif
#endif
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_cbc");
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_cbc128");
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_cfb8");
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_cfb128");
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_cbc256");
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_ctr");
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_ecb");
#ifdef HAVE_AES_IGE
algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"aes_ige256");
#endif
+#ifndef OPENSSL_NO_DES
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"des_cbc");
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"des_cfb");
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"des_ecb");
+#endif
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"blowfish_cbc");
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"blowfish_cfb64");
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"blowfish_ofb64");
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"blowfish_ecb");
+#ifndef OPENSSL_NO_RC2
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"rc2_cbc");
+#endif
+#ifndef OPENSSL_NO_RC4
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"rc4");
+#endif
#if defined(HAVE_GCM)
algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"aes_gcm");
#endif
@@ -816,10 +861,13 @@ static void init_algorithms_types(ErlNifEnv* env)
static ERL_NIF_TERM algorithms(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
+ int hash_cnt = algo_hash_cnt;
+ int pubkey_cnt = algo_pubkey_cnt;
+ int cipher_cnt = algo_cipher_cnt;
return enif_make_tuple3(env,
- enif_make_list_from_array(env, algo_hash, algo_hash_cnt),
- enif_make_list_from_array(env, algo_pubkey, algo_pubkey_cnt),
- enif_make_list_from_array(env, algo_cipher, algo_cipher_cnt));
+ enif_make_list_from_array(env, algo_hash, hash_cnt),
+ enif_make_list_from_array(env, algo_pubkey, pubkey_cnt),
+ enif_make_list_from_array(env, algo_cipher, cipher_cnt));
}
static ERL_NIF_TERM info_lib(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
@@ -849,601 +897,392 @@ static ERL_NIF_TERM info_lib(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]
ver_term));
}
-static ERL_NIF_TERM md5(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Data) */
- ErlNifBinary ibin;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
+static ERL_NIF_TERM make_badarg_maybe(ErlNifEnv* env)
+{
+ ERL_NIF_TERM reason;
+ if (enif_has_pending_exception(env, &reason))
+ return reason; /* dummy return value ignored */
+ else
return enif_make_badarg(env);
- }
- MD5((unsigned char *) ibin.data, ibin.size,
- enif_make_new_binary(env,MD5_LEN, &ret));
- CONSUME_REDS(env,ibin);
- return ret;
-}
-static ERL_NIF_TERM md5_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* () */
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- MD5_Init((MD5_CTX *) enif_make_new_binary(env, MD5_CTX_LEN, &ret));
- return ret;
}
-static ERL_NIF_TERM md5_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context, Data) */
- MD5_CTX* new_ctx;
- ErlNifBinary ctx_bin, data_bin;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_binary(env, argv[0], &ctx_bin)
- || ctx_bin.size != MD5_CTX_LEN
- || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
+
+static ERL_NIF_TERM hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Type, Data) */
+ struct digest_type_t *digp = NULL;
+ const EVP_MD *md;
+ ErlNifBinary data;
+ ERL_NIF_TERM ret;
+ unsigned ret_size;
+
+ digp = get_digest_type(argv[0]);
+ if (!digp ||
+ !enif_inspect_iolist_as_binary(env, argv[1], &data)) {
return enif_make_badarg(env);
}
- new_ctx = (MD5_CTX*) enif_make_new_binary(env,MD5_CTX_LEN, &ret);
- memcpy(new_ctx, ctx_bin.data, MD5_CTX_LEN);
- MD5_Update(new_ctx, data_bin.data, data_bin.size);
- CONSUME_REDS(env,data_bin);
- return ret;
-}
-static ERL_NIF_TERM md5_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context) */
- ErlNifBinary ctx_bin;
- MD5_CTX ctx_clone;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != MD5_CTX_LEN) {
- return enif_make_badarg(env);
+ md = digp->md.p;
+ if (!md) {
+ return atom_notsup;
}
- memcpy(&ctx_clone, ctx_bin.data, MD5_CTX_LEN); /* writable */
- MD5_Final(enif_make_new_binary(env, MD5_LEN, &ret), &ctx_clone);
- return ret;
-}
-static ERL_NIF_TERM ripemd160(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Data) */
- ErlNifBinary ibin;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
- return enif_make_badarg(env);
+ ret_size = (unsigned)EVP_MD_size(md);
+ ASSERT(0 < ret_size && ret_size <= EVP_MAX_MD_SIZE);
+ if (!EVP_Digest(data.data, data.size,
+ enif_make_new_binary(env, ret_size, &ret), &ret_size,
+ md, NULL)) {
+ return atom_notsup;
}
- RIPEMD160((unsigned char *) ibin.data, ibin.size,
- enif_make_new_binary(env,RIPEMD160_LEN, &ret));
- CONSUME_REDS(env,ibin);
- return ret;
-}
-static ERL_NIF_TERM ripemd160_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* () */
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- RIPEMD160_Init((RIPEMD160_CTX *) enif_make_new_binary(env, RIPEMD160_CTX_LEN, &ret));
+ ASSERT(ret_size == (unsigned)EVP_MD_size(md));
+
+ CONSUME_REDS(env, data);
return ret;
}
-static ERL_NIF_TERM ripemd160_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context, Data) */
- RIPEMD160_CTX* new_ctx;
- ErlNifBinary ctx_bin, data_bin;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_binary(env, argv[0], &ctx_bin)
- || ctx_bin.size != RIPEMD160_CTX_LEN
- || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
+
+#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(1,0,0)
+
+static ERL_NIF_TERM hash_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Type) */
+ struct digest_type_t *digp = NULL;
+ EVP_MD_CTX *ctx;
+ ERL_NIF_TERM ret;
+
+ digp = get_digest_type(argv[0]);
+ if (!digp) {
return enif_make_badarg(env);
}
- new_ctx = (RIPEMD160_CTX*) enif_make_new_binary(env,RIPEMD160_CTX_LEN, &ret);
- memcpy(new_ctx, ctx_bin.data, RIPEMD160_CTX_LEN);
- RIPEMD160_Update(new_ctx, data_bin.data, data_bin.size);
- CONSUME_REDS(env, data_bin);
- return ret;
-}
-static ERL_NIF_TERM ripemd160_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context) */
- ErlNifBinary ctx_bin;
- RIPEMD160_CTX ctx_clone;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != RIPEMD160_CTX_LEN) {
- return enif_make_badarg(env);
+ if (!digp->md.p) {
+ return atom_notsup;
}
- memcpy(&ctx_clone, ctx_bin.data, RIPEMD160_CTX_LEN); /* writable */
- RIPEMD160_Final(enif_make_new_binary(env, RIPEMD160_LEN, &ret), &ctx_clone);
- return ret;
-}
-
-static ERL_NIF_TERM sha(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Data) */
- ErlNifBinary ibin;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
- return enif_make_badarg(env);
+ ctx = enif_alloc_resource(evp_md_ctx_rtype, sizeof(EVP_MD_CTX));
+ if (!EVP_DigestInit(ctx, digp->md.p)) {
+ enif_release_resource(ctx);
+ return atom_notsup;
}
- SHA1((unsigned char *) ibin.data, ibin.size,
- enif_make_new_binary(env,SHA_LEN, &ret));
- CONSUME_REDS(env,ibin);
- return ret;
-}
-static ERL_NIF_TERM sha_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* () */
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- SHA1_Init((SHA_CTX *) enif_make_new_binary(env, SHA_CTX_LEN, &ret));
+ ret = enif_make_resource(env, ctx);
+ enif_release_resource(ctx);
return ret;
}
-static ERL_NIF_TERM sha_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+static ERL_NIF_TERM hash_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Context, Data) */
- SHA_CTX* new_ctx;
- ErlNifBinary ctx_bin, data_bin;
+ EVP_MD_CTX *ctx, *new_ctx;
+ ErlNifBinary data;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != SHA_CTX_LEN
- || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
- return enif_make_badarg(env);
+
+ if (!enif_get_resource(env, argv[0], evp_md_ctx_rtype, (void**)&ctx) ||
+ !enif_inspect_iolist_as_binary(env, argv[1], &data)) {
+ return enif_make_badarg(env);
}
- new_ctx = (SHA_CTX*) enif_make_new_binary(env,SHA_CTX_LEN, &ret);
- memcpy(new_ctx, ctx_bin.data, SHA_CTX_LEN);
- SHA1_Update(new_ctx, data_bin.data, data_bin.size);
- CONSUME_REDS(env,data_bin);
+
+ new_ctx = enif_alloc_resource(evp_md_ctx_rtype, sizeof(EVP_MD_CTX));
+ if (!EVP_MD_CTX_copy(new_ctx, ctx) ||
+ !EVP_DigestUpdate(new_ctx, data.data, data.size)) {
+ enif_release_resource(new_ctx);
+ return atom_notsup;
+ }
+
+ ret = enif_make_resource(env, new_ctx);
+ enif_release_resource(new_ctx);
+ CONSUME_REDS(env, data);
return ret;
}
-static ERL_NIF_TERM sha_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+static ERL_NIF_TERM hash_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Context) */
- ErlNifBinary ctx_bin;
- SHA_CTX ctx_clone;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != SHA_CTX_LEN) {
- return enif_make_badarg(env);
+ EVP_MD_CTX *ctx, new_ctx;
+ ERL_NIF_TERM ret;
+ unsigned ret_size;
+
+ if (!enif_get_resource(env, argv[0], evp_md_ctx_rtype, (void**)&ctx)) {
+ return enif_make_badarg(env);
}
- memcpy(&ctx_clone, ctx_bin.data, SHA_CTX_LEN); /* writable */
- SHA1_Final(enif_make_new_binary(env, SHA_LEN, &ret), &ctx_clone);
- return ret;
-}
-static ERL_NIF_TERM sha224_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Data) */
-#ifdef HAVE_SHA224
- ErlNifBinary ibin;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
- return enif_make_badarg(env);
+ ret_size = (unsigned)EVP_MD_CTX_size(ctx);
+ ASSERT(0 < ret_size && ret_size <= EVP_MAX_MD_SIZE);
+
+ if (!EVP_MD_CTX_copy(&new_ctx, ctx) ||
+ !EVP_DigestFinal(&new_ctx,
+ enif_make_new_binary(env, ret_size, &ret),
+ &ret_size)) {
+ return atom_notsup;
}
- SHA224((unsigned char *) ibin.data, ibin.size,
- enif_make_new_binary(env,SHA224_LEN, &ret));
- CONSUME_REDS(env,ibin);
- return ret;
-#else
- return atom_notsup;
-#endif
-}
-static ERL_NIF_TERM sha224_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* () */
-#ifdef HAVE_SHA224
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- SHA224_Init((SHA256_CTX *) enif_make_new_binary(env, sizeof(SHA256_CTX), &ret));
+ ASSERT(ret_size == (unsigned)EVP_MD_CTX_size(ctx));
+
return ret;
-#else
- return atom_notsup;
-#endif
}
-static ERL_NIF_TERM sha224_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context, Data) */
-#ifdef HAVE_SHA224
- SHA256_CTX* new_ctx;
- ErlNifBinary ctx_bin, data_bin;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA256_CTX)
- || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
+
+#else /* if OPENSSL_VERSION_NUMBER < 1.0 */
+
+static ERL_NIF_TERM hash_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Type) */
+ typedef int (*init_fun)(unsigned char*);
+ struct digest_type_t *digp = NULL;
+ ERL_NIF_TERM ctx;
+ size_t ctx_size = 0;
+ init_fun ctx_init = 0;
+
+ digp = get_digest_type(argv[0]);
+ if (!digp) {
return enif_make_badarg(env);
}
- new_ctx = (SHA256_CTX*) enif_make_new_binary(env,sizeof(SHA256_CTX), &ret);
- memcpy(new_ctx, ctx_bin.data, sizeof(SHA256_CTX));
- SHA224_Update(new_ctx, data_bin.data, data_bin.size);
- CONSUME_REDS(env,data_bin);
- return ret;
-#else
- return atom_notsup;
-#endif
-}
-static ERL_NIF_TERM sha224_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context) */
-#ifdef HAVE_SHA224
- ErlNifBinary ctx_bin;
- SHA256_CTX ctx_clone;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA256_CTX)) {
- return enif_make_badarg(env);
+ if (!digp->md.p) {
+ return atom_notsup;
}
- memcpy(&ctx_clone, ctx_bin.data, sizeof(SHA256_CTX)); /* writable */
- SHA224_Final(enif_make_new_binary(env, SHA224_LEN, &ret), &ctx_clone);
- return ret;
-#else
- return atom_notsup;
-#endif
-}
-static ERL_NIF_TERM sha256_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Data) */
-#ifdef HAVE_SHA256
- ErlNifBinary ibin;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
- return enif_make_badarg(env);
- }
- SHA256((unsigned char *) ibin.data, ibin.size,
- enif_make_new_binary(env,SHA256_LEN, &ret));
- CONSUME_REDS(env,ibin);
- return ret;
-#else
- return atom_notsup;
+ switch (EVP_MD_type(digp->md.p))
+ {
+ case NID_md4:
+ ctx_size = MD4_CTX_LEN;
+ ctx_init = (init_fun)(&MD4_Init);
+ break;
+ case NID_md5:
+ ctx_size = MD5_CTX_LEN;
+ ctx_init = (init_fun)(&MD5_Init);
+ break;
+ case NID_ripemd160:
+ ctx_size = RIPEMD160_CTX_LEN;
+ ctx_init = (init_fun)(&RIPEMD160_Init);
+ break;
+ case NID_sha1:
+ ctx_size = sizeof(SHA_CTX);
+ ctx_init = (init_fun)(&SHA1_Init);
+ break;
+#ifdef HAVE_SHA224
+ case NID_sha224:
+ ctx_size = sizeof(SHA256_CTX);
+ ctx_init = (init_fun)(&SHA224_Init);
+ break;
#endif
-}
-static ERL_NIF_TERM sha256_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* () */
#ifdef HAVE_SHA256
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- SHA256_Init((SHA256_CTX *) enif_make_new_binary(env, sizeof(SHA256_CTX), &ret));
- return ret;
-#else
- return atom_notsup;
+ case NID_sha256:
+ ctx_size = sizeof(SHA256_CTX);
+ ctx_init = (init_fun)(&SHA256_Init);
+ break;
#endif
-}
-static ERL_NIF_TERM sha256_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context, Data) */
-#ifdef HAVE_SHA256
- SHA256_CTX* new_ctx;
- ErlNifBinary ctx_bin, data_bin;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA256_CTX)
- || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
- return enif_make_badarg(env);
+#ifdef HAVE_SHA384
+ case NID_sha384:
+ ctx_size = sizeof(SHA512_CTX);
+ ctx_init = (init_fun)(&SHA384_Init);
+ break;
+#endif
+#ifdef HAVE_SHA512
+ case NID_sha512:
+ ctx_size = sizeof(SHA512_CTX);
+ ctx_init = (init_fun)(&SHA512_Init);
+ break;
+#endif
+ default:
+ return atom_notsup;
+ }
+ ASSERT(ctx_size);
+ ASSERT(ctx_init);
+
+ ctx_init(enif_make_new_binary(env, ctx_size, &ctx));
+ return enif_make_tuple2(env, argv[0], ctx);
+}
+static ERL_NIF_TERM hash_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* ({Type, Context}, Data) */
+ typedef int (*update_fun)(unsigned char*, const unsigned char*, size_t);
+ ERL_NIF_TERM new_ctx;
+ ErlNifBinary ctx, data;
+ const ERL_NIF_TERM *tuple;
+ int arity;
+ struct digest_type_t *digp = NULL;
+ unsigned char *ctx_buff;
+ size_t ctx_size = 0;
+ update_fun ctx_update = 0;
+
+ if (!enif_get_tuple(env, argv[0], &arity, &tuple) ||
+ arity != 2 ||
+ !(digp = get_digest_type(tuple[0])) ||
+ !enif_inspect_binary(env, tuple[1], &ctx) ||
+ !enif_inspect_iolist_as_binary(env, argv[1], &data)) {
+ return enif_make_badarg(env);
}
- new_ctx = (SHA256_CTX*) enif_make_new_binary(env,sizeof(SHA256_CTX), &ret);
- memcpy(new_ctx, ctx_bin.data, sizeof(SHA256_CTX));
- SHA256_Update(new_ctx, data_bin.data, data_bin.size);
- CONSUME_REDS(env,data_bin);
- return ret;
-#else
- return atom_notsup;
+ if (!digp->md.p) {
+ return atom_notsup;
+ }
+
+ switch (EVP_MD_type(digp->md.p))
+ {
+ case NID_md4:
+ ctx_size = MD4_CTX_LEN;
+ ctx_update = (update_fun)(&MD4_Update);
+ break;
+ case NID_md5:
+ ctx_size = MD5_CTX_LEN;
+ ctx_update = (update_fun)(&MD5_Update);
+ break;
+ case NID_ripemd160:
+ ctx_size = RIPEMD160_CTX_LEN;
+ ctx_update = (update_fun)(&RIPEMD160_Update);
+ break;
+ case NID_sha1:
+ ctx_size = sizeof(SHA_CTX);
+ ctx_update = (update_fun)(&SHA1_Update);
+ break;
+#ifdef HAVE_SHA224
+ case NID_sha224:
+ ctx_size = sizeof(SHA256_CTX);
+ ctx_update = (update_fun)(&SHA224_Update);
+ break;
#endif
-}
-static ERL_NIF_TERM sha256_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context) */
#ifdef HAVE_SHA256
- ErlNifBinary ctx_bin;
- SHA256_CTX ctx_clone;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA256_CTX)) {
- return enif_make_badarg(env);
- }
- memcpy(&ctx_clone, ctx_bin.data, sizeof(SHA256_CTX)); /* writable */
- SHA256_Final(enif_make_new_binary(env, SHA256_LEN, &ret), &ctx_clone);
- return ret;
-#else
- return atom_notsup;
+ case NID_sha256:
+ ctx_size = sizeof(SHA256_CTX);
+ ctx_update = (update_fun)(&SHA256_Update);
+ break;
#endif
-}
-
-static ERL_NIF_TERM sha384_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Data) */
#ifdef HAVE_SHA384
- ErlNifBinary ibin;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
- return enif_make_badarg(env);
- }
- SHA384((unsigned char *) ibin.data, ibin.size,
- enif_make_new_binary(env,SHA384_LEN, &ret));
- CONSUME_REDS(env,ibin);
- return ret;
-#else
- return atom_notsup;
+ case NID_sha384:
+ ctx_size = sizeof(SHA512_CTX);
+ ctx_update = (update_fun)(&SHA384_Update);
+ break;
#endif
-}
-static ERL_NIF_TERM sha384_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* () */
-#ifdef HAVE_SHA384
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- SHA384_Init((SHA512_CTX *) enif_make_new_binary(env, sizeof(SHA512_CTX), &ret));
- return ret;
-#else
- return atom_notsup;
+#ifdef HAVE_SHA512
+ case NID_sha512:
+ ctx_size = sizeof(SHA512_CTX);
+ ctx_update = (update_fun)(&SHA512_Update);
+ break;
#endif
-}
-static ERL_NIF_TERM sha384_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context, Data) */
-#ifdef HAVE_SHA384
- SHA512_CTX* new_ctx;
- ErlNifBinary ctx_bin, data_bin;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA512_CTX)
- || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
- return enif_make_badarg(env);
+ default:
+ return atom_notsup;
}
- new_ctx = (SHA512_CTX*) enif_make_new_binary(env,sizeof(SHA512_CTX), &ret);
- memcpy(new_ctx, ctx_bin.data, sizeof(SHA512_CTX));
- SHA384_Update(new_ctx, data_bin.data, data_bin.size);
- CONSUME_REDS(env,data_bin);
- return ret;
-#else
- return atom_notsup;
-#endif
-}
-static ERL_NIF_TERM sha384_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context) */
-#ifdef HAVE_SHA384
- ErlNifBinary ctx_bin;
- SHA512_CTX ctx_clone;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA512_CTX)) {
- return enif_make_badarg(env);
+ ASSERT(ctx_size);
+ ASSERT(ctx_update);
+
+ if (ctx.size != ctx_size) {
+ return enif_make_badarg(env);
}
- memcpy(&ctx_clone, ctx_bin.data, sizeof(SHA512_CTX)); /* writable */
- SHA384_Final(enif_make_new_binary(env, SHA384_LEN, &ret), &ctx_clone);
- return ret;
-#else
- return atom_notsup;
-#endif
-}
-static ERL_NIF_TERM sha512_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Data) */
-#ifdef HAVE_SHA512
- ErlNifBinary ibin;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
- return enif_make_badarg(env);
+ ctx_buff = enif_make_new_binary(env, ctx_size, &new_ctx);
+ memcpy(ctx_buff, ctx.data, ctx_size);
+ ctx_update(ctx_buff, data.data, data.size);
+
+ CONSUME_REDS(env, data);
+ return enif_make_tuple2(env, tuple[0], new_ctx);
+}
+static ERL_NIF_TERM hash_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* ({Type, Context}) */
+ typedef int (*final_fun)(unsigned char*, void*);
+ ERL_NIF_TERM ret;
+ ErlNifBinary ctx;
+ const ERL_NIF_TERM *tuple;
+ int arity;
+ struct digest_type_t *digp = NULL;
+ const EVP_MD *md;
+ void *new_ctx;
+ size_t ctx_size = 0;
+ final_fun ctx_final = 0;
+
+ if (!enif_get_tuple(env, argv[0], &arity, &tuple) ||
+ arity != 2 ||
+ !(digp = get_digest_type(tuple[0])) ||
+ !enif_inspect_binary(env, tuple[1], &ctx)) {
+ return enif_make_badarg(env);
}
- SHA512((unsigned char *) ibin.data, ibin.size,
- enif_make_new_binary(env,SHA512_LEN, &ret));
- CONSUME_REDS(env,ibin);
- return ret;
-#else
- return atom_notsup;
+ md = digp->md.p;
+ if (!md) {
+ return atom_notsup;
+ }
+
+
+ switch (EVP_MD_type(md))
+ {
+ case NID_md4:
+ ctx_size = MD4_CTX_LEN;
+ ctx_final = (final_fun)(&MD4_Final);
+ break;
+ case NID_md5:
+ ctx_size = MD5_CTX_LEN;
+ ctx_final = (final_fun)(&MD5_Final);
+ break;
+ case NID_ripemd160:
+ ctx_size = RIPEMD160_CTX_LEN;
+ ctx_final = (final_fun)(&RIPEMD160_Final);
+ break;
+ case NID_sha1:
+ ctx_size = sizeof(SHA_CTX);
+ ctx_final = (final_fun)(&SHA1_Final);
+ break;
+#ifdef HAVE_SHA224
+ case NID_sha224:
+ ctx_size = sizeof(SHA256_CTX);
+ ctx_final = (final_fun)(&SHA224_Final);
+ break;
#endif
-}
-static ERL_NIF_TERM sha512_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* () */
-#ifdef HAVE_SHA512
- ERL_NIF_TERM ret;
- SHA512_Init((SHA512_CTX *) enif_make_new_binary(env, sizeof(SHA512_CTX), &ret));
- return ret;
-#else
- return atom_notsup;
+#ifdef HAVE_SHA256
+ case NID_sha256:
+ ctx_size = sizeof(SHA256_CTX);
+ ctx_final = (final_fun)(&SHA256_Final);
+ break;
#endif
-}
-static ERL_NIF_TERM sha512_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context, Data) */
-#ifdef HAVE_SHA512
- SHA512_CTX* new_ctx;
- ErlNifBinary ctx_bin, data_bin;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA512_CTX)
- || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
- return enif_make_badarg(env);
- }
- new_ctx = (SHA512_CTX*) enif_make_new_binary(env,sizeof(SHA512_CTX), &ret);
- memcpy(new_ctx, ctx_bin.data, sizeof(SHA512_CTX));
- SHA512_Update(new_ctx, data_bin.data, data_bin.size);
- CONSUME_REDS(env,data_bin);
- return ret;
-#else
- return atom_notsup;
+#ifdef HAVE_SHA384
+ case NID_sha384:
+ ctx_size = sizeof(SHA512_CTX);
+ ctx_final = (final_fun)(&SHA384_Final);
+ break;
#endif
-}
-static ERL_NIF_TERM sha512_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context) */
#ifdef HAVE_SHA512
- ErlNifBinary ctx_bin;
- SHA512_CTX ctx_clone;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != sizeof(SHA512_CTX)) {
- return enif_make_badarg(env);
- }
- memcpy(&ctx_clone, ctx_bin.data, sizeof(SHA512_CTX)); /* writable */
- SHA512_Final(enif_make_new_binary(env, SHA512_LEN, &ret), &ctx_clone);
- return ret;
-#else
- return atom_notsup;
+ case NID_sha512:
+ ctx_size = sizeof(SHA512_CTX);
+ ctx_final = (final_fun)(&SHA512_Final);
+ break;
#endif
-}
-
-
-static ERL_NIF_TERM md4(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Data) */
- ErlNifBinary ibin;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
- return enif_make_badarg(env);
- }
- MD4((unsigned char *) ibin.data, ibin.size,
- enif_make_new_binary(env,MD4_LEN, &ret));
- CONSUME_REDS(env,ibin);
- return ret;
-}
-static ERL_NIF_TERM md4_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* () */
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- MD4_Init((MD4_CTX *) enif_make_new_binary(env, MD4_CTX_LEN, &ret));
- return ret;
-}
-static ERL_NIF_TERM md4_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context, Data) */
- MD4_CTX* new_ctx;
- ErlNifBinary ctx_bin, data_bin;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != MD4_CTX_LEN
- || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
- return enif_make_badarg(env);
- }
- new_ctx = (MD4_CTX*) enif_make_new_binary(env,MD4_CTX_LEN, &ret);
- memcpy(new_ctx, ctx_bin.data, MD4_CTX_LEN);
- MD4_Update(new_ctx, data_bin.data, data_bin.size);
- CONSUME_REDS(env,data_bin);
- return ret;
-}
-static ERL_NIF_TERM md4_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Context) */
- ErlNifBinary ctx_bin;
- MD4_CTX ctx_clone;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != MD4_CTX_LEN) {
- return enif_make_badarg(env);
+ default:
+ return atom_notsup;
}
- memcpy(&ctx_clone, ctx_bin.data, MD4_CTX_LEN); /* writable */
- MD4_Final(enif_make_new_binary(env, MD4_LEN, &ret), &ctx_clone);
- return ret;
-}
+ ASSERT(ctx_size);
+ ASSERT(ctx_final);
-static ERL_NIF_TERM md5_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, Data, MacSize) */
- unsigned char hmacbuf[SHA_DIGEST_LENGTH];
- ErlNifBinary key, data;
- unsigned mac_sz;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
- || !enif_inspect_iolist_as_binary(env, argv[1], &data)
- || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > MD5_LEN) {
- return enif_make_badarg(env);
+ if (ctx.size != ctx_size) {
+ return enif_make_badarg(env);
}
- hmac_md5(key.data, key.size, data.data, data.size, hmacbuf);
- memcpy(enif_make_new_binary(env, mac_sz, &ret), hmacbuf, mac_sz);
- CONSUME_REDS(env,data);
- return ret;
-}
-static ERL_NIF_TERM sha_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, Data, MacSize) */
- unsigned char hmacbuf[SHA_DIGEST_LENGTH];
- ErlNifBinary key, data;
- unsigned mac_sz;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
- || !enif_inspect_iolist_as_binary(env, argv[1], &data)
- || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA_LEN) {
- return enif_make_badarg(env);
- }
- hmac_sha1(key.data, key.size, data.data, data.size, hmacbuf);
- memcpy(enif_make_new_binary(env, mac_sz, &ret),
- hmacbuf, mac_sz);
- CONSUME_REDS(env,data);
- return ret;
-}
+ new_ctx = enif_alloc(ctx_size);
+ memcpy(new_ctx, ctx.data, ctx_size);
+ ctx_final(enif_make_new_binary(env, (size_t)EVP_MD_size(md), &ret),
+ new_ctx);
+ enif_free(new_ctx);
-static ERL_NIF_TERM sha224_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, Data, MacSize) */
-#ifdef HAVE_SHA224
- unsigned char hmacbuf[SHA224_DIGEST_LENGTH];
- ErlNifBinary key, data;
- unsigned mac_sz;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
- || !enif_inspect_iolist_as_binary(env, argv[1], &data)
- || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA224_DIGEST_LENGTH) {
- return enif_make_badarg(env);
- }
- hmac_sha224(key.data, key.size, data.data, data.size, hmacbuf);
- memcpy(enif_make_new_binary(env, mac_sz, &ret),
- hmacbuf, mac_sz);
- CONSUME_REDS(env,data);
return ret;
-#else
- return atom_notsup;
-#endif
}
+#endif /* OPENSSL_VERSION_NUMBER < 1.0 */
-static ERL_NIF_TERM sha256_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, Data, MacSize) */
-#ifdef HAVE_SHA256
- unsigned char hmacbuf[SHA256_DIGEST_LENGTH];
- ErlNifBinary key, data;
- unsigned mac_sz;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
- || !enif_inspect_iolist_as_binary(env, argv[1], &data)
- || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA256_DIGEST_LENGTH) {
- return enif_make_badarg(env);
- }
- hmac_sha256(key.data, key.size, data.data, data.size, hmacbuf);
- memcpy(enif_make_new_binary(env, mac_sz, &ret),
- hmacbuf, mac_sz);
- CONSUME_REDS(env,data);
- return ret;
-#else
- return atom_notsup;
-#endif
-}
+static ERL_NIF_TERM hmac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Type, Key, Data) or (Type, Key, Data, MacSize) */
+ struct digest_type_t *digp = NULL;
+ ErlNifBinary key, data;
+ unsigned char buff[EVP_MAX_MD_SIZE];
+ unsigned size = 0, req_size = 0;
+ ERL_NIF_TERM ret;
-static ERL_NIF_TERM sha384_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, Data, MacSize) */
-#ifdef HAVE_SHA384
- unsigned char hmacbuf[SHA384_DIGEST_LENGTH];
- ErlNifBinary key, data;
- unsigned mac_sz;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
- || !enif_inspect_iolist_as_binary(env, argv[1], &data)
- || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA384_DIGEST_LENGTH) {
- return enif_make_badarg(env);
+ digp = get_digest_type(argv[0]);
+ if (!digp ||
+ !enif_inspect_iolist_as_binary(env, argv[1], &key) ||
+ !enif_inspect_iolist_as_binary(env, argv[2], &data) ||
+ (argc == 4 && !enif_get_uint(env, argv[3], &req_size))) {
+ return enif_make_badarg(env);
}
- hmac_sha384(key.data, key.size, data.data, data.size, hmacbuf);
- memcpy(enif_make_new_binary(env, mac_sz, &ret),
- hmacbuf, mac_sz);
- CONSUME_REDS(env,data);
- return ret;
-#else
- return atom_notsup;
-#endif
-}
+ if (!digp->md.p ||
+ !HMAC(digp->md.p,
+ key.data, key.size,
+ data.data, data.size,
+ buff, &size)) {
+ return atom_notsup;
+ }
+ ASSERT(0 < size && size <= EVP_MAX_MD_SIZE);
+ CONSUME_REDS(env, data);
-static ERL_NIF_TERM sha512_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, Data, MacSize) */
-#ifdef HAVE_SHA512
- unsigned char hmacbuf[SHA512_DIGEST_LENGTH];
- ErlNifBinary key, data;
- unsigned mac_sz;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
- || !enif_inspect_iolist_as_binary(env, argv[1], &data)
- || !enif_get_uint(env,argv[2],&mac_sz) || mac_sz > SHA512_DIGEST_LENGTH) {
- return enif_make_badarg(env);
+ if (argc == 4) {
+ if (req_size <= size) {
+ size = req_size;
+ }
+ else {
+ return enif_make_badarg(env);
+ }
}
- hmac_sha512(key.data, key.size, data.data, data.size, hmacbuf);
- memcpy(enif_make_new_binary(env, mac_sz, &ret),
- hmacbuf, mac_sz);
- CONSUME_REDS(env,data);
+ memcpy(enif_make_new_binary(env, size, &ret), buff, size);
return ret;
-#else
- return atom_notsup;
-#endif
}
static void hmac_context_dtor(ErlNifEnv* env, struct hmac_context *obj)
@@ -1455,55 +1294,46 @@ static void hmac_context_dtor(ErlNifEnv* env, struct hmac_context *obj)
enif_mutex_destroy(obj->mtx);
}
-static ERL_NIF_TERM hmac_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+static ERL_NIF_TERM hmac_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Type, Key) */
- ErlNifBinary key;
- struct hmac_context* obj;
- const EVP_MD *md;
- ERL_NIF_TERM ret;
-
- CHECK_OSE_CRYPTO();
+ struct digest_type_t *digp = NULL;
+ ErlNifBinary key;
+ ERL_NIF_TERM ret;
+ struct hmac_context *obj;
- if (argv[0] == atom_sha) md = EVP_sha1();
-#ifdef HAVE_SHA224
- else if (argv[0] == atom_sha224) md = EVP_sha224();
-#endif
-#ifdef HAVE_SHA256
- else if (argv[0] == atom_sha256) md = EVP_sha256();
-#endif
-#ifdef HAVE_SHA384
- else if (argv[0] == atom_sha384) md = EVP_sha384();
-#endif
-#ifdef HAVE_SHA512
- else if (argv[0] == atom_sha512) md = EVP_sha512();
-#endif
- else if (argv[0] == atom_md5) md = EVP_md5();
- else if (argv[0] == atom_ripemd160) md = EVP_ripemd160();
- else goto badarg;
-
- if (!enif_inspect_iolist_as_binary(env, argv[1], &key)) {
- badarg:
- return enif_make_badarg(env);
+ digp = get_digest_type(argv[0]);
+ if (!digp ||
+ !enif_inspect_iolist_as_binary(env, argv[1], &key)) {
+ return enif_make_badarg(env);
+ }
+ if (!digp->md.p) {
+ return atom_notsup;
}
obj = enif_alloc_resource(hmac_context_rtype, sizeof(struct hmac_context));
obj->mtx = enif_mutex_create("crypto.hmac");
obj->alive = 1;
- HMAC_CTX_init(&obj->ctx);
- HMAC_Init(&obj->ctx, key.data, key.size, md);
+#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(1,0,0)
+ // Check the return value of HMAC_Init: it may fail in FIPS mode
+ // for disabled algorithms
+ if (!HMAC_Init(&obj->ctx, key.data, key.size, digp->md.p)) {
+ enif_release_resource(obj);
+ return atom_notsup;
+ }
+#else
+ HMAC_Init(&obj->ctx, key.data, key.size, digp->md.p);
+#endif
ret = enif_make_resource(env, obj);
enif_release_resource(obj);
return ret;
}
-static ERL_NIF_TERM hmac_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+static ERL_NIF_TERM hmac_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Context, Data) */
ErlNifBinary data;
struct hmac_context* obj;
- CHECK_OSE_CRYPTO();
-
if (!enif_get_resource(env, argv[0], hmac_context_rtype, (void**)&obj)
|| !enif_inspect_iolist_as_binary(env, argv[1], &data)) {
return enif_make_badarg(env);
@@ -1520,7 +1350,7 @@ static ERL_NIF_TERM hmac_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
return argv[0];
}
-static ERL_NIF_TERM hmac_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+static ERL_NIF_TERM hmac_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Context) or (Context, HashLen) */
ERL_NIF_TERM ret;
struct hmac_context* obj;
@@ -1529,8 +1359,6 @@ static ERL_NIF_TERM hmac_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
unsigned int req_len = 0;
unsigned int mac_len;
- CHECK_OSE_CRYPTO();
-
if (!enif_get_resource(env,argv[0],hmac_context_rtype, (void**)&obj)
|| (argc == 2 && !enif_get_uint(env, argv[1], &req_len))) {
return enif_make_badarg(env);
@@ -1557,132 +1385,115 @@ static ERL_NIF_TERM hmac_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
return ret;
}
-static ERL_NIF_TERM des_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, Ivec, Text, IsEncrypt) */
- ErlNifBinary key, ivec, text;
- DES_key_schedule schedule;
- DES_cblock ivec_clone; /* writable copy */
- ERL_NIF_TERM ret;
-
- CHECK_OSE_CRYPTO();
+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;
+ const EVP_CIPHER *cipher;
+ ErlNifBinary key, ivec, text;
+ EVP_CIPHER_CTX ctx;
+ ERL_NIF_TERM ret;
+ unsigned char *out;
+ int ivec_size, out_size = 0;
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 8
- || !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 8
- || !enif_inspect_iolist_as_binary(env, argv[2], &text)
- || text.size % 8 != 0) {
- return enif_make_badarg(env);
+ if (!enif_inspect_iolist_as_binary(env, argv[1], &key)
+ || !(cipherp = get_cipher_type(argv[0], key.size))
+ || !enif_inspect_iolist_as_binary(env, argv[argc - 2], &text)) {
+ return enif_make_badarg(env);
}
- memcpy(&ivec_clone, ivec.data, 8);
- DES_set_key((const_DES_cblock*)key.data, &schedule);
- DES_ncbc_encrypt(text.data, enif_make_new_binary(env, text.size, &ret),
- text.size, &schedule, &ivec_clone, (argv[3] == atom_true));
- CONSUME_REDS(env,text);
- return ret;
-}
-
-static ERL_NIF_TERM des_cfb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, Ivec, Text, IsEncrypt) */
- ErlNifBinary key, ivec, text;
- DES_key_schedule schedule;
- DES_cblock ivec_clone; /* writable copy */
- ERL_NIF_TERM ret;
-
- CHECK_OSE_CRYPTO();
-
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 8
- || !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 8
- || !enif_inspect_iolist_as_binary(env, argv[2], &text)) {
- return enif_make_badarg(env);
+ cipher = cipherp->cipher.p;
+ if (!cipher) {
+ return enif_raise_exception(env, atom_notsup);
}
- memcpy(&ivec_clone, ivec.data, 8);
- DES_set_key((const_DES_cblock*)key.data, &schedule);
- DES_cfb_encrypt(text.data, enif_make_new_binary(env, text.size, &ret),
- 8, text.size, &schedule, &ivec_clone, (argv[3] == atom_true));
- CONSUME_REDS(env,text);
- return ret;
-}
-static ERL_NIF_TERM des_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, Text/Cipher, IsEncrypt) */
- ErlNifBinary key, text;
- DES_key_schedule schedule;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 8 ||
- !enif_inspect_iolist_as_binary(env, argv[1], &text) || text.size != 8) {
- return enif_make_badarg(env);
+ if (argv[0] == atom_aes_cfb8
+ && (key.size == 24 || key.size == 32)) {
+ /* Why do EVP_CIPHER_CTX_set_key_length() fail on these key sizes?
+ * Fall back on low level API
+ */
+ return aes_cfb_8_crypt(env, argc-1, argv+1);
}
- DES_set_key((const_DES_cblock*)key.data, &schedule);
- DES_ecb_encrypt((const_DES_cblock*)text.data,
- (DES_cblock*)enif_make_new_binary(env, 8, &ret),
- &schedule, (argv[2] == atom_true));
- CONSUME_REDS(env,text);
- return ret;
-}
+ else if (argv[0] == atom_aes_cfb128
+ && (key.size == 24 || key.size == 32)) {
+ /* Why do EVP_CIPHER_CTX_set_key_length() fail on these key sizes?
+ * Fall back on low level API
+ */
+ return aes_cfb_128_crypt_nif(env, argc-1, argv+1);
+ }
-static ERL_NIF_TERM des_ede3_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key1, Key2, Key3, IVec, Text/Cipher, IsEncrypt) */
- ErlNifBinary key1, key2, key3, ivec, text;
- DES_key_schedule schedule1, schedule2, schedule3;
- DES_cblock ivec_clone; /* writable copy */
- ERL_NIF_TERM ret;
+ ivec_size = EVP_CIPHER_iv_length(cipher);
- CHECK_OSE_CRYPTO();
+#ifdef HAVE_ECB_IVEC_BUG
+ if (argv[0] == atom_aes_ecb || argv[0] == atom_blowfish_ecb ||
+ argv[0] == atom_des_ecb)
+ ivec_size = 0; /* 0.9.8l returns faulty ivec_size */
+#endif
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key1) || key1.size != 8
- || !enif_inspect_iolist_as_binary(env, argv[1], &key2) || key2.size != 8
- || !enif_inspect_iolist_as_binary(env, argv[2], &key3) || key3.size != 8
- || !enif_inspect_binary(env, argv[3], &ivec) || ivec.size != 8
- || !enif_inspect_iolist_as_binary(env, argv[4], &text)
- || text.size % 8 != 0) {
- return enif_make_badarg(env);
+ if (text.size % EVP_CIPHER_block_size(cipher) != 0 ||
+ (ivec_size == 0 ? argc != 4
+ : (argc != 5 ||
+ !enif_inspect_iolist_as_binary(env, argv[2], &ivec) ||
+ ivec.size != ivec_size))) {
+ return enif_make_badarg(env);
}
- memcpy(&ivec_clone, ivec.data, 8);
- DES_set_key((const_DES_cblock*)key1.data, &schedule1);
- DES_set_key((const_DES_cblock*)key2.data, &schedule2);
- DES_set_key((const_DES_cblock*)key3.data, &schedule3);
- DES_ede3_cbc_encrypt(text.data, enif_make_new_binary(env,text.size,&ret),
- text.size, &schedule1, &schedule2, &schedule3,
- &ivec_clone, (argv[5] == atom_true));
- CONSUME_REDS(env,text);
- return ret;
-}
+ out = enif_make_new_binary(env, text.size, &ret);
-static ERL_NIF_TERM des_ede3_cfb_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key1, Key2, Key3, IVec, Text/Cipher, IsEncrypt) */
-#ifdef HAVE_DES_ede3_cfb_encrypt
- ErlNifBinary key1, key2, key3, ivec, text;
- DES_key_schedule schedule1, schedule2, schedule3;
- DES_cblock ivec_clone; /* writable copy */
- ERL_NIF_TERM ret;
+ EVP_CIPHER_CTX_init(&ctx);
+ if (!EVP_CipherInit_ex(&ctx, cipher, NULL, NULL, NULL,
+ (argv[argc - 1] == atom_true)) ||
+ !EVP_CIPHER_CTX_set_key_length(&ctx, key.size) ||
+ !(EVP_CIPHER_type(cipher) != NID_rc2_cbc ||
+ EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_SET_RC2_KEY_BITS, key.size * 8, NULL)) ||
+ !EVP_CipherInit_ex(&ctx, NULL, NULL,
+ key.data, ivec_size ? ivec.data : NULL, -1) ||
+ !EVP_CIPHER_CTX_set_padding(&ctx, 0)) {
+
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ return enif_raise_exception(env, atom_notsup);
+ }
- CHECK_OSE_CRYPTO();
+ if (text.size > 0 && /* OpenSSL 0.9.8h asserts text.size > 0 */
+ (!EVP_CipherUpdate(&ctx, out, &out_size, text.data, text.size)
+ || (ASSERT(out_size == text.size), 0)
+ || !EVP_CipherFinal_ex(&ctx, out + out_size, &out_size))) {
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key1) || key1.size != 8
- || !enif_inspect_iolist_as_binary(env, argv[1], &key2) || key2.size != 8
- || !enif_inspect_iolist_as_binary(env, argv[2], &key3) || key3.size != 8
- || !enif_inspect_binary(env, argv[3], &ivec) || ivec.size != 8
- || !enif_inspect_iolist_as_binary(env, argv[4], &text)) {
- return enif_make_badarg(env);
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ return enif_raise_exception(env, atom_notsup);
}
+ ASSERT(out_size == 0);
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ CONSUME_REDS(env, text);
- memcpy(&ivec_clone, ivec.data, 8);
- DES_set_key((const_DES_cblock*)key1.data, &schedule1);
- DES_set_key((const_DES_cblock*)key2.data, &schedule2);
- DES_set_key((const_DES_cblock*)key3.data, &schedule3);
- DES_ede3_cfb_encrypt(text.data, enif_make_new_binary(env,text.size,&ret),
- 8, text.size, &schedule1, &schedule2, &schedule3,
- &ivec_clone, (argv[5] == atom_true));
- CONSUME_REDS(env,text);
return ret;
-#else
- return atom_notsup;
-#endif
}
static ERL_NIF_TERM aes_cfb_8_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, IVec, Data, IsEncrypt) */
+{/* (Key, IVec, Data, IsEncrypt) */
+ ErlNifBinary key, ivec, text;
+ AES_KEY aes_key;
+ unsigned char ivec_clone[16]; /* writable copy */
+ int new_ivlen = 0;
+ ERL_NIF_TERM ret;
+
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
+ || !(key.size == 16 || key.size == 24 || key.size == 32)
+ || !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 16
+ || !enif_inspect_iolist_as_binary(env, argv[2], &text)) {
+ return enif_make_badarg(env);
+ }
+
+ memcpy(ivec_clone, ivec.data, 16);
+ AES_set_encrypt_key(key.data, key.size * 8, &aes_key);
+ AES_cfb8_encrypt((unsigned char *) text.data,
+ enif_make_new_binary(env, text.size, &ret),
+ text.size, &aes_key, ivec_clone, &new_ivlen,
+ (argv[3] == atom_true));
+ CONSUME_REDS(env,text);
+ return ret;
+}
+
+static ERL_NIF_TERM aes_cfb_128_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Key, IVec, Data, IsEncrypt) */
ErlNifBinary key, ivec, text;
AES_KEY aes_key;
unsigned char ivec_clone[16]; /* writable copy */
@@ -1690,73 +1501,113 @@ static ERL_NIF_TERM aes_cfb_8_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM
ERL_NIF_TERM ret;
if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
- || !(key.size == 16 || key.size == 24 || key.size == 32)
- || !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 16
- || !enif_inspect_iolist_as_binary(env, argv[2], &text)) {
- return enif_make_badarg(env);
+ || !(key.size == 16 || key.size == 24 || key.size == 32)
+ || !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 16
+ || !enif_inspect_iolist_as_binary(env, argv[2], &text)) {
+ return enif_make_badarg(env);
}
memcpy(ivec_clone, ivec.data, 16);
AES_set_encrypt_key(key.data, key.size * 8, &aes_key);
- AES_cfb8_encrypt((unsigned char *) text.data,
- enif_make_new_binary(env, text.size, &ret),
- text.size, &aes_key, ivec_clone, &new_ivlen,
- (argv[3] == atom_true));
+ AES_cfb128_encrypt((unsigned char *) text.data,
+ enif_make_new_binary(env, text.size, &ret),
+ text.size, &aes_key, ivec_clone, &new_ivlen,
+ (argv[3] != atom_true));
CONSUME_REDS(env,text);
return ret;
}
-static ERL_NIF_TERM aes_cfb_128_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, IVec, Data, IsEncrypt) */
- ErlNifBinary key, ivec, text;
+static ERL_NIF_TERM aes_ige_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Key, IVec, Data, IsEncrypt) */
+#ifdef HAVE_AES_IGE
+ ErlNifBinary key_bin, ivec_bin, data_bin;
AES_KEY aes_key;
- unsigned char ivec_clone[16]; /* writable copy */
- int new_ivlen = 0;
+ unsigned char ivec[32];
+ int i;
+ unsigned char* ret_ptr;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
+ || (key_bin.size != 16 && key_bin.size != 32)
+ || !enif_inspect_binary(env, argv[1], &ivec_bin)
+ || ivec_bin.size != 32
+ || !enif_inspect_iolist_as_binary(env, argv[2], &data_bin)
+ || data_bin.size % 16 != 0) {
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
- || !(key.size == 16 || key.size == 24 || key.size == 32)
- || !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 16
- || !enif_inspect_iolist_as_binary(env, argv[2], &text)) {
- return enif_make_badarg(env);
+ return enif_make_badarg(env);
}
- memcpy(ivec_clone, ivec.data, 16);
- AES_set_encrypt_key(key.data, key.size * 8, &aes_key);
- AES_cfb128_encrypt((unsigned char *) text.data,
- enif_make_new_binary(env, text.size, &ret),
- text.size, &aes_key, ivec_clone, &new_ivlen,
- (argv[3] == atom_true));
- CONSUME_REDS(env,text);
+ if (argv[3] == atom_true) {
+ i = AES_ENCRYPT;
+ AES_set_encrypt_key(key_bin.data, key_bin.size*8, &aes_key);
+ }
+ else {
+ i = AES_DECRYPT;
+ AES_set_decrypt_key(key_bin.data, key_bin.size*8, &aes_key);
+ }
+
+ ret_ptr = enif_make_new_binary(env, data_bin.size, &ret);
+ memcpy(ivec, ivec_bin.data, 32); /* writable copy */
+ AES_ige_encrypt(data_bin.data, ret_ptr, data_bin.size, &aes_key, ivec, i);
+ CONSUME_REDS(env,data_bin);
return ret;
+#else
+ return atom_notsup;
+#endif
}
/* Common for both encrypt and decrypt
*/
static ERL_NIF_TERM aes_ctr_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Key, IVec, Data) */
- ErlNifBinary key, ivec, text;
- AES_KEY aes_key;
- unsigned char ivec_clone[16]; /* writable copy */
- unsigned char ecount_buf[AES_BLOCK_SIZE];
- unsigned int num = 0;
- ERL_NIF_TERM ret;
-
- CHECK_OSE_CRYPTO();
+ ErlNifBinary key, ivec, text;
+#ifdef HAVE_EVP_AES_CTR
+ const EVP_CIPHER *cipher;
+ EVP_CIPHER_CTX ctx;
+ unsigned char *out;
+ int outl = 0;
+#else
+ AES_KEY aes_key;
+ unsigned char ivec_clone[16]; /* writable copy */
+ unsigned char ecount_buf[AES_BLOCK_SIZE];
+ unsigned int num = 0;
+#endif
+ ERL_NIF_TERM ret;
if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
+#ifndef HAVE_EVP_AES_CTR
|| AES_set_encrypt_key(key.data, key.size*8, &aes_key) != 0
+#endif
|| !enif_inspect_binary(env, argv[1], &ivec) || ivec.size != 16
|| !enif_inspect_iolist_as_binary(env, argv[2], &text)) {
return enif_make_badarg(env);
}
+#ifdef HAVE_EVP_AES_CTR
+ switch (key.size)
+ {
+ case 16: cipher = EVP_aes_128_ctr(); break;
+ case 24: cipher = EVP_aes_192_ctr(); break;
+ case 32: cipher = EVP_aes_256_ctr(); break;
+ default: return enif_make_badarg(env);
+ }
+
+ out = enif_make_new_binary(env,text.size,&ret);
+ EVP_CIPHER_CTX_init(&ctx);
+ EVP_CipherInit_ex(&ctx, cipher, NULL,
+ key.data, ivec.data, (argv[3] == atom_true));
+ EVP_CIPHER_CTX_set_padding(&ctx, 0);
+ EVP_CipherUpdate(&ctx, out, &outl, text.data, text.size);
+ ASSERT(outl == text.size);
+ EVP_CipherFinal_ex(&ctx, out + outl, &outl);
+ ASSERT(outl == 0);
+ EVP_CIPHER_CTX_cleanup(&ctx);
+#else
memcpy(ivec_clone, ivec.data, 16);
memset(ecount_buf, 0, sizeof(ecount_buf));
AES_ctr128_encrypt((unsigned char *) text.data,
enif_make_new_binary(env, text.size, &ret),
text.size, &aes_key, ivec_clone, ecount_buf, &num);
+#endif
CONSUME_REDS(env,text);
/* To do an incremental {en|de}cryption, the state to to keep between calls
@@ -1766,6 +1617,81 @@ static ERL_NIF_TERM aes_ctr_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM
/* Initializes state for ctr streaming (de)encryption
*/
+#ifdef HAVE_EVP_AES_CTR
+static ERL_NIF_TERM aes_ctr_stream_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Key, IVec) */
+ ErlNifBinary key_bin, ivec_bin;
+ 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)
+ || ivec_bin.size != 16) {
+ return enif_make_badarg(env);
+ }
+
+ switch (key_bin.size)
+ {
+ case 16: cipher = EVP_aes_128_ctr(); break;
+ case 24: cipher = EVP_aes_192_ctr(); break;
+ case 32: cipher = EVP_aes_256_ctr(); break;
+ default: return enif_make_badarg(env);
+ }
+
+ ctx = enif_alloc_resource(evp_cipher_ctx_rtype, sizeof(EVP_CIPHER_CTX));
+ EVP_CIPHER_CTX_init(ctx);
+ EVP_CipherInit_ex(ctx, cipher, NULL,
+ key_bin.data, ivec_bin.data, 1);
+ EVP_CIPHER_CTX_set_padding(ctx, 0);
+ ret = enif_make_resource(env, ctx);
+ enif_release_resource(ctx);
+ return ret;
+}
+static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Context, Data) */
+ 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(EVP_CIPHER_CTX));
+ EVP_CIPHER_CTX_init(new_ctx);
+ EVP_CIPHER_CTX_copy(new_ctx, ctx);
+ out = enif_make_new_binary(env, data_bin.size, &cipher_term);
+ EVP_CipherUpdate(new_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 /* if not HAVE_EVP_AES_CTR */
+
+static ERL_NIF_TERM aes_ctr_stream_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Key, IVec) */
+ ErlNifBinary key_bin, ivec_bin;
+ ERL_NIF_TERM ecount_bin;
+
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
+ || !enif_inspect_binary(env, argv[1], &ivec_bin)
+ || !(key_bin.size == 16 || key_bin.size == 24 || key_bin.size ==32)
+ || ivec_bin.size != 16) {
+ return enif_make_badarg(env);
+ }
+
+ memset(enif_make_new_binary(env, AES_BLOCK_SIZE, &ecount_bin),
+ 0, AES_BLOCK_SIZE);
+ return enif_make_tuple4(env, argv[0], argv[1], ecount_bin, enif_make_int(env, 0));
+}
+
static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* ({Key, IVec, ECount, Num}, Data) */
ErlNifBinary key_bin, ivec_bin, text_bin, ecount_bin;
@@ -1777,8 +1703,6 @@ static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_N
unsigned char * ivec2_buf;
unsigned char * ecount2_buf;
- CHECK_OSE_CRYPTO();
-
if (!enif_get_tuple(env, argv[0], &state_arity, &state_term)
|| state_arity != 4
|| !enif_inspect_iolist_as_binary(env, state_term[0], &key_bin)
@@ -1806,94 +1730,173 @@ static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_N
CONSUME_REDS(env,text_bin);
return ret;
}
+#endif /* !HAVE_EVP_AES_CTR */
static ERL_NIF_TERM aes_gcm_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Key,Iv,AAD,In) */
#if defined(HAVE_GCM)
- GCM128_CONTEXT *ctx = NULL;
+ EVP_CIPHER_CTX ctx;
+ const EVP_CIPHER *cipher = NULL;
ErlNifBinary key, iv, aad, in;
- AES_KEY aes_key;
- unsigned char *outp;
+ unsigned int tag_len;
+ unsigned char *outp, *tagp;
ERL_NIF_TERM out, out_tag;
-
- CHECK_OSE_CRYPTO();
+ int len;
if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
- || AES_set_encrypt_key(key.data, key.size*8, &aes_key) != 0
+ || (key.size != 16 && key.size != 24 && key.size != 32)
|| !enif_inspect_binary(env, argv[1], &iv) || iv.size == 0
|| !enif_inspect_iolist_as_binary(env, argv[2], &aad)
- || !enif_inspect_iolist_as_binary(env, argv[3], &in)) {
+ || !enif_inspect_iolist_as_binary(env, argv[3], &in)
+ || !enif_get_uint(env, argv[4], &tag_len) || tag_len < 1 || tag_len > 16) {
return enif_make_badarg(env);
}
- if (!(ctx = CRYPTO_gcm128_new(&aes_key, (block128_f)AES_encrypt)))
- return atom_error;
+ if (key.size == 16)
+ cipher = EVP_aes_128_gcm();
+ else if (key.size == 24)
+ cipher = EVP_aes_192_gcm();
+ else if (key.size == 32)
+ cipher = EVP_aes_256_gcm();
- CRYPTO_gcm128_setiv(ctx, iv.data, iv.size);
+ EVP_CIPHER_CTX_init(&ctx);
- if (CRYPTO_gcm128_aad(ctx, aad.data, aad.size))
- goto out_err;
+ if (EVP_EncryptInit_ex(&ctx, cipher, NULL, NULL, NULL) != 1)
+ goto out_err;
+
+ EVP_CIPHER_CTX_set_padding(&ctx, 0);
+
+ if (EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_IVLEN, iv.size, NULL) != 1)
+ goto out_err;
+ if (EVP_EncryptInit_ex(&ctx, NULL, NULL, key.data, iv.data) != 1)
+ goto out_err;
+ if (EVP_EncryptUpdate(&ctx, NULL, &len, aad.data, aad.size) != 1)
+ goto out_err;
outp = enif_make_new_binary(env, in.size, &out);
- /* encrypt */
- if (CRYPTO_gcm128_encrypt(ctx, in.data, outp, in.size))
- goto out_err;
+ if (EVP_EncryptUpdate(&ctx, outp, &len, in.data, in.size) != 1)
+ goto out_err;
+ if (EVP_EncryptFinal_ex(&ctx, outp+len, &len) != 1)
+ goto out_err;
- /* calculate the tag */
- CRYPTO_gcm128_tag(ctx, enif_make_new_binary(env, EVP_GCM_TLS_TAG_LEN, &out_tag), EVP_GCM_TLS_TAG_LEN);
- CRYPTO_gcm128_release(ctx);
+ tagp = enif_make_new_binary(env, tag_len, &out_tag);
+
+ if (EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_GET_TAG, tag_len, tagp) != 1)
+ goto out_err;
+
+ EVP_CIPHER_CTX_cleanup(&ctx);
CONSUME_REDS(env, in);
return enif_make_tuple2(env, out, out_tag);
out_err:
- CRYPTO_gcm128_release(ctx);
+ EVP_CIPHER_CTX_cleanup(&ctx);
return atom_error;
#else
- return atom_notsup;
+ return enif_raise_exception(env, atom_notsup);
#endif
}
static ERL_NIF_TERM aes_gcm_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Key,Iv,AAD,In,Tag) */
-#if defined(HAVE_GCM)
- GCM128_CONTEXT *ctx;
+#if defined(HAVE_GCM_EVP_DECRYPT_BUG)
+ return aes_gcm_decrypt_NO_EVP(env, argc, argv);
+#elif defined(HAVE_GCM)
+ EVP_CIPHER_CTX ctx;
+ const EVP_CIPHER *cipher = NULL;
ErlNifBinary key, iv, aad, in, tag;
- AES_KEY aes_key;
unsigned char *outp;
ERL_NIF_TERM out;
-
- CHECK_OSE_CRYPTO();
+ int len;
if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
- || AES_set_encrypt_key(key.data, key.size*8, &aes_key) != 0
+ || (key.size != 16 && key.size != 24 && key.size != 32)
|| !enif_inspect_binary(env, argv[1], &iv) || iv.size == 0
|| !enif_inspect_iolist_as_binary(env, argv[2], &aad)
|| !enif_inspect_iolist_as_binary(env, argv[3], &in)
- || !enif_inspect_iolist_as_binary(env, argv[4], &tag) || tag.size != EVP_GCM_TLS_TAG_LEN) {
+ || !enif_inspect_iolist_as_binary(env, argv[4], &tag)) {
return enif_make_badarg(env);
}
+ if (key.size == 16)
+ cipher = EVP_aes_128_gcm();
+ else if (key.size == 24)
+ cipher = EVP_aes_192_gcm();
+ else if (key.size == 32)
+ cipher = EVP_aes_256_gcm();
+
+ EVP_CIPHER_CTX_init(&ctx);
+
+ if (EVP_DecryptInit_ex(&ctx, cipher, NULL, NULL, NULL) != 1)
+ goto out_err;
+ if (EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_IVLEN, iv.size, NULL) != 1)
+ goto out_err;
+ if (EVP_DecryptInit_ex(&ctx, NULL, NULL, key.data, iv.data) != 1)
+ goto out_err;
+ if (EVP_DecryptUpdate(&ctx, NULL, &len, aad.data, aad.size) != 1)
+ goto out_err;
+
+ outp = enif_make_new_binary(env, in.size, &out);
+
+ if (EVP_DecryptUpdate(&ctx, outp, &len, in.data, in.size) != 1)
+ goto out_err;
+ if (EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_TAG, tag.size, tag.data) != 1)
+ goto out_err;
+ if (EVP_DecryptFinal_ex(&ctx, outp+len, &len) != 1)
+ goto out_err;
+
+ EVP_CIPHER_CTX_cleanup(&ctx);
+
+ CONSUME_REDS(env, in);
+
+ return out;
+
+out_err:
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ return atom_error;
+#else
+ return enif_raise_exception(env, atom_notsup);
+#endif
+}
+
+#ifdef HAVE_GCM_EVP_DECRYPT_BUG
+static ERL_NIF_TERM aes_gcm_decrypt_NO_EVP(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+ GCM128_CONTEXT *ctx;
+ ErlNifBinary key, iv, aad, in, tag;
+ AES_KEY aes_key;
+ unsigned char *outp;
+ ERL_NIF_TERM out;
+
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
+ || AES_set_encrypt_key(key.data, key.size*8, &aes_key) != 0
+ || !enif_inspect_binary(env, argv[1], &iv) || iv.size == 0
+ || !enif_inspect_iolist_as_binary(env, argv[2], &aad)
+ || !enif_inspect_iolist_as_binary(env, argv[3], &in)
+ || !enif_inspect_iolist_as_binary(env, argv[4], &tag)) {
+ return enif_make_badarg(env);
+ }
+
if (!(ctx = CRYPTO_gcm128_new(&aes_key, (block128_f)AES_encrypt)))
- return atom_error;
+ return atom_error;
CRYPTO_gcm128_setiv(ctx, iv.data, iv.size);
if (CRYPTO_gcm128_aad(ctx, aad.data, aad.size))
- goto out_err;
+ goto out_err;
outp = enif_make_new_binary(env, in.size, &out);
/* decrypt */
if (CRYPTO_gcm128_decrypt(ctx, in.data, outp, in.size))
- goto out_err;
+ goto out_err;
/* calculate and check the tag */
- if (CRYPTO_gcm128_finish(ctx, tag.data, EVP_GCM_TLS_TAG_LEN))
- goto out_err;
+ if (CRYPTO_gcm128_finish(ctx, tag.data, tag.size))
+ goto out_err;
CRYPTO_gcm128_release(ctx);
CONSUME_REDS(env, in);
@@ -1903,10 +1906,8 @@ static ERL_NIF_TERM aes_gcm_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM
out_err:
CRYPTO_gcm128_release(ctx);
return atom_error;
-#else
- return atom_notsup;
-#endif
}
+#endif /* HAVE_GCM_EVP_DECRYPT_BUG */
#if defined(HAVE_CHACHA20_POLY1305)
static void
@@ -1937,8 +1938,6 @@ static ERL_NIF_TERM chacha20_poly1305_encrypt(ErlNifEnv* env, int argc, const ER
unsigned char poly1305_key[32];
poly1305_state poly1305;
- CHECK_OSE_CRYPTO();
-
if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 32
|| !enif_inspect_binary(env, argv[1], &iv) || iv.size != CHACHA20_NONCE_LEN
|| !enif_inspect_iolist_as_binary(env, argv[2], &aad)
@@ -1976,7 +1975,7 @@ static ERL_NIF_TERM chacha20_poly1305_encrypt(ErlNifEnv* env, int argc, const ER
return enif_make_tuple2(env, out, out_tag);
#else
- return atom_notsup;
+ return enif_raise_exception(env, atom_notsup);
#endif
}
@@ -1991,8 +1990,6 @@ static ERL_NIF_TERM chacha20_poly1305_decrypt(ErlNifEnv* env, int argc, const ER
unsigned char mac[POLY1305_TAG_LEN];
poly1305_state poly1305;
- CHECK_OSE_CRYPTO();
-
if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 32
|| !enif_inspect_binary(env, argv[1], &iv) || iv.size != CHACHA20_NONCE_LEN
|| !enif_inspect_iolist_as_binary(env, argv[2], &aad)
@@ -2033,51 +2030,16 @@ static ERL_NIF_TERM chacha20_poly1305_decrypt(ErlNifEnv* env, int argc, const ER
return out;
#else
- return atom_notsup;
+ return enif_raise_exception(env, atom_notsup);
#endif
}
-static ERL_NIF_TERM aes_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, Data, IsEncrypt) */
- ErlNifBinary key_bin, data_bin;
- AES_KEY aes_key;
- int i;
- int j;
- unsigned char* ret_ptr;
- ERL_NIF_TERM ret;
-
- CHECK_OSE_CRYPTO();
-
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
- || (key_bin.size != 16 && key_bin.size != 32)
- || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)
- || data_bin.size % 16 != 0) {
- return enif_make_badarg(env);
- }
-
- if (argv[2] == atom_true) {
- i = AES_ENCRYPT;
- AES_set_encrypt_key(key_bin.data, key_bin.size*8, &aes_key);
- }
- else {
- i = AES_DECRYPT;
- AES_set_decrypt_key(key_bin.data, key_bin.size*8, &aes_key);
- }
-
- ret_ptr = enif_make_new_binary(env, data_bin.size, &ret);
- for (j = 0; j < data_bin.size; j += 16) {
- AES_ecb_encrypt(data_bin.data+j, ret_ptr+j, &aes_key, i);
- }
- CONSUME_REDS(env,data_bin);
- return ret;
-}
-
static ERL_NIF_TERM rand_bytes_1(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Bytes) */
unsigned bytes;
unsigned char* data;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
+
if (!enif_get_uint(env, argv[0], &bytes)) {
return enif_make_badarg(env);
}
@@ -2091,7 +2053,7 @@ static ERL_NIF_TERM strong_rand_bytes_nif(ErlNifEnv* env, int argc, const ERL_NI
unsigned bytes;
unsigned char* data;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
+
if (!enif_get_uint(env, argv[0], &bytes)) {
return enif_make_badarg(env);
}
@@ -2103,27 +2065,7 @@ static ERL_NIF_TERM strong_rand_bytes_nif(ErlNifEnv* env, int argc, const ERL_NI
return ret;
}
-static ERL_NIF_TERM rand_bytes_3(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Bytes, TopMask, BottomMask) */
- unsigned bytes;
- unsigned char* data;
- unsigned top_mask, bot_mask;
- ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
- if (!enif_get_uint(env, argv[0], &bytes)
- || !enif_get_uint(env, argv[1], &top_mask)
- || !enif_get_uint(env, argv[2], &bot_mask)) {
- return enif_make_badarg(env);
- }
- data = enif_make_new_binary(env, bytes, &ret);
- RAND_pseudo_bytes(data, bytes);
- ERL_VALGRIND_MAKE_MEM_DEFINED(data, bytes);
- if (bytes > 0) {
- data[bytes-1] |= top_mask;
- data[0] |= bot_mask;
- }
- return ret;
-}
+
static ERL_NIF_TERM strong_rand_mpint_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Bytes, TopMask, BottomMask) */
unsigned bits;
@@ -2133,8 +2075,6 @@ static ERL_NIF_TERM strong_rand_mpint_nif(ErlNifEnv* env, int argc, const ERL_NI
unsigned dlen;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
-
if (!enif_get_uint(env, argv[0], &bits)
|| !enif_get_int(env, argv[1], &top)
|| !enif_get_int(env, argv[2], &bottom)) {
@@ -2203,8 +2143,6 @@ static ERL_NIF_TERM rand_uniform_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER
unsigned dlen;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
-
if (!get_bn_from_mpint(env, argv[0], &bn_from)
|| !get_bn_from_mpint(env, argv[1], &bn_rand)) {
if (bn_from) BN_free(bn_from);
@@ -2236,8 +2174,6 @@ static ERL_NIF_TERM mod_exp_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
unsigned extra_byte;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
-
if (!get_bn_from_bin(env, argv[0], &bn_base)
|| !get_bn_from_bin(env, argv[1], &bn_exponent)
|| !get_bn_from_bin(env, argv[2], &bn_modulo)
@@ -2269,46 +2205,17 @@ static ERL_NIF_TERM mod_exp_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
}
static ERL_NIF_TERM dss_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (DigestType|none, Data|{digest,Digest}, Signature,Key=[P, Q, G, Y]) */
- ErlNifBinary data_bin, sign_bin;
+{/* (sha, Digest, Signature,Key=[P, Q, G, Y]) */
+ ErlNifBinary digest_bin, sign_bin;
BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL, *dsa_y = NULL;
- unsigned char hmacbuf[SHA_DIGEST_LENGTH];
- unsigned char* digest;
ERL_NIF_TERM head, tail;
- const ERL_NIF_TERM* tpl_terms;
- int tpl_arity;
DSA *dsa;
int i;
- CHECK_OSE_CRYPTO();
-
- if (argv[0] == atom_sha) {
- if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) {
- if (tpl_arity != 2 || tpl_terms[0] != atom_digest
- || !enif_inspect_binary(env, tpl_terms[1], &data_bin)
- || data_bin.size != SHA_DIGEST_LENGTH) {
-
- return enif_make_badarg(env);
- }
- digest = data_bin.data;
- }
- else {
- if (!enif_inspect_binary(env, argv[1], &data_bin)) {
- return enif_make_badarg(env);
- }
- SHA1(data_bin.data, data_bin.size, hmacbuf);
- digest = hmacbuf;
- }
- }
- else if (argv[0] == atom_none && enif_inspect_binary(env, argv[1], &data_bin)
- && data_bin.size == SHA_DIGEST_LENGTH) {
- digest = data_bin.data;
- }
- else {
- return enif_make_badarg(env);
- }
-
- if (!enif_inspect_binary(env, argv[2], &sign_bin)
+ if (argv[0] != atom_sha
+ || !enif_inspect_binary(env, argv[1], &digest_bin)
+ || digest_bin.size != SHA_DIGEST_LENGTH
+ || !enif_inspect_binary(env, argv[2], &sign_bin)
|| !enif_get_list_cell(env, argv[3], &head, &tail)
|| !get_bn_from_bin(env, head, &dsa_p)
|| !enif_get_list_cell(env, tail, &head, &tail)
@@ -2332,136 +2239,86 @@ static ERL_NIF_TERM dss_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
dsa->g = dsa_g;
dsa->priv_key = NULL;
dsa->pub_key = dsa_y;
- i = DSA_verify(0, digest, SHA_DIGEST_LENGTH,
+ i = DSA_verify(0, digest_bin.data, SHA_DIGEST_LENGTH,
sign_bin.data, sign_bin.size, dsa);
DSA_free(dsa);
return(i > 0) ? atom_true : atom_false;
}
-
-static void md5_digest(unsigned char* in, unsigned int in_len, unsigned char* out)
-{
- MD5(in, in_len, out);
-}
-static void sha1_digest(unsigned char* in, unsigned int in_len, unsigned char* out)
-{
- SHA1(in, in_len, out);
-}
-#ifdef HAVE_SHA224
-static void sha224_digest(unsigned char* in, unsigned int in_len, unsigned char* out)
-{
- SHA224(in, in_len, out);
-}
-#endif
-#ifdef HAVE_SHA256
-static void sha256_digest(unsigned char* in, unsigned int in_len, unsigned char* out)
-{
- SHA256(in, in_len, out);
-}
-#endif
-#ifdef HAVE_SHA384
-static void sha384_digest(unsigned char* in, unsigned int in_len, unsigned char* out)
-{
- SHA384(in, in_len, out);
-}
-#endif
-#ifdef HAVE_SHA512
-static void sha512_digest(unsigned char* in, unsigned int in_len, unsigned char* out)
-{
- SHA512(in, in_len, out);
-}
-#endif
-
-struct digest_type_t {
- const char* type_str;
- unsigned len; /* 0 if notsup */
- int NID_type;
- void (*funcp)(unsigned char* in, unsigned int in_len, unsigned char* out);
- ERL_NIF_TERM type_atom;
-};
-
-struct digest_type_t digest_types[] =
-{
- {"md5", MD5_DIGEST_LENGTH, NID_md5, md5_digest},
- {"sha", SHA_DIGEST_LENGTH, NID_sha1, sha1_digest},
- {"sha224",
-#ifdef HAVE_SHA224
- SHA224_LEN, NID_sha224, sha224_digest
-#else
- 0
-#endif
- },
- {"sha256",
-#ifdef HAVE_SHA256
- SHA256_LEN, NID_sha256, sha256_digest
-#else
- 0
-#endif
- },
- {"sha384",
-#ifdef HAVE_SHA384
- SHA384_LEN, NID_sha384, sha384_digest
-#else
- 0
-#endif
- },
- {"sha512",
-#ifdef HAVE_SHA512
- SHA512_LEN, NID_sha512, sha512_digest
-#else
- 0
-#endif
- },
- {NULL}
-};
-
static void init_digest_types(ErlNifEnv* env)
{
struct digest_type_t* p = digest_types;
- for (p = digest_types; p->type_str; p++) {
- p->type_atom = enif_make_atom(env, p->type_str);
+ for (p = digest_types; p->type.str; p++) {
+ p->type.atom = enif_make_atom(env, p->type.str);
+ if (p->md.funcp)
+ p->md.p = p->md.funcp();
}
+ p->type.atom = atom_false; /* end marker */
+}
+static void init_cipher_types(ErlNifEnv* env)
+{
+ struct cipher_type_t* p = cipher_types;
+
+ for (p = cipher_types; p->type.str; p++) {
+ p->type.atom = enif_make_atom(env, p->type.str);
+ if (p->cipher.funcp)
+ p->cipher.p = p->cipher.funcp();
+ }
+ p->type.atom = atom_false; /* end marker */
}
static struct digest_type_t* get_digest_type(ERL_NIF_TERM type)
{
struct digest_type_t* p = NULL;
- for (p = digest_types; p->type_str; p++) {
- if (type == p->type_atom) {
+ for (p = digest_types; p->type.atom != atom_false; p++) {
+ if (type == p->type.atom) {
return p;
}
}
return NULL;
}
-static ERL_NIF_TERM rsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Type, Data|{digest,Digest}, Signature, Key=[E,N]) */
- ErlNifBinary data_bin, sign_bin;
- unsigned char hmacbuf[SHA512_LEN];
- ERL_NIF_TERM head, tail, ret;
- int i;
- RSA* rsa;
- const ERL_NIF_TERM type = argv[0];
- const ERL_NIF_TERM* tpl_terms;
- int tpl_arity;
- struct digest_type_t* digp = NULL;
- unsigned char* digest = NULL;
+static struct cipher_type_t* get_cipher_type(ERL_NIF_TERM type, size_t key_len)
+{
+ struct cipher_type_t* p = NULL;
+ for (p = cipher_types; p->type.atom != atom_false; p++) {
+ if (type == p->type.atom && (!p->key_len || key_len == p->key_len)) {
+ return p;
+ }
+ }
+ return NULL;
+}
- CHECK_OSE_CRYPTO();
+static ERL_NIF_TERM rsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Type, Digest, Signature, Key=[E,N]) */
+ ErlNifBinary digest_bin, sign_bin;
+ ERL_NIF_TERM head, tail, ret;
+ int i;
+ RSA *rsa;
+#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(1,0,0)
+ EVP_PKEY *pkey;
+ EVP_PKEY_CTX *ctx;
+#endif
+ const EVP_MD *md;
+ const ERL_NIF_TERM type = argv[0];
+ struct digest_type_t *digp = NULL;
digp = get_digest_type(type);
if (!digp) {
return enif_make_badarg(env);
}
- if (!digp->len) {
+ md = digp->md.p;
+ if (!md) {
return atom_notsup;
}
rsa = RSA_new();
- if (!enif_inspect_binary(env, argv[2], &sign_bin)
+ if (!enif_inspect_binary(env, argv[1], &digest_bin)
+ || digest_bin.size != EVP_MD_size(md)
+ || !enif_inspect_binary(env, argv[2], &sign_bin)
|| !enif_get_list_cell(env, argv[3], &head, &tail)
|| !get_bn_from_bin(env, head, &rsa->e)
|| !enif_get_list_cell(env, tail, &head, &tail)
@@ -2471,27 +2328,24 @@ static ERL_NIF_TERM rsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
ret = enif_make_badarg(env);
goto done;
}
- if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) {
- if (tpl_arity != 2 || tpl_terms[0] != atom_digest
- || !enif_inspect_binary(env, tpl_terms[1], &data_bin)
- || data_bin.size != digp->len) {
- ret = enif_make_badarg(env);
- goto done;
- }
- digest = data_bin.data;
- }
- else if (enif_inspect_binary(env, argv[1], &data_bin)) {
- digest = hmacbuf;
- digp->funcp(data_bin.data, data_bin.size, digest);
- }
- else {
- ret = enif_make_badarg(env);
- goto done;
- }
+#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(1,0,0)
+ pkey = EVP_PKEY_new();
+ EVP_PKEY_set1_RSA(pkey, rsa);
+
+ ctx = EVP_PKEY_CTX_new(pkey, NULL);
+ EVP_PKEY_verify_init(ctx);
+ EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING);
+ EVP_PKEY_CTX_set_signature_md(ctx, md);
- i = RSA_verify(digp->NID_type, digest, digp->len,
+ i = EVP_PKEY_verify(ctx, sign_bin.data, sign_bin.size,
+ digest_bin.data, digest_bin.size);
+ EVP_PKEY_CTX_free(ctx);
+ EVP_PKEY_free(pkey);
+#else
+ i = RSA_verify(md->type, digest_bin.data, EVP_MD_size(md),
sign_bin.data, sign_bin.size, rsa);
+#endif
ret = (i==1 ? atom_true : atom_false);
@@ -2500,109 +2354,6 @@ done:
return ret;
}
-
-static ERL_NIF_TERM aes_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, IVec, Data, IsEncrypt) */
- ErlNifBinary key_bin, ivec_bin, data_bin;
- unsigned char ivec[16];
- int enc, i = 0, outlen = 0;
- EVP_CIPHER_CTX ctx;
- const EVP_CIPHER *cipher = NULL;
- unsigned char* ret_ptr;
- ERL_NIF_TERM ret;
-
- CHECK_OSE_CRYPTO();
-
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
- || (key_bin.size != 16 && key_bin.size != 32)
- || !enif_inspect_binary(env, argv[1], &ivec_bin)
- || ivec_bin.size != 16
- || !enif_inspect_iolist_as_binary(env, argv[2], &data_bin)
- || data_bin.size % 16 != 0) {
-
- return enif_make_badarg(env);
- }
-
- if (argv[3] == atom_true)
- enc = 1;
- else
- enc = 0;
-
- EVP_CIPHER_CTX_init(&ctx);
-
- if (key_bin.size == 16)
- cipher = EVP_aes_128_cbc();
- else if (key_bin.size == 32)
- cipher = EVP_aes_256_cbc();
-
- memcpy(ivec, ivec_bin.data, 16); /* writeable copy */
-
- /* openssl docs say we need to leave at least 3 blocks available
- at the end of the buffer for EVP calls. let's be safe */
- ret_ptr = enif_make_new_binary(env, data_bin.size + 16*3, &ret);
-
- if (EVP_CipherInit_ex(&ctx, cipher, NULL, key_bin.data, ivec, enc) != 1)
- return enif_make_badarg(env);
-
- /* disable padding, we only handle whole blocks */
- EVP_CIPHER_CTX_set_padding(&ctx, 0);
-
- if (EVP_CipherUpdate(&ctx, ret_ptr, &i, data_bin.data, data_bin.size) != 1)
- return enif_make_badarg(env);
- outlen += i;
- if (EVP_CipherFinal_ex(&ctx, ret_ptr + outlen, &i) != 1)
- return enif_make_badarg(env);
- outlen += i;
-
- EVP_CIPHER_CTX_cleanup(&ctx);
-
- CONSUME_REDS(env,data_bin);
-
- /* the garbage collector is going to love this */
- return enif_make_sub_binary(env, ret, 0, outlen);
-}
-
-static ERL_NIF_TERM aes_ige_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, IVec, Data, IsEncrypt) */
-#ifdef HAVE_AES_IGE
- ErlNifBinary key_bin, ivec_bin, data_bin;
- AES_KEY aes_key;
- unsigned char ivec[32];
- int i;
- unsigned char* ret_ptr;
- ERL_NIF_TERM ret;
-
- CHECK_OSE_CRYPTO();
-
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
- || (key_bin.size != 16 && key_bin.size != 32)
- || !enif_inspect_binary(env, argv[1], &ivec_bin)
- || ivec_bin.size != 32
- || !enif_inspect_iolist_as_binary(env, argv[2], &data_bin)
- || data_bin.size % 16 != 0) {
-
- return enif_make_badarg(env);
- }
-
- if (argv[3] == atom_true) {
- i = AES_ENCRYPT;
- AES_set_encrypt_key(key_bin.data, key_bin.size*8, &aes_key);
- }
- else {
- i = AES_DECRYPT;
- AES_set_decrypt_key(key_bin.data, key_bin.size*8, &aes_key);
- }
-
- ret_ptr = enif_make_new_binary(env, data_bin.size, &ret);
- memcpy(ivec, ivec_bin.data, 32); /* writable copy */
- AES_ige_encrypt(data_bin.data, ret_ptr, data_bin.size, &aes_key, ivec, i);
- CONSUME_REDS(env,data_bin);
- return ret;
-#else
- return atom_notsup;
-#endif
-}
-
static ERL_NIF_TERM do_exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Data1, Data2) */
ErlNifBinary d1, d2;
@@ -2610,8 +2361,6 @@ static ERL_NIF_TERM do_exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
int i;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
-
if (!enif_inspect_iolist_as_binary(env,argv[0], &d1)
|| !enif_inspect_iolist_as_binary(env,argv[1], &d2)
|| d1.size != d2.size) {
@@ -2628,12 +2377,11 @@ static ERL_NIF_TERM do_exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
static ERL_NIF_TERM rc4_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Key, Data) */
+#ifndef OPENSSL_NO_RC4
ErlNifBinary key, data;
RC4_KEY rc4_key;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
-
if (!enif_inspect_iolist_as_binary(env,argv[0], &key)
|| !enif_inspect_iolist_as_binary(env,argv[1], &data)) {
return enif_make_badarg(env);
@@ -2643,32 +2391,35 @@ static ERL_NIF_TERM rc4_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
enif_make_new_binary(env, data.size, &ret));
CONSUME_REDS(env,data);
return ret;
-}
+#else
+ return enif_raise_exception(env, atom_notsup);
+#endif
+}
static ERL_NIF_TERM rc4_set_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Key) */
+#ifndef OPENSSL_NO_RC4
ErlNifBinary key;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
-
if (!enif_inspect_iolist_as_binary(env,argv[0], &key)) {
return enif_make_badarg(env);
}
RC4_set_key((RC4_KEY*)enif_make_new_binary(env, sizeof(RC4_KEY), &ret),
key.size, key.data);
return ret;
+#else
+ return enif_raise_exception(env, atom_notsup);
+#endif
}
static ERL_NIF_TERM rc4_encrypt_with_state(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (State, Data) */
-
+#ifndef OPENSSL_NO_RC4
ErlNifBinary state, data;
RC4_KEY* rc4_key;
ERL_NIF_TERM new_state, new_data;
- CHECK_OSE_CRYPTO();
-
if (!enif_inspect_iolist_as_binary(env,argv[0], &state)
|| state.size != sizeof(RC4_KEY)
|| !enif_inspect_iolist_as_binary(env,argv[1], &data)) {
@@ -2680,35 +2431,9 @@ static ERL_NIF_TERM rc4_encrypt_with_state(ErlNifEnv* env, int argc, const ERL_N
enif_make_new_binary(env, data.size, &new_data));
CONSUME_REDS(env,data);
return enif_make_tuple2(env,new_state,new_data);
-}
-
-static ERL_NIF_TERM rc2_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key,IVec,Data,IsEncrypt) */
- ErlNifBinary key_bin, ivec_bin, data_bin;
- RC2_KEY rc2_key;
- ERL_NIF_TERM ret;
- unsigned char iv_copy[8];
-
- CHECK_OSE_CRYPTO();
-
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
- || (key_bin.size != 5 && key_bin.size != 8 && key_bin.size != 16)
- || !enif_inspect_binary(env, argv[1], &ivec_bin)
- || ivec_bin.size != 8
- || !enif_inspect_iolist_as_binary(env, argv[2], &data_bin)
- || data_bin.size % 8 != 0) {
- return enif_make_badarg(env);
- }
-
- RC2_set_key(&rc2_key, key_bin.size, key_bin.data, key_bin.size*8);
- memcpy(iv_copy, ivec_bin.data, 8);
- RC2_cbc_encrypt(data_bin.data,
- enif_make_new_binary(env, data_bin.size, &ret),
- data_bin.size, &rc2_key,
- iv_copy,
- (argv[3] == atom_true));
- CONSUME_REDS(env,data_bin);
- return ret;
+#else
+ return enif_raise_exception(env, atom_notsup);
+#endif
}
static int get_rsa_private_key(ErlNifEnv* env, ERL_NIF_TERM key, RSA *rsa)
@@ -2740,42 +2465,32 @@ static int get_rsa_private_key(ErlNifEnv* env, ERL_NIF_TERM key, RSA *rsa)
}
static ERL_NIF_TERM rsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Type, Data|{digest,Digest}, Key=[E,N,D]|[E,N,D,P1,P2,E1,E2,C]) */
- ErlNifBinary data_bin, ret_bin;
- unsigned char hmacbuf[SHA512_LEN];
- unsigned rsa_s_len;
- RSA* rsa;
- int i;
- const ERL_NIF_TERM* tpl_terms;
- int tpl_arity;
+{/* (Type, Digest, Key=[E,N,D]|[E,N,D,P1,P2,E1,E2,C]) */
+ ErlNifBinary digest_bin, ret_bin;
+#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(1,0,0)
+ EVP_PKEY *pkey;
+ EVP_PKEY_CTX *ctx;
+ size_t rsa_s_len;
+#else
+ unsigned rsa_s_len, len;
+#endif
+ RSA *rsa;
+ int i;
struct digest_type_t *digp;
- unsigned char* digest;
-
- CHECK_OSE_CRYPTO();
+ const EVP_MD *md;
digp = get_digest_type(argv[0]);
if (!digp) {
return enif_make_badarg(env);
}
- if (!digp->len) {
+ md = digp->md.p;
+ if (!md) {
return atom_notsup;
}
- if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) {
- if (tpl_arity != 2 || tpl_terms[0] != atom_digest
- || !enif_inspect_binary(env, tpl_terms[1], &data_bin)
- || data_bin.size != digp->len) {
-
- return enif_make_badarg(env);
- }
- digest = data_bin.data;
- }
- else {
- if (!enif_inspect_binary(env,argv[1],&data_bin)) {
- return enif_make_badarg(env);
- }
- digest = hmacbuf;
- digp->funcp(data_bin.data, data_bin.size, digest);
+ if (!enif_inspect_binary(env,argv[1],&digest_bin)
+ || digest_bin.size != EVP_MD_size(md)) {
+ return enif_make_badarg(env);
}
rsa = RSA_new();
@@ -2785,14 +2500,33 @@ static ERL_NIF_TERM rsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
}
+#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(1,0,0)
+ pkey = EVP_PKEY_new();
+ EVP_PKEY_set1_RSA(pkey, rsa);
+ rsa_s_len=(size_t)EVP_PKEY_size(pkey);
+ enif_alloc_binary(rsa_s_len, &ret_bin);
+
+ ctx = EVP_PKEY_CTX_new(pkey, NULL);
+ EVP_PKEY_sign_init(ctx);
+ EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING);
+ EVP_PKEY_CTX_set_signature_md(ctx, md);
+
+ i = EVP_PKEY_sign(ctx, ret_bin.data, &rsa_s_len,
+ digest_bin.data, digest_bin.size);
+ ASSERT(i<=0 || rsa_s_len <= ret_bin.size);
+ EVP_PKEY_CTX_free(ctx);
+ EVP_PKEY_free(pkey);
+#else
enif_alloc_binary(RSA_size(rsa), &ret_bin);
+ len = EVP_MD_size(md);
- ERL_VALGRIND_ASSERT_MEM_DEFINED(digest, digp->len);
- i = RSA_sign(digp->NID_type, digest, digp->len,
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(digest_bin.data, len);
+ i = RSA_sign(md->type, digest_bin.data, len,
ret_bin.data, &rsa_s_len, rsa);
+#endif
RSA_free(rsa);
- if (i) {
+ if (i > 0) {
ERL_VALGRIND_MAKE_MEM_DEFINED(ret_bin.data, rsa_s_len);
if (rsa_s_len != ret_bin.size) {
enif_realloc_binary(&ret_bin, rsa_s_len);
@@ -2808,44 +2542,16 @@ static ERL_NIF_TERM rsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
static ERL_NIF_TERM dss_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (DigesType|none, Data|{digest,Digest}, Key=[P,Q,G,PrivKey]) */
- ErlNifBinary data_bin, ret_bin;
+{/* (sha, Digest, Key=[P,Q,G,PrivKey]) */
+ ErlNifBinary digest_bin, ret_bin;
ERL_NIF_TERM head, tail;
- unsigned char hmacbuf[SHA_DIGEST_LENGTH];
unsigned int dsa_s_len;
- const ERL_NIF_TERM* tpl_terms;
- int tpl_arity;
- unsigned char* digest = NULL;
DSA* dsa;
int i;
- CHECK_OSE_CRYPTO();
-
- if (argv[0] == atom_sha) {
- if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) {
- if (tpl_arity != 2 || tpl_terms[0] != atom_digest
- || !enif_inspect_binary(env, tpl_terms[1], &data_bin)
- || data_bin.size != SHA_DIGEST_LENGTH) {
-
- return enif_make_badarg(env);
- }
- digest = data_bin.data;
- }
- else {
- if (!enif_inspect_binary(env,argv[1],&data_bin)) {
- return enif_make_badarg(env);
- }
- SHA1(data_bin.data, data_bin.size, hmacbuf);
- digest = hmacbuf;
- }
- }
- else if (argv[0] == atom_none
- && enif_inspect_binary(env,argv[1],&data_bin)
- && data_bin.size == SHA_DIGEST_LENGTH) {
-
- digest = data_bin.data;
- }
- else {
+ if (argv[0] != atom_sha
+ || !enif_inspect_binary(env, argv[1], &digest_bin)
+ || digest_bin.size != SHA_DIGEST_LENGTH) {
return enif_make_badarg(env);
}
@@ -2866,7 +2572,7 @@ static ERL_NIF_TERM dss_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
}
enif_alloc_binary(DSA_size(dsa), &ret_bin);
- i = DSA_sign(NID_sha1, digest, SHA_DIGEST_LENGTH,
+ i = DSA_sign(NID_sha1, digest_bin.data, SHA_DIGEST_LENGTH,
ret_bin.data, &dsa_s_len, dsa);
DSA_free(dsa);
if (i) {
@@ -2906,8 +2612,6 @@ static ERL_NIF_TERM rsa_public_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TER
int padding, i;
RSA* rsa;
- CHECK_OSE_CRYPTO();
-
rsa = RSA_new();
if (!enif_inspect_binary(env, argv[0], &data_bin)
@@ -2956,8 +2660,6 @@ static ERL_NIF_TERM rsa_private_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TE
int padding, i;
RSA* rsa;
- CHECK_OSE_CRYPTO();
-
rsa = RSA_new();
if (!enif_inspect_binary(env, argv[0], &data_bin)
@@ -3004,8 +2706,6 @@ static ERL_NIF_TERM dh_generate_parameters_nif(ErlNifEnv* env, int argc, const E
unsigned char *p_ptr, *g_ptr;
ERL_NIF_TERM ret_p, ret_g;
- CHECK_OSE_CRYPTO();
-
if (!enif_get_int(env, argv[0], &prime_len)
|| !enif_get_int(env, argv[1], &generator)) {
@@ -3033,8 +2733,6 @@ static ERL_NIF_TERM dh_check(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]
int i;
ERL_NIF_TERM ret, head, tail;
- CHECK_OSE_CRYPTO();
-
dh_params = DH_new();
if (!enif_get_list_cell(env, argv[0], &head, &tail)
@@ -3062,14 +2760,13 @@ static ERL_NIF_TERM dh_check(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]
}
static ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (PrivKey, DHParams=[P,G], Mpint) */
+{/* (PrivKey|undefined, DHParams=[P,G], Mpint, Len|0) */
DH* dh_params;
int pub_len, prv_len;
unsigned char *pub_ptr, *prv_ptr;
ERL_NIF_TERM ret, ret_pub, ret_prv, head, tail;
int mpint; /* 0 or 4 */
-
- CHECK_OSE_CRYPTO();
+ unsigned long len = 0;
dh_params = DH_new();
@@ -3080,11 +2777,21 @@ static ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_
|| !enif_get_list_cell(env, tail, &head, &tail)
|| !get_bn_from_bin(env, head, &dh_params->g)
|| !enif_is_empty_list(env, tail)
- || !enif_get_int(env, argv[2], &mpint) || (mpint & ~4)) {
+ || !enif_get_int(env, argv[2], &mpint) || (mpint & ~4)
+ || !enif_get_ulong(env, argv[3], &len) ) {
DH_free(dh_params);
return enif_make_badarg(env);
}
+ if (len) {
+ if (len < BN_num_bits(dh_params->p))
+ dh_params->length = len;
+ else {
+ DH_free(dh_params);
+ return enif_make_badarg(env);
+ }
+ }
+
if (DH_generate_key(dh_params)) {
pub_len = BN_num_bytes(dh_params->pub_key);
prv_len = BN_num_bytes(dh_params->priv_key);
@@ -3115,8 +2822,6 @@ static ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_T
ErlNifBinary ret_bin;
ERL_NIF_TERM ret, head, tail;
- CHECK_OSE_CRYPTO();
-
dh_params = DH_new();
if (!get_bn_from_bin(env, argv[0], &pubkey)
@@ -3139,7 +2844,7 @@ static ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_T
ret = enif_make_binary(env, &ret_bin);
}
else {
- enif_release_binary(&ret_bin);
+ enif_release_binary(&ret_bin);
ret = atom_error;
}
}
@@ -3157,8 +2862,6 @@ static ERL_NIF_TERM srp_value_B_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
unsigned dlen;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
-
if (!get_bn_from_bin(env, argv[0], &bn_multiplier)
|| !get_bn_from_bin(env, argv[1], &bn_verifier)
|| !get_bn_from_bin(env, argv[2], &bn_generator)
@@ -3219,8 +2922,6 @@ static ERL_NIF_TERM srp_user_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_
unsigned dlen;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
-
if (!get_bn_from_bin(env, argv[0], &bn_a)
|| !get_bn_from_bin(env, argv[1], &bn_u)
|| !get_bn_from_bin(env, argv[2], &bn_B)
@@ -3300,8 +3001,6 @@ static ERL_NIF_TERM srp_host_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_
unsigned dlen;
ERL_NIF_TERM ret;
- CHECK_OSE_CRYPTO();
-
if (!get_bn_from_bin(env, argv[0], &bn_verifier)
|| !get_bn_from_bin(env, argv[1], &bn_b)
|| !get_bn_from_bin(env, argv[2], &bn_u)
@@ -3354,103 +3053,6 @@ static ERL_NIF_TERM srp_host_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_
return ret;
}
-static ERL_NIF_TERM bf_cfb64_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, Ivec, Data, IsEncrypt) */
- ErlNifBinary key_bin, ivec_bin, data_bin;
- BF_KEY bf_key; /* blowfish key 8 */
- unsigned char bf_tkey[8]; /* blowfish ivec */
- int bf_n = 0; /* blowfish ivec pos */
- ERL_NIF_TERM ret;
-
- CHECK_OSE_CRYPTO();
-
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
- || !enif_inspect_binary(env, argv[1], &ivec_bin)
- || ivec_bin.size != 8
- || !enif_inspect_iolist_as_binary(env, argv[2], &data_bin)) {
- return enif_make_badarg(env);
- }
-
- BF_set_key(&bf_key, key_bin.size, key_bin.data);
- memcpy(bf_tkey, ivec_bin.data, 8);
- BF_cfb64_encrypt(data_bin.data, enif_make_new_binary(env,data_bin.size,&ret),
- data_bin.size, &bf_key, bf_tkey, &bf_n,
- (argv[3] == atom_true ? BF_ENCRYPT : BF_DECRYPT));
- CONSUME_REDS(env,data_bin);
- return ret;
-}
-
-static ERL_NIF_TERM bf_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, Ivec, Data, IsEncrypt) */
- ErlNifBinary key_bin, ivec_bin, data_bin;
- BF_KEY bf_key; /* blowfish key 8 */
- unsigned char bf_tkey[8]; /* blowfish ivec */
- ERL_NIF_TERM ret;
-
- CHECK_OSE_CRYPTO();
-
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
- || !enif_inspect_binary(env, argv[1], &ivec_bin)
- || ivec_bin.size != 8
- || !enif_inspect_iolist_as_binary(env, argv[2], &data_bin)
- || data_bin.size % 8 != 0) {
- return enif_make_badarg(env);
- }
-
- BF_set_key(&bf_key, key_bin.size, key_bin.data);
- memcpy(bf_tkey, ivec_bin.data, 8);
- BF_cbc_encrypt(data_bin.data, enif_make_new_binary(env,data_bin.size,&ret),
- data_bin.size, &bf_key, bf_tkey,
- (argv[3] == atom_true ? BF_ENCRYPT : BF_DECRYPT));
- CONSUME_REDS(env,data_bin);
- return ret;
-}
-
-static ERL_NIF_TERM bf_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, Data, IsEncrypt) */
- ErlNifBinary key_bin, data_bin;
- BF_KEY bf_key; /* blowfish key 8 */
- ERL_NIF_TERM ret;
-
- CHECK_OSE_CRYPTO();
-
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
- || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)
- || data_bin.size < 8) {
- return enif_make_badarg(env);
- }
- BF_set_key(&bf_key, key_bin.size, key_bin.data);
- BF_ecb_encrypt(data_bin.data, enif_make_new_binary(env,data_bin.size,&ret),
- &bf_key, (argv[2] == atom_true ? BF_ENCRYPT : BF_DECRYPT));
- CONSUME_REDS(env,data_bin);
- return ret;
-}
-
-static ERL_NIF_TERM blowfish_ofb64_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key, IVec, Data) */
- ErlNifBinary key_bin, ivec_bin, data_bin;
- BF_KEY bf_key; /* blowfish key 8 */
- unsigned char bf_tkey[8]; /* blowfish ivec */
- int bf_n = 0; /* blowfish ivec pos */
- ERL_NIF_TERM ret;
-
- CHECK_OSE_CRYPTO();
-
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
- || !enif_inspect_binary(env, argv[1], &ivec_bin)
- || ivec_bin.size != 8
- || !enif_inspect_iolist_as_binary(env, argv[2], &data_bin)) {
- return enif_make_badarg(env);
- }
-
- BF_set_key(&bf_key, key_bin.size, key_bin.data);
- memcpy(bf_tkey, ivec_bin.data, 8);
- BF_ofb64_encrypt(data_bin.data, enif_make_new_binary(env,data_bin.size,&ret),
- data_bin.size, &bf_key, bf_tkey, &bf_n);
- CONSUME_REDS(env,data_bin);
- return ret;
-}
-
#if defined(HAVE_EC)
static EC_KEY* ec_key_new(ErlNifEnv* env, ERL_NIF_TERM curve_arg)
{
@@ -3467,8 +3069,7 @@ static EC_KEY* ec_key_new(ErlNifEnv* env, ERL_NIF_TERM curve_arg)
EC_POINT *point = NULL;
/* {Field, Prime, Point, Order, CoFactor} = Curve */
- if (enif_is_tuple(env, curve_arg)
- && enif_get_tuple(env,curve_arg,&c_arity,&curve)
+ if (enif_get_tuple(env,curve_arg,&c_arity,&curve)
&& c_arity == 5
&& get_bn_from_bin(env, curve[3], &bn_order)
&& (curve[4] != atom_none && get_bn_from_bin(env, curve[4], &cofactor))) {
@@ -3505,9 +3106,11 @@ static EC_KEY* ec_key_new(ErlNifEnv* env, ERL_NIF_TERM curve_arg)
/* create the EC_GROUP structure */
group = EC_GROUP_new_curve_GFp(p, a, b, NULL);
-#if !defined(OPENSSL_NO_EC2M)
-
} else if (f_arity == 3 && field[0] == atom_characteristic_two_field) {
+#if defined(OPENSSL_NO_EC2M)
+ enif_raise_exception(env, atom_notsup);
+ goto out_err;
+#else
/* {characteristic_two_field, M, Basis} */
int b_arity = -1;
@@ -3762,8 +3365,6 @@ static ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM
ERL_NIF_TERM priv_key;
ERL_NIF_TERM pub_key = atom_undefined;
- CHECK_OSE_CRYPTO();
-
if (!get_ec_key(env, argv[0], argv[1], atom_undefined, &key))
goto badarg;
@@ -3786,58 +3387,40 @@ static ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM
badarg:
if (key)
EC_KEY_free(key);
- return enif_make_badarg(env);
+ return make_badarg_maybe(env);
#else
return atom_notsup;
#endif
}
static ERL_NIF_TERM ecdsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Type, Data|{digest,Digest}, Curve, Key) */
+{/* (Type, Digest, Curve, Key) */
#if defined(HAVE_EC)
- ErlNifBinary data_bin, ret_bin;
- unsigned char hmacbuf[SHA_DIGEST_LENGTH];
+ ErlNifBinary digest_bin, ret_bin;
unsigned int dsa_s_len;
EC_KEY* key = NULL;
- int i;
- const ERL_NIF_TERM* tpl_terms;
- int tpl_arity;
+ int i, len;
struct digest_type_t *digp;
- unsigned char* digest;
-
- CHECK_OSE_CRYPTO();
+ const EVP_MD *md;
digp = get_digest_type(argv[0]);
if (!digp) {
return enif_make_badarg(env);
}
- if (!digp->len) {
+ md = digp->md.p;
+ if (!md) {
return atom_notsup;
}
+ len = EVP_MD_size(md);
- if (!get_ec_key(env, argv[2], argv[3], atom_undefined, &key))
+ if (!enif_inspect_binary(env,argv[1],&digest_bin)
+ || digest_bin.size != len
+ || !get_ec_key(env, argv[2], argv[3], atom_undefined, &key))
goto badarg;
- if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) {
- if (tpl_arity != 2 || tpl_terms[0] != atom_digest
- || !enif_inspect_binary(env, tpl_terms[1], &data_bin)
- || data_bin.size != digp->len) {
-
- goto badarg;
- }
- digest = data_bin.data;
- }
- else {
- if (!enif_inspect_binary(env,argv[1],&data_bin)) {
- goto badarg;
- }
- digest = hmacbuf;
- digp->funcp(data_bin.data, data_bin.size, digest);
- }
-
enif_alloc_binary(ECDSA_size(key), &ret_bin);
- i = ECDSA_sign(digp->NID_type, digest, digp->len,
+ i = ECDSA_sign(md->type, digest_bin.data, len,
ret_bin.data, &dsa_s_len, key);
EC_KEY_free(key);
@@ -3855,57 +3438,39 @@ static ERL_NIF_TERM ecdsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
badarg:
if (key)
EC_KEY_free(key);
- return enif_make_badarg(env);
+ return make_badarg_maybe(env);
#else
return atom_notsup;
#endif
}
static ERL_NIF_TERM ecdsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Type, Data|{digest,Digest}, Signature, Curve, Key) */
+{/* (Type, Digest, Signature, Curve, Key) */
#if defined(HAVE_EC)
- ErlNifBinary data_bin, sign_bin;
- unsigned char hmacbuf[SHA512_LEN];
- int i;
+ ErlNifBinary digest_bin, sign_bin;
+ int i, len;
EC_KEY* key = NULL;
const ERL_NIF_TERM type = argv[0];
- const ERL_NIF_TERM* tpl_terms;
- int tpl_arity;
- struct digest_type_t* digp = NULL;
- unsigned char* digest = NULL;
-
- CHECK_OSE_CRYPTO();
+ struct digest_type_t *digp = NULL;
+ const EVP_MD *md;
digp = get_digest_type(type);
if (!digp) {
return enif_make_badarg(env);
}
- if (!digp->len) {
+ md = digp->md.p;
+ if (!md) {
return atom_notsup;
}
+ len = EVP_MD_size(md);
- if (!enif_inspect_binary(env, argv[2], &sign_bin)
+ if (!enif_inspect_binary(env, argv[1], &digest_bin)
+ || digest_bin.size != len
+ || !enif_inspect_binary(env, argv[2], &sign_bin)
|| !get_ec_key(env, argv[3], atom_undefined, argv[4], &key))
goto badarg;
- if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) {
- if (tpl_arity != 2 || tpl_terms[0] != atom_digest
- || !enif_inspect_binary(env, tpl_terms[1], &data_bin)
- || data_bin.size != digp->len) {
-
- goto badarg;
- }
- digest = data_bin.data;
- }
- else if (enif_inspect_binary(env, argv[1], &data_bin)) {
- digest = hmacbuf;
- digp->funcp(data_bin.data, data_bin.size, digest);
- }
- else {
- goto badarg;
- }
-
- i = ECDSA_verify(digp->NID_type, digest, digp->len,
+ i = ECDSA_verify(md->type, digest_bin.data, len,
sign_bin.data, sign_bin.size, key);
EC_KEY_free(key);
@@ -3915,7 +3480,7 @@ static ERL_NIF_TERM ecdsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER
badarg:
if (key)
EC_KEY_free(key);
- return enif_make_badarg(env);
+ return make_badarg_maybe(env);
#else
return atom_notsup;
#endif
@@ -3939,10 +3504,8 @@ static ERL_NIF_TERM ecdh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF
EC_POINT *my_ecpoint;
EC_KEY *other_ecdh = NULL;
- CHECK_OSE_CRYPTO();
-
if (!get_ec_key(env, argv[1], argv[2], atom_undefined, &key))
- return enif_make_badarg(env);
+ return make_badarg_maybe(env);
group = EC_GROUP_dup(EC_KEY_get0_group(key));
priv_key = EC_KEY_get0_private_key(key);
@@ -3984,253 +3547,9 @@ out_err:
static ERL_NIF_TERM rand_seed_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary seed_bin;
- CHECK_OSE_CRYPTO();
+
if (!enif_inspect_binary(env, argv[0], &seed_bin))
return enif_make_badarg(env);
RAND_seed(seed_bin.data,seed_bin.size);
return atom_ok;
}
-
-
-/* HMAC */
-
-static void hmac_md5(unsigned char *key, int klen, unsigned char *dbuf, int dlen,
- unsigned char *hmacbuf)
-{
- MD5_CTX ctx;
- char ipad[HMAC_INT_LEN];
- char opad[HMAC_INT_LEN];
- unsigned char nkey[MD5_LEN];
- int i;
-
- /* Change key if longer than 64 bytes */
- if (klen > HMAC_INT_LEN) {
- MD5(key, klen, nkey);
- key = nkey;
- klen = MD5_LEN;
- }
-
- memset(ipad, '\0', sizeof(ipad));
- memset(opad, '\0', sizeof(opad));
- memcpy(ipad, key, klen);
- memcpy(opad, key, klen);
-
- for (i = 0; i < HMAC_INT_LEN; i++) {
- ipad[i] ^= HMAC_IPAD;
- opad[i] ^= HMAC_OPAD;
- }
-
- /* inner MD5 */
- MD5_Init(&ctx);
- MD5_Update(&ctx, ipad, HMAC_INT_LEN);
- MD5_Update(&ctx, dbuf, dlen);
- MD5_Final((unsigned char *) hmacbuf, &ctx);
- /* outer MD5 */
- MD5_Init(&ctx);
- MD5_Update(&ctx, opad, HMAC_INT_LEN);
- MD5_Update(&ctx, hmacbuf, MD5_LEN);
- MD5_Final((unsigned char *) hmacbuf, &ctx);
-}
-
-static void hmac_sha1(unsigned char *key, int klen,
- unsigned char *dbuf, int dlen,
- unsigned char *hmacbuf)
-{
- SHA_CTX ctx;
- char ipad[HMAC_INT_LEN];
- char opad[HMAC_INT_LEN];
- unsigned char nkey[SHA_LEN];
- int i;
-
- /* Change key if longer than 64 bytes */
- if (klen > HMAC_INT_LEN) {
- SHA1(key, klen, nkey);
- key = nkey;
- klen = SHA_LEN;
- }
-
- memset(ipad, '\0', sizeof(ipad));
- memset(opad, '\0', sizeof(opad));
- memcpy(ipad, key, klen);
- memcpy(opad, key, klen);
-
- for (i = 0; i < HMAC_INT_LEN; i++) {
- ipad[i] ^= HMAC_IPAD;
- opad[i] ^= HMAC_OPAD;
- }
-
- /* inner SHA */
- SHA1_Init(&ctx);
- SHA1_Update(&ctx, ipad, HMAC_INT_LEN);
- SHA1_Update(&ctx, dbuf, dlen);
- SHA1_Final((unsigned char *) hmacbuf, &ctx);
- /* outer SHA */
- SHA1_Init(&ctx);
- SHA1_Update(&ctx, opad, HMAC_INT_LEN);
- SHA1_Update(&ctx, hmacbuf, SHA_LEN);
- SHA1_Final((unsigned char *) hmacbuf, &ctx);
-}
-
-#ifdef HAVE_SHA224
-static void hmac_sha224(unsigned char *key, int klen,
- unsigned char *dbuf, int dlen,
- unsigned char *hmacbuf)
-{
- SHA256_CTX ctx;
- char ipad[HMAC_INT_LEN];
- char opad[HMAC_INT_LEN];
- unsigned char nkey[SHA224_DIGEST_LENGTH];
- int i;
-
- /* Change key if longer than 64 bytes */
- if (klen > HMAC_INT_LEN) {
- SHA224(key, klen, nkey);
- key = nkey;
- klen = SHA224_DIGEST_LENGTH;
- }
-
- memset(ipad, '\0', sizeof(ipad));
- memset(opad, '\0', sizeof(opad));
- memcpy(ipad, key, klen);
- memcpy(opad, key, klen);
-
- for (i = 0; i < HMAC_INT_LEN; i++) {
- ipad[i] ^= HMAC_IPAD;
- opad[i] ^= HMAC_OPAD;
- }
-
- /* inner SHA */
- SHA224_Init(&ctx);
- SHA224_Update(&ctx, ipad, HMAC_INT_LEN);
- SHA224_Update(&ctx, dbuf, dlen);
- SHA224_Final((unsigned char *) hmacbuf, &ctx);
- /* outer SHA */
- SHA224_Init(&ctx);
- SHA224_Update(&ctx, opad, HMAC_INT_LEN);
- SHA224_Update(&ctx, hmacbuf, SHA224_DIGEST_LENGTH);
- SHA224_Final((unsigned char *) hmacbuf, &ctx);
-}
-#endif
-
-#ifdef HAVE_SHA256
-static void hmac_sha256(unsigned char *key, int klen,
- unsigned char *dbuf, int dlen,
- unsigned char *hmacbuf)
-{
- SHA256_CTX ctx;
- char ipad[HMAC_INT_LEN];
- char opad[HMAC_INT_LEN];
- unsigned char nkey[SHA256_DIGEST_LENGTH];
- int i;
-
- /* Change key if longer than 64 bytes */
- if (klen > HMAC_INT_LEN) {
- SHA256(key, klen, nkey);
- key = nkey;
- klen = SHA256_DIGEST_LENGTH;
- }
-
- memset(ipad, '\0', sizeof(ipad));
- memset(opad, '\0', sizeof(opad));
- memcpy(ipad, key, klen);
- memcpy(opad, key, klen);
-
- for (i = 0; i < HMAC_INT_LEN; i++) {
- ipad[i] ^= HMAC_IPAD;
- opad[i] ^= HMAC_OPAD;
- }
-
- /* inner SHA */
- SHA256_Init(&ctx);
- SHA256_Update(&ctx, ipad, HMAC_INT_LEN);
- SHA256_Update(&ctx, dbuf, dlen);
- SHA256_Final((unsigned char *) hmacbuf, &ctx);
- /* outer SHA */
- SHA256_Init(&ctx);
- SHA256_Update(&ctx, opad, HMAC_INT_LEN);
- SHA256_Update(&ctx, hmacbuf, SHA256_DIGEST_LENGTH);
- SHA256_Final((unsigned char *) hmacbuf, &ctx);
-}
-#endif
-
-#ifdef HAVE_SHA384
-static void hmac_sha384(unsigned char *key, int klen,
- unsigned char *dbuf, int dlen,
- unsigned char *hmacbuf)
-{
- SHA512_CTX ctx;
- char ipad[HMAC_INT2_LEN];
- char opad[HMAC_INT2_LEN];
- unsigned char nkey[SHA384_DIGEST_LENGTH];
- int i;
-
- /* Change key if longer than 64 bytes */
- if (klen > HMAC_INT2_LEN) {
- SHA384(key, klen, nkey);
- key = nkey;
- klen = SHA384_DIGEST_LENGTH;
- }
-
- memset(ipad, '\0', sizeof(ipad));
- memset(opad, '\0', sizeof(opad));
- memcpy(ipad, key, klen);
- memcpy(opad, key, klen);
-
- for (i = 0; i < HMAC_INT2_LEN; i++) {
- ipad[i] ^= HMAC_IPAD;
- opad[i] ^= HMAC_OPAD;
- }
-
- /* inner SHA */
- SHA384_Init(&ctx);
- SHA384_Update(&ctx, ipad, HMAC_INT2_LEN);
- SHA384_Update(&ctx, dbuf, dlen);
- SHA384_Final((unsigned char *) hmacbuf, &ctx);
- /* outer SHA */
- SHA384_Init(&ctx);
- SHA384_Update(&ctx, opad, HMAC_INT2_LEN);
- SHA384_Update(&ctx, hmacbuf, SHA384_DIGEST_LENGTH);
- SHA384_Final((unsigned char *) hmacbuf, &ctx);
-}
-#endif
-
-#ifdef HAVE_SHA512
-static void hmac_sha512(unsigned char *key, int klen,
- unsigned char *dbuf, int dlen,
- unsigned char *hmacbuf)
-{
- SHA512_CTX ctx;
- char ipad[HMAC_INT2_LEN];
- char opad[HMAC_INT2_LEN];
- unsigned char nkey[SHA512_DIGEST_LENGTH];
- int i;
-
- /* Change key if longer than 64 bytes */
- if (klen > HMAC_INT2_LEN) {
- SHA512(key, klen, nkey);
- key = nkey;
- klen = SHA512_DIGEST_LENGTH;
- }
-
- memset(ipad, '\0', sizeof(ipad));
- memset(opad, '\0', sizeof(opad));
- memcpy(ipad, key, klen);
- memcpy(opad, key, klen);
-
- for (i = 0; i < HMAC_INT2_LEN; i++) {
- ipad[i] ^= HMAC_IPAD;
- opad[i] ^= HMAC_OPAD;
- }
-
- /* inner SHA */
- SHA512_Init(&ctx);
- SHA512_Update(&ctx, ipad, HMAC_INT2_LEN);
- SHA512_Update(&ctx, dbuf, dlen);
- SHA512_Final((unsigned char *) hmacbuf, &ctx);
- /* outer SHA */
- SHA512_Init(&ctx);
- SHA512_Update(&ctx, opad, HMAC_INT2_LEN);
- SHA512_Update(&ctx, hmacbuf, SHA512_DIGEST_LENGTH);
- SHA512_Final((unsigned char *) hmacbuf, &ctx);
-}
-#endif
diff --git a/lib/crypto/c_src/crypto_callback.c b/lib/crypto/c_src/crypto_callback.c
index e0de16074c..3acbbf406b 100644
--- a/lib/crypto/c_src/crypto_callback.c
+++ b/lib/crypto/c_src/crypto_callback.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2014. All Rights Reserved.
+ * Copyright Ericsson AB 2014-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -43,6 +43,10 @@
#ifdef __WIN32__
# define DLLEXPORT __declspec(dllexport)
+#elif defined(__GNUC__) && __GNUC__ >= 4
+# define DLLEXPORT __attribute__ ((visibility("default")))
+#elif defined (__SUNPRO_C) && (__SUNPRO_C >= 0x550)
+# define DLLEXPORT __global
#else
# define DLLEXPORT
#endif
@@ -51,8 +55,6 @@
DLLEXPORT struct crypto_callbacks* get_crypto_callbacks(int nlocks);
-static ErlNifRWLock** lock_vec = NULL; /* Static locks used by openssl */
-
static void nomem(size_t size, const char* op)
{
fprintf(stderr, "Out of memory abort. Crypto failed to %s %zu bytes.\r\n",
@@ -84,6 +86,8 @@ static void crypto_free(void* ptr)
#ifdef OPENSSL_THREADS /* vvvvvvvvvvvvvvv OPENSSL_THREADS vvvvvvvvvvvvvvvv */
+static ErlNifRWLock** lock_vec = NULL; /* Static locks used by openssl */
+
#include <openssl/crypto.h>
static INLINE void locking(int mode, ErlNifRWLock* lock)
diff --git a/lib/crypto/c_src/crypto_callback.h b/lib/crypto/c_src/crypto_callback.h
index df5c99d4d3..894d86cfd9 100644
--- a/lib/crypto/c_src/crypto_callback.h
+++ b/lib/crypto/c_src/crypto_callback.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2012. All Rights Reserved.
+ * Copyright Ericsson AB 2012-2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/lib/crypto/doc/src/book.xml b/lib/crypto/doc/src/book.xml
index 43ed49113f..b8b2c935b3 100644
--- a/lib/crypto/doc/src/book.xml
+++ b/lib/crypto/doc/src/book.xml
@@ -4,7 +4,7 @@
<book xmlns:xi="http://www.w3.org/2001/XInclude">
<header titlestyle="normal">
<copyright>
- <year>1999</year><year>2013</year>
+ <year>1999</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml
index 563a090e98..82e450ec21 100644
--- a/lib/crypto/doc/src/crypto.xml
+++ b/lib/crypto/doc/src/crypto.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1999</year><year>2014</year>
+ <year>1999</year><year>2017</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -100,7 +100,7 @@
<code>dh_private() = key_value() </code>
- <code>dh_params() = [key_value()] = [P, G] </code>
+ <code>dh_params() = [key_value()] = [P, G] | [P, G, PrivateKeyBitLength]</code>
<code>ecdh_public() = key_value() </code>
@@ -135,9 +135,8 @@
<code>stream_cipher() = rc4 | aes_ctr </code>
- <code>block_cipher() = aes_cbc128 | aes_cfb8 | aes_cfb128 | aes_ige256 | blowfish_cbc |
- blowfish_cfb64 | des_cbc | des_cfb | des3_cbc | des3_cbf
- | des_ede3 | rc2_cbc </code>
+ <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>
<code>aead_cipher() = aes_gcm | chacha20_poly1305 </code>
@@ -160,8 +159,9 @@
<code> hash_algorithms() = md5 | ripemd160 | sha | sha224 | sha256 | sha384 | sha512 </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.
</p>
- <code> cipher_algorithms() = des_cbc | des_cfb | des3_cbc | des3_cbf | des_ede3 |
- blowfish_cbc | blowfish_cfb64 | aes_cbc128 | aes_cfb8 | aes_cfb128| aes_cbc256 | aes_ige256 | aes_gcm | chacha20_poly1305 | rc2_cbc | aes_ctr| rc4 </code>
+ <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> 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.
@@ -203,6 +203,7 @@
<func>
<name>block_encrypt(Type, Key, Ivec, PlainText) -> CipherText</name>
<name>block_encrypt(AeadType, Key, Ivec, {AAD, PlainText}) -> {CipherText, CipherTag}</name>
+ <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>
@@ -210,6 +211,7 @@
<v>Key = block_key() </v>
<v>PlainText = iodata() </v>
<v>AAD = IVec = CipherText = CipherTag = binary()</v>
+ <v>TagLength = 1..16</v>
</type>
<desc>
<p>Encrypt <c>PlainText</c> according to <c>Type</c> block cipher.
@@ -306,6 +308,8 @@
<desc>
<p>Generates public keys 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 <c>low_entropy</c> in case the random generator
+ failed due to lack of secure "randomness".
</p>
</desc>
</func>
@@ -594,22 +598,6 @@
</func>
<func>
- <name>rand_bytes(N) -> binary()</name>
- <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 the <c>crypto</c> library pseudo-random
- number generator.</p>
- <p>This function is not recommended for cryptographic purposes.
- Please use <seealso marker="#strong_rand_bytes/1">
- strong_rand_bytes/1</seealso> instead.</p>
- </desc>
- </func>
-
- <func>
<name>rand_seed(Seed) -> ok</name>
<fsummary>Set the seed for random bytes generation</fsummary>
<type>
diff --git a/lib/crypto/doc/src/crypto_app.xml b/lib/crypto/doc/src/crypto_app.xml
index 4ba2d34934..2b9e505988 100644
--- a/lib/crypto/doc/src/crypto_app.xml
+++ b/lib/crypto/doc/src/crypto_app.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>1999</year>
- <year>2014</year>
+ <year>2016</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
diff --git a/lib/crypto/doc/src/licenses.xml b/lib/crypto/doc/src/licenses.xml
index 57d78f7bd9..e5c06cf7ce 100644
--- a/lib/crypto/doc/src/licenses.xml
+++ b/lib/crypto/doc/src/licenses.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2003</year><year>2013</year>
+ <year>2003</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/crypto/doc/src/notes.xml b/lib/crypto/doc/src/notes.xml
index 0138eb6ad2..887aeca680 100644
--- a/lib/crypto/doc/src/notes.xml
+++ b/lib/crypto/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1999</year><year>2013</year>
+ <year>1999</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,6 +31,152 @@
</header>
<p>This document describes the changes made to the Crypto application.</p>
+<section><title>Crypto 3.7.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix a bug with AES CFB 128 for 192 and 256 bit keys.
+ Thanks to kellymclaughlin !</p>
+ <p>
+ Own Id: OTP-14313 Aux Id: PR-1393 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Crypto 3.7.3</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The implementation of the key exchange algorithms
+ diffie-hellman-group-exchange-sha* are optimized, up to a
+ factor of 11 for the slowest ( = biggest and safest)
+ group size.</p>
+ <p>
+ Own Id: OTP-14169 Aux Id: seq-13261 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Crypto 3.7.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The crypto application has been fixed to not use RC2
+ against OpenSSL built with RC2 disabled.</p>
+ <p>
+ Own Id: OTP-13895 Aux Id: PR-1163 </p>
+ </item>
+ <item>
+ <p>
+ The crypto application has been fixed to not use RC4
+ against OpenSSL built with RC4 disabled.</p>
+ <p>
+ Own Id: OTP-13896 Aux Id: PR-1169 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ To ease troubleshooting, <c>erlang:load_nif/2</c> now
+ includes the return value from a failed call to
+ load/reload/upgrade in the text part of the error tuple.
+ The <c>crypto</c> NIF makes use of this feature by
+ returning the source line where/if the initialization
+ fails.</p>
+ <p>
+ Own Id: OTP-13951</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Crypto 3.7.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Crypto has been fixed to work against OpenSSL versions
+ with disabled DES ciphers. Correct spelling of cipher
+ algorithm 'des3_cfb' has been introduced; the previous
+ misspeling still works.</p>
+ <p>
+ Own Id: OTP-13783 Aux Id: ERL-203 </p>
+ </item>
+ <item>
+ <p>
+ The size of an internal array in crypto has been fixed to
+ not segfault when having all possible ciphers. Bug fix by
+ Duncan Overbruck.</p>
+ <p>
+ Own Id: OTP-13789 Aux Id: PR-1140 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Crypto 3.7</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Refactor <c>crypto</c> to use the EVP interface of
+ OpenSSL, which is the recommended interface that also
+ enables access to hardware acceleration for some
+ operations.</p>
+ <p>
+ Own Id: OTP-12217</p>
+ </item>
+ <item>
+ <p>
+ Add support for 192-bit keys for the <c>aes_cbc</c>
+ cipher.</p>
+ <p>
+ Own Id: OTP-13206 Aux Id: pr 832 </p>
+ </item>
+ <item>
+ <p>
+ Add support for 192-bit keys for <c>aes_ecb</c>.</p>
+ <p>
+ Own Id: OTP-13207 Aux Id: pr829 </p>
+ </item>
+ <item>
+ <p>
+ Deprecate the function <c>crypto:rand_bytes</c> and make
+ sure that <c>crypto:strong_rand_bytes</c> is used in all
+ places that are cryptographically significant.</p>
+ <p>
+ Own Id: OTP-13214</p>
+ </item>
+ <item>
+ <p>
+ Enable AES-GCM encryption/decryption to change the tag
+ length between 1 to 16 bytes.</p>
+ <p>
+ Own Id: OTP-13483 Aux Id: PR-998 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Crypto 3.6.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -769,7 +915,7 @@
also been extended. </item><item> The <c>configure</c>
scripts of <c>erl_interface</c> and <c>odbc</c> now
search for thread libraries and thread library quirks the
- same way as <c>erts</c> do. </item><item> The
+ same way as ERTS do. </item><item> The
<c>configure</c> script of the <c>odbc</c> application
now also looks for odbc libraries in <c>lib64</c> and
<c>lib/64</c> directories when building on a 64-bit
diff --git a/lib/crypto/doc/src/ref_man.xml b/lib/crypto/doc/src/ref_man.xml
index ccdb5afb9b..14922cbcec 100644
--- a/lib/crypto/doc/src/ref_man.xml
+++ b/lib/crypto/doc/src/ref_man.xml
@@ -4,7 +4,7 @@
<application xmlns:xi="http://www.w3.org/2001/XInclude">
<header>
<copyright>
- <year>1999</year><year>2013</year>
+ <year>1999</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/crypto/doc/src/release_notes.xml b/lib/crypto/doc/src/release_notes.xml
index 5253027b9c..a2d7964455 100644
--- a/lib/crypto/doc/src/release_notes.xml
+++ b/lib/crypto/doc/src/release_notes.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>1999</year>
- <year>2013</year>
+ <year>2016</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
diff --git a/lib/crypto/doc/src/usersguide.xml b/lib/crypto/doc/src/usersguide.xml
index 469ab10cc8..fb088a8285 100644
--- a/lib/crypto/doc/src/usersguide.xml
+++ b/lib/crypto/doc/src/usersguide.xml
@@ -4,7 +4,7 @@
<part xmlns:xi="http://www.w3.org/2001/XInclude">
<header>
<copyright>
- <year>2003</year><year>2013</year>
+ <year>2003</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/crypto/src/Makefile b/lib/crypto/src/Makefile
index 6e4008e434..456b8be64d 100644
--- a/lib/crypto/src/Makefile
+++ b/lib/crypto/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1999-2014. All Rights Reserved.
+# Copyright Ericsson AB 1999-2016. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/lib/crypto/src/crypto.app.src b/lib/crypto/src/crypto.app.src
index 70611bb637..8a47b8a78b 100644
--- a/lib/crypto/src/crypto.app.src
+++ b/lib/crypto/src/crypto.app.src
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/crypto/src/crypto.appup.src b/lib/crypto/src/crypto.appup.src
index ce13746a07..a177de22fb 100644
--- a/lib/crypto/src/crypto.appup.src
+++ b/lib/crypto/src/crypto.appup.src
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index 38e71591f3..60e0affda0 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -28,7 +28,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([exor/2, strong_rand_bytes/1, mod_pow/3]).
--export([rand_bytes/1, rand_bytes/3, rand_uniform/2]).
+-export([rand_uniform/2]).
-export([block_encrypt/3, block_decrypt/3, block_encrypt/4, block_decrypt/4]).
-export([next_iv/2, next_iv/3]).
-export([stream_init/2, stream_init/3, stream_encrypt/2, stream_decrypt/2]).
@@ -39,6 +39,9 @@
-export([rand_seed/1]).
%% DEPRECATED
+-export([rand_bytes/1]).
+-deprecated({rand_bytes, 1, next_major_release}).
+
%% Replaced by hash_*
-export([md4/1, md4_init/0, md4_update/2, md4_final/1]).
-export([md5/1, md5_init/0, md5_update/2, md5_final/1]).
@@ -210,10 +213,8 @@ supports()->
{Hashs, PubKeys, Ciphers} = algorithms(),
[{hashs, Hashs},
- {ciphers, [des_cbc, des_cfb, des3_cbc, des_ede3, blowfish_cbc,
- blowfish_cfb64, blowfish_ofb64, blowfish_ecb, aes_cbc128, aes_cfb8, aes_cfb128,
- aes_cbc256, rc2_cbc, aes_ctr, rc4, aes_ecb] ++ Ciphers},
- {public_keys, [rsa, dss, dh, srp] ++ PubKeys}
+ {ciphers, Ciphers},
+ {public_keys, PubKeys}
].
info_lib() -> ?nif_stub.
@@ -222,20 +223,14 @@ info_lib() -> ?nif_stub.
hash(Hash, Data0) ->
Data = iolist_to_binary(Data0),
- MaxByts = max_bytes(),
- hash(Hash, Data, erlang:byte_size(Data), MaxByts, initial).
+ MaxBytes = max_bytes(),
+ hash(Hash, Data, erlang:byte_size(Data), MaxBytes).
-spec hash_init('md5'|'md4'|'ripemd160'|
'sha'|'sha224'|'sha256'|'sha384'|'sha512') -> any().
-hash_init(md5) -> {md5, md5_init()};
-hash_init(md4) -> {md4, md4_init()};
-hash_init(sha) -> {sha, sha_init()};
-hash_init(ripemd160) -> {ripemd160, ripemd160_init()};
-hash_init(sha224) -> {sha224, sha224_init()};
-hash_init(sha256) -> {sha256, sha256_init()};
-hash_init(sha384) -> {sha384, sha384_init()};
-hash_init(sha512) -> {sha512, sha512_init()}.
+hash_init(Hash) ->
+ notsup_to_error(hash_init_nif(Hash)).
-spec hash_update(_, iodata()) -> any().
@@ -246,14 +241,8 @@ hash_update(State, Data0) ->
-spec hash_final(_) -> binary().
-hash_final({md5,Context}) -> md5_final(Context);
-hash_final({md4,Context}) -> md4_final(Context);
-hash_final({sha,Context}) -> sha_final(Context);
-hash_final({ripemd160,Context}) -> ripemd160_final(Context);
-hash_final({sha224,Context}) -> sha224_final(Context);
-hash_final({sha256,Context}) -> sha256_final(Context);
-hash_final({sha384,Context}) -> sha384_final(Context);
-hash_final({sha512,Context}) -> sha512_final(Context).
+hash_final(State) ->
+ notsup_to_error(hash_final_nif(State)).
-spec hmac(_, iodata(), iodata()) -> binary().
@@ -265,151 +254,141 @@ hash_final({sha512,Context}) -> sha512_final(Context).
hmac(Type, Key, Data0) ->
Data = iolist_to_binary(Data0),
- hmac(Type, Key, Data, undefined, erlang:byte_size(Data), max_bytes(), initial).
+ 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(), initial).
+ hmac(Type, Key, Data, MacSize, erlang:byte_size(Data), max_bytes()).
-
-hmac_init(_Type, _Key) -> ?nif_stub.
+hmac_init(Type, Key) ->
+ notsup_to_error(hmac_init_nif(Type, Key)).
hmac_update(State, Data0) ->
Data = iolist_to_binary(Data0),
hmac_update(State, Data, erlang:byte_size(Data), max_bytes()).
-hmac_final(_Context) -> ? nif_stub.
-hmac_final_n(_Context, _HashLen) -> ? nif_stub.
+
+hmac_final(Context) ->
+ notsup_to_error(hmac_final_nif(Context)).
+hmac_final_n(Context, HashLen) ->
+ notsup_to_error(hmac_final_nif(Context, HashLen)).
%% Ecrypt/decrypt %%%
--spec block_encrypt(des_cbc | des_cfb | des3_cbc | des3_cbf | des_ede3 | blowfish_cbc |
- blowfish_cfb64 | aes_cbc128 | aes_cfb8 | aes_cfb128 | aes_cbc256 | rc2_cbc,
- Key::iodata(), Ivec::binary(), Data::iodata()) -> binary();
- (aes_gcm | chacha20_poly1305, Key::iodata(), Ivec::binary(), {AAD::binary(), Data::iodata()}) -> {binary(), binary()}.
-
-block_encrypt(des_cbc, Key, Ivec, Data) ->
- des_cbc_encrypt(Key, Ivec, Data);
-block_encrypt(des_cfb, Key, Ivec, Data) ->
- des_cfb_encrypt(Key, Ivec, Data);
-block_encrypt(des3_cbc, [Key1, Key2, Key3], Ivec, Data) ->
- des3_cbc_encrypt(Key1, Key2, Key3, Ivec, Data);
-block_encrypt(des3_cbf, [Key1, Key2, Key3], Ivec, Data) ->
- des3_cfb_encrypt(Key1, Key2, Key3, Ivec, Data);
-block_encrypt(des_ede3, [Key1, Key2, Key3], Ivec, Data) ->
- des_ede3_cbc_encrypt(Key1, Key2, Key3, Ivec, Data);
-block_encrypt(blowfish_cbc, Key, Ivec, Data) ->
- blowfish_cbc_encrypt(Key, Ivec, Data);
-block_encrypt(blowfish_cfb64, Key, Ivec, Data) ->
- blowfish_cfb64_encrypt(Key, Ivec, Data);
-block_encrypt(blowfish_ofb64, Key, Ivec, Data) ->
- blowfish_ofb64_encrypt(Key, Ivec, Data);
-block_encrypt(aes_cbc128, Key, Ivec, Data) ->
- aes_cbc_128_encrypt(Key, Ivec, Data);
-block_encrypt(aes_cbc256, Key, Ivec, Data) ->
- aes_cbc_256_encrypt(Key, Ivec, Data);
+-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;
+ Type =:= des_cfb;
+ Type =:= blowfish_cbc;
+ Type =:= blowfish_cfb64;
+ Type =:= blowfish_ofb64;
+ Type =:= aes_cbc128;
+ Type =:= aes_cfb8;
+ Type =:= aes_cfb128;
+ 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;
+ 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) ->
+ Key = check_des3_key(Key0),
+ block_crypt_nif(des_ede3_cbf, Key, Ivec, Data, true);
+block_encrypt(des3_cfb, Key0, Ivec, Data) ->
+ Key = check_des3_key(Key0),
+ block_crypt_nif(des_ede3_cfb, Key, Ivec, Data, true);
block_encrypt(aes_ige256, Key, Ivec, Data) ->
- aes_ige_256_encrypt(Key, Ivec, Data);
-block_encrypt(aes_cfb8, Key, Ivec, Data) ->
- aes_cfb_8_encrypt(Key, Ivec, Data);
-block_encrypt(aes_cfb128, Key, Ivec, Data) ->
- aes_cfb_128_encrypt(Key, Ivec, Data);
+ aes_ige_crypt_nif(Key, Ivec, Data, true);
block_encrypt(aes_gcm, Key, Ivec, {AAD, Data}) ->
- case aes_gcm_encrypt(Key, Ivec, AAD, Data) of
- notsup -> erlang:error(notsup);
- Return -> Return
- end;
+ 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}) ->
- case chacha20_poly1305_encrypt(Key, Ivec, AAD, Data) of
- notsup -> erlang:error(notsup);
- Return -> Return
- end;
-block_encrypt(rc2_cbc, Key, Ivec, Data) ->
- rc2_cbc_encrypt(Key, Ivec, Data).
-
--spec block_decrypt(des_cbc | des_cfb | des3_cbc | des3_cbf | des_ede3 | blowfish_cbc |
- blowfish_cfb64 | blowfish_ofb64 | aes_cbc128 | aes_cbc256 | aes_ige256 |
- aes_cfb8 | aes_cfb128 | rc2_cbc,
+ 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(),
{AAD::binary(), Data::iodata(), Tag::binary()}) -> binary() | error.
-block_decrypt(des_cbc, Key, Ivec, Data) ->
- des_cbc_decrypt(Key, Ivec, Data);
-block_decrypt(des_cfb, Key, Ivec, Data) ->
- des_cfb_decrypt(Key, Ivec, Data);
-block_decrypt(des3_cbc, [Key1, Key2, Key3], Ivec, Data) ->
- des3_cbc_decrypt(Key1, Key2, Key3, Ivec, Data);
-block_decrypt(des3_cbf, [Key1, Key2, Key3], Ivec, Data) ->
- des3_cfb_decrypt(Key1, Key2, Key3, Ivec, Data);
-block_decrypt(des_ede3, [Key1, Key2, Key3], Ivec, Data) ->
- des_ede3_cbc_decrypt(Key1, Key2, Key3, Ivec, Data);
-block_decrypt(blowfish_cbc, Key, Ivec, Data) ->
- blowfish_cbc_decrypt(Key, Ivec, Data);
-block_decrypt(blowfish_cfb64, Key, Ivec, Data) ->
- blowfish_cfb64_decrypt(Key, Ivec, Data);
-block_decrypt(blowfish_ofb64, Key, Ivec, Data) ->
- blowfish_ofb64_decrypt(Key, Ivec, Data);
-block_decrypt(aes_cbc128, Key, Ivec, Data) ->
- aes_cbc_128_decrypt(Key, Ivec, Data);
-block_decrypt(aes_cbc256, Key, Ivec, Data) ->
- aes_cbc_256_decrypt(Key, Ivec, Data);
+block_decrypt(Type, Key, Ivec, Data) when Type =:= des_cbc;
+ Type =:= des_cfb;
+ Type =:= blowfish_cbc;
+ Type =:= blowfish_cfb64;
+ Type =:= blowfish_ofb64;
+ Type =:= aes_cbc;
+ Type =:= aes_cbc128;
+ Type =:= aes_cfb8;
+ Type =:= aes_cfb128;
+ Type =:= aes_cbc256;
+ Type =:= rc2_cbc ->
+ block_crypt_nif(Type, Key, Ivec, Data, false);
+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) ->
+ Key = check_des3_key(Key0),
+ block_crypt_nif(des_ede3_cbf, Key, Ivec, Data, false);
+block_decrypt(des3_cfb, Key0, Ivec, Data) ->
+ Key = check_des3_key(Key0),
+ block_crypt_nif(des_ede3_cfb, Key, Ivec, Data, false);
block_decrypt(aes_ige256, Key, Ivec, Data) ->
- aes_ige_256_decrypt(Key, Ivec, Data);
-block_decrypt(aes_cfb8, Key, Ivec, Data) ->
- aes_cfb_8_decrypt(Key, Ivec, Data);
-block_decrypt(aes_cfb128, Key, Ivec, Data) ->
- aes_cfb_128_decrypt(Key, Ivec, Data);
+ notsup_to_error(aes_ige_crypt_nif(Key, Ivec, Data, false));
block_decrypt(aes_gcm, Key, Ivec, {AAD, Data, Tag}) ->
- case aes_gcm_decrypt(Key, Ivec, AAD, Data, Tag) of
- notsup -> erlang:error(notsup);
- Return -> Return
- end;
+ aes_gcm_decrypt(Key, Ivec, AAD, Data, Tag);
block_decrypt(chacha20_poly1305, Key, Ivec, {AAD, Data, Tag}) ->
- case chacha20_poly1305_decrypt(Key, Ivec, AAD, Data, Tag) of
- notsup -> erlang:error(notsup);
- Return -> Return
- end;
-block_decrypt(rc2_cbc, Key, Ivec, Data) ->
- rc2_cbc_decrypt(Key, Ivec, Data).
+ chacha20_poly1305_decrypt(Key, Ivec, AAD, Data, Tag).
-spec block_encrypt(des_ecb | blowfish_ecb | aes_ecb, Key::iodata(), Data::iodata()) -> binary().
-block_encrypt(des_ecb, Key, Data) ->
- des_ecb_encrypt(Key, Data);
-block_encrypt(blowfish_ecb, Key, Data) ->
- blowfish_ecb_encrypt(Key, Data);
-block_encrypt(aes_ecb, Key, Data) ->
- aes_ecb_encrypt(Key, Data).
+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().
-block_decrypt(des_ecb, Key, Data) ->
- des_ecb_decrypt(Key, Data);
-block_decrypt(blowfish_ecb, Key, Data) ->
- blowfish_ecb_decrypt(Key, Data);
-block_decrypt(aes_ecb, Key, Data) ->
- aes_ecb_decrypt(Key, Data).
+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().
-next_iv(des_cbc, Data) ->
- des_cbc_ivec(Data);
-next_iv(des3_cbc, Data) ->
- des_cbc_ivec(Data);
-next_iv(aes_cbc, Data) ->
- aes_cbc_ivec(Data);
-next_iv(aes_ige, Data) ->
- aes_ige_ivec(Data).
+next_iv(Type, Data) when is_binary(Data) ->
+ IVecSize = case Type of
+ des_cbc -> 8;
+ des3_cbc -> 8;
+ aes_cbc -> 16;
+ aes_ige -> 32
+ 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().
-next_iv(des_cfb, Data, Ivec) ->
- des_cfb_ivec(Ivec, Data);
+next_iv(des_cfb, Data, IVec) ->
+ IVecAndData = list_to_binary([IVec, Data]),
+ {_, NewIVec} = split_binary(IVecAndData, byte_size(IVecAndData) - 8),
+ NewIVec;
next_iv(Type, Data, _Ivec) ->
next_iv(Type, Data).
stream_init(aes_ctr, Key, Ivec) ->
{aes_ctr, aes_ctr_stream_init(Key, Ivec)}.
stream_init(rc4, Key) ->
- {rc4, rc4_set_key(Key)}.
+ {rc4, notsup_to_error(rc4_set_key(Key))}.
stream_encrypt(State, Data0) ->
Data = iolist_to_binary(Data0),
@@ -438,8 +417,6 @@ strong_rand_bytes(Bytes) ->
end.
strong_rand_bytes_nif(_Bytes) -> ?nif_stub.
-rand_bytes(_Bytes, _Topmask, _Bottommask) -> ?nif_stub.
-
rand_uniform(From,To) when is_binary(From), is_binary(To) ->
case rand_uniform_nif(From,To) of
@@ -485,35 +462,31 @@ verify(dss, none, Data, Signature, Key) when is_binary(Data) ->
verify(dss, sha, {digest, Data}, Signature, Key);
verify(Alg, Type, Data, Signature, Key) when is_binary(Data) ->
verify(Alg, Type, {digest, hash(Type, Data)}, Signature, Key);
-verify(dss, Type, Data, Signature, Key) ->
- dss_verify_nif(Type, Data, Signature, map_ensure_int_as_bin(Key));
-verify(rsa, Type, DataOrDigest, Signature, Key) ->
- case rsa_verify_nif(Type, DataOrDigest, Signature, map_ensure_int_as_bin(Key)) of
- notsup -> erlang:error(notsup);
- Bool -> Bool
- end;
-verify(ecdsa, Type, DataOrDigest, Signature, [Key, Curve]) ->
- case ecdsa_verify_nif(Type, DataOrDigest, Signature, nif_curve_params(Curve), ensure_int_as_bin(Key)) of
- notsup -> erlang:error(notsup);
- Bool -> Bool
- end.
+verify(dss, Type, {digest, Digest}, Signature, Key) ->
+ dss_verify_nif(Type, Digest, Signature, map_ensure_int_as_bin(Key));
+verify(rsa, Type, {digest, Digest}, Signature, Key) ->
+ notsup_to_error(
+ rsa_verify_nif(Type, Digest, Signature, map_ensure_int_as_bin(Key)));
+verify(ecdsa, Type, {digest, Digest}, Signature, [Key, Curve]) ->
+ notsup_to_error(
+ ecdsa_verify_nif(Type, Digest, Signature, nif_curve_params(Curve), ensure_int_as_bin(Key))).
sign(dss, none, Data, Key) when is_binary(Data) ->
sign(dss, sha, {digest, Data}, Key);
sign(Alg, Type, Data, Key) when is_binary(Data) ->
sign(Alg, Type, {digest, hash(Type, Data)}, Key);
-sign(rsa, Type, DataOrDigest, Key) ->
- case rsa_sign_nif(Type, DataOrDigest, map_ensure_int_as_bin(Key)) of
- error -> erlang:error(badkey, [Type,DataOrDigest,Key]);
+sign(rsa, Type, {digest, Digest}, Key) ->
+ case rsa_sign_nif(Type, Digest, map_ensure_int_as_bin(Key)) of
+ error -> erlang:error(badkey, [Type,Digest,Key]);
Sign -> Sign
end;
-sign(dss, Type, DataOrDigest, Key) ->
- case dss_sign_nif(Type, DataOrDigest, map_ensure_int_as_bin(Key)) of
- error -> erlang:error(badkey, [DataOrDigest, Key]);
+sign(dss, Type, {digest, Digest}, Key) ->
+ case dss_sign_nif(Type, Digest, map_ensure_int_as_bin(Key)) of
+ error -> erlang:error(badkey, [Digest, Key]);
Sign -> Sign
end;
-sign(ecdsa, Type, DataOrDigest, [Key, Curve]) ->
- case ecdsa_sign_nif(Type, DataOrDigest, nif_curve_params(Curve), ensure_int_as_bin(Key)) of
- error -> erlang:error(badkey, [Type,DataOrDigest,Key]);
+sign(ecdsa, Type, {digest, Digest}, [Key, Curve]) ->
+ case ecdsa_sign_nif(Type, Digest, nif_curve_params(Curve), ensure_int_as_bin(Key)) of
+ error -> erlang:error(badkey, [Type,Digest,Key]);
Sign -> Sign
end.
@@ -574,14 +547,20 @@ exor(Bin1, Bin2) ->
generate_key(Type, Params) ->
generate_key(Type, Params, undefined).
-generate_key(dh, DHParameters, PrivateKey) ->
+generate_key(dh, DHParameters0, PrivateKey) ->
+ {DHParameters, Len} =
+ case DHParameters0 of
+ [P,G,L] -> {[P,G], L};
+ [P,G] -> {[P,G], 0}
+ end,
dh_generate_key_nif(ensure_int_as_bin(PrivateKey),
- map_ensure_int_as_bin(DHParameters), 0);
+ map_ensure_int_as_bin(DHParameters),
+ 0, Len);
generate_key(srp, {host, [Verifier, Generator, Prime, Version]}, PrivArg)
when is_binary(Verifier), is_binary(Generator), is_binary(Prime), is_atom(Version) ->
Private = case PrivArg of
- undefined -> random_bytes(32);
+ undefined -> strong_rand_bytes(32);
_ -> ensure_int_as_bin(PrivArg)
end,
host_srp_gen_key(Private, Verifier, Generator, Prime, Version);
@@ -589,7 +568,7 @@ generate_key(srp, {host, [Verifier, Generator, Prime, Version]}, PrivArg)
generate_key(srp, {user, [Generator, Prime, Version]}, PrivateArg)
when is_binary(Generator), is_binary(Prime), is_atom(Version) ->
Private = case PrivateArg of
- undefined -> random_bytes(32);
+ undefined -> strong_rand_bytes(32);
_ -> PrivateArg
end,
user_srp_gen_key(Private, Generator, Prime);
@@ -618,8 +597,9 @@ compute_key(srp, HostPublic, {UserPublic, UserPrivate},
HostPubBin, Prime);
[S] -> S
end,
+ notsup_to_error(
srp_user_secret_nif(ensure_int_as_bin(UserPrivate), Scrambler, HostPubBin,
- Multiplier, Generator, DerivedKey, Prime);
+ Multiplier, Generator, DerivedKey, Prime));
compute_key(srp, UserPublic, {HostPublic, HostPrivate},
{host,[Verifier, Prime, Version | ScramblerArg]}) when
@@ -631,24 +611,15 @@ compute_key(srp, UserPublic, {HostPublic, HostPrivate},
[] -> srp_scrambler(Version, UserPubBin, ensure_int_as_bin(HostPublic), Prime);
[S] -> S
end,
+ notsup_to_error(
srp_host_secret_nif(Verifier, ensure_int_as_bin(HostPrivate), Scrambler,
- UserPubBin, Prime);
+ UserPubBin, Prime));
compute_key(ecdh, Others, My, Curve) ->
ecdh_compute_key_nif(ensure_int_as_bin(Others),
nif_curve_params(Curve),
ensure_int_as_bin(My)).
-
-random_bytes(N) ->
- try strong_rand_bytes(N) of
- RandBytes ->
- RandBytes
- catch
- error:low_entropy ->
- rand_bytes(N)
- end.
-
%%--------------------------------------------------------------------
%%% On load
%%--------------------------------------------------------------------
@@ -677,7 +648,8 @@ on_load() ->
end
end,
Lib = filename:join([PrivDir, "lib", LibName]),
- Status = case erlang:load_nif(Lib, {?CRYPTO_NIF_VSN,path2bin(Lib)}) of
+ LibBin = path2bin(Lib),
+ Status = case erlang:load_nif(Lib, {?CRYPTO_NIF_VSN,LibBin}) of
ok -> ok;
{error, {load_failed, _}}=Error1 ->
ArchLibDir =
@@ -689,7 +661,8 @@ on_load() ->
[] -> Error1;
_ ->
ArchLib = filename:join([ArchLibDir, LibName]),
- erlang:load_nif(ArchLib, {?CRYPTO_NIF_VSN,path2bin(ArchLib)})
+ ArchBin = path2bin(ArchLib),
+ erlang:load_nif(ArchLib, {?CRYPTO_NIF_VSN,ArchBin})
end;
Error1 -> Error1
end,
@@ -714,46 +687,30 @@ path2bin(Path) when is_list(Path) ->
max_bytes() ->
?MAX_BYTES_TO_NIF.
+notsup_to_error(notsup) ->
+ erlang:error(notsup);
+notsup_to_error(Other) ->
+ Other.
+
%% HASH --------------------------------------------------------------------
-hash(Hash, Data, Size, Max, initial) when Size =< Max ->
- do_hash(Hash, Data);
-hash(State0, Data, Size, Max, continue) when Size =< Max ->
- State = do_hash_update(State0, Data),
- hash_final(State);
-hash(Hash, Data, _Size, Max, initial) ->
- <<Increment:Max/binary, Rest/binary>> = Data,
+hash(Hash, Data, Size, Max) when Size =< Max ->
+ notsup_to_error(hash_nif(Hash, Data));
+hash(Hash, Data, Size, Max) ->
State0 = hash_init(Hash),
- State = do_hash_update(State0, Increment),
- hash(State, Rest, erlang:byte_size(Rest), max_bytes(), continue);
-hash(State0, Data, _Size, MaxByts, continue) ->
- <<Increment:MaxByts/binary, Rest/binary>> = Data,
- State = do_hash_update(State0, Increment),
- hash(State, Rest, erlang:byte_size(Rest), max_bytes(), continue).
-
-do_hash(md5, Data) -> md5(Data);
-do_hash(md4, Data) -> md4(Data);
-do_hash(sha, Data) -> sha(Data);
-do_hash(ripemd160, Data) -> ripemd160(Data);
-do_hash(sha224, Data) -> sha224(Data);
-do_hash(sha256, Data) -> sha256(Data);
-do_hash(sha384, Data) -> sha384(Data);
-do_hash(sha512, Data) -> sha512(Data).
+ State1 = hash_update(State0, Data, Size, Max),
+ hash_final(State1).
hash_update(State, Data, Size, MaxBytes) when Size =< MaxBytes ->
- do_hash_update(State, Data);
+ notsup_to_error(hash_update_nif(State, Data));
hash_update(State0, Data, _, MaxBytes) ->
<<Increment:MaxBytes/binary, Rest/binary>> = Data,
- State = do_hash_update(State0, Increment),
+ State = notsup_to_error(hash_update_nif(State0, Increment)),
hash_update(State, Rest, erlang:byte_size(Rest), MaxBytes).
-do_hash_update({md5,Context}, Data) -> {md5, md5_update(Context,Data)};
-do_hash_update({md4,Context}, Data) -> {md4, md4_update(Context,Data)};
-do_hash_update({sha,Context}, Data) -> {sha, sha_update(Context,Data)};
-do_hash_update({ripemd160,Context}, Data) -> {ripemd160, ripemd160_update(Context,Data)};
-do_hash_update({sha224,Context}, Data) -> {sha224, sha224_update(Context,Data)};
-do_hash_update({sha256,Context}, Data) -> {sha256, sha256_update(Context,Data)};
-do_hash_update({sha384,Context}, Data) -> {sha384, sha384_update(Context,Data)};
-do_hash_update({sha512,Context}, Data) -> {sha512, sha512_update(Context,Data)}.
+hash_nif(_Hash, _Data) -> ?nif_stub.
+hash_init_nif(_Hash) -> ?nif_stub.
+hash_update_nif(_State, _Data) -> ?nif_stub.
+hash_final_nif(_State) -> ?nif_stub.
%%
@@ -765,10 +722,14 @@ do_hash_update({sha512,Context}, Data) -> {sha512, sha512_update(Context,Data
-spec md5_update(binary(), iodata()) -> binary().
-spec md5_final(binary()) -> binary().
-md5(_Data) -> ?nif_stub.
-md5_init() -> ?nif_stub.
-md5_update(_Context, _Data) -> ?nif_stub.
-md5_final(_Context) -> ?nif_stub.
+md5(Data) ->
+ hash(md5, Data).
+md5_init() ->
+ hash_init(md5).
+md5_update(Context, Data) ->
+ hash_update(Context, Data).
+md5_final(Context) ->
+ hash_final(Context).
%%
%% MD4
@@ -778,24 +739,14 @@ md5_final(_Context) -> ?nif_stub.
-spec md4_update(binary(), iodata()) -> binary().
-spec md4_final(binary()) -> binary().
-md4(_Data) -> ?nif_stub.
-md4_init() -> ?nif_stub.
-md4_update(_Context, _Data) -> ?nif_stub.
-md4_final(_Context) -> ?nif_stub.
-
-%%
-%% RIPEMD160
-%%
-
--spec ripemd160(iodata()) -> binary().
--spec ripemd160_init() -> binary().
--spec ripemd160_update(binary(), iodata()) -> binary().
--spec ripemd160_final(binary()) -> binary().
-
-ripemd160(_Data) -> ?nif_stub.
-ripemd160_init() -> ?nif_stub.
-ripemd160_update(_Context, _Data) -> ?nif_stub.
-ripemd160_final(_Context) -> ?nif_stub.
+md4(Data) ->
+ hash(md4, Data).
+md4_init() ->
+ hash_init(md4).
+md4_update(Context, Data) ->
+ hash_update(Context, Data).
+md4_final(Context) ->
+ hash_final(Context).
%%
%% SHA
@@ -805,196 +756,44 @@ ripemd160_final(_Context) -> ?nif_stub.
-spec sha_update(binary(), iodata()) -> binary().
-spec sha_final(binary()) -> binary().
-sha(_Data) -> ?nif_stub.
-sha_init() -> ?nif_stub.
-sha_update(_Context, _Data) -> ?nif_stub.
-sha_final(_Context) -> ?nif_stub.
-
-%
-%% SHA224
-%%
--spec sha224(iodata()) -> binary().
--spec sha224_init() -> binary().
--spec sha224_update(binary(), iodata()) -> binary().
--spec sha224_final(binary()) -> binary().
-
-sha224(Data) ->
- case sha224_nif(Data) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-sha224_init() ->
- case sha224_init_nif() of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-sha224_update(Context, Data) ->
- case sha224_update_nif(Context, Data) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-sha224_final(Context) ->
- case sha224_final_nif(Context) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-
-sha224_nif(_Data) -> ?nif_stub.
-sha224_init_nif() -> ?nif_stub.
-sha224_update_nif(_Context, _Data) -> ?nif_stub.
-sha224_final_nif(_Context) -> ?nif_stub.
-
-%
-%% SHA256
-%%
--spec sha256(iodata()) -> binary().
--spec sha256_init() -> binary().
--spec sha256_update(binary(), iodata()) -> binary().
--spec sha256_final(binary()) -> binary().
-
-sha256(Data) ->
- case sha256_nif(Data) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-sha256_init() ->
- case sha256_init_nif() of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-sha256_update(Context, Data) ->
- case sha256_update_nif(Context, Data) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-sha256_final(Context) ->
- case sha256_final_nif(Context) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-
-sha256_nif(_Data) -> ?nif_stub.
-sha256_init_nif() -> ?nif_stub.
-sha256_update_nif(_Context, _Data) -> ?nif_stub.
-sha256_final_nif(_Context) -> ?nif_stub.
-
-%
-%% SHA384
-%%
--spec sha384(iodata()) -> binary().
--spec sha384_init() -> binary().
--spec sha384_update(binary(), iodata()) -> binary().
--spec sha384_final(binary()) -> binary().
-
-sha384(Data) ->
- case sha384_nif(Data) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-sha384_init() ->
- case sha384_init_nif() of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-sha384_update(Context, Data) ->
- case sha384_update_nif(Context, Data) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-sha384_final(Context) ->
- case sha384_final_nif(Context) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-
-sha384_nif(_Data) -> ?nif_stub.
-sha384_init_nif() -> ?nif_stub.
-sha384_update_nif(_Context, _Data) -> ?nif_stub.
-sha384_final_nif(_Context) -> ?nif_stub.
-
-%
-%% SHA512
-%%
--spec sha512(iodata()) -> binary().
--spec sha512_init() -> binary().
--spec sha512_update(binary(), iodata()) -> binary().
--spec sha512_final(binary()) -> binary().
-
-sha512(Data) ->
- case sha512_nif(Data) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-sha512_init() ->
- case sha512_init_nif() of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-sha512_update(Context, Data) ->
- case sha512_update_nif(Context, Data) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-sha512_final(Context) ->
- case sha512_final_nif(Context) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-
-sha512_nif(_Data) -> ?nif_stub.
-sha512_init_nif() -> ?nif_stub.
-sha512_update_nif(_Context, _Data) -> ?nif_stub.
-sha512_final_nif(_Context) -> ?nif_stub.
+sha(Data) ->
+ hash(sha, Data).
+sha_init() ->
+ hash_init(sha).
+sha_update(Context, Data) ->
+ hash_update(Context, Data).
+sha_final(Context) ->
+ hash_final(Context).
%% HMAC --------------------------------------------------------------------
-hmac(Type, Key, Data, MacSize, Size, MaxBytes, initial) when Size =< MaxBytes ->
+hmac(Type, Key, Data, MacSize, Size, MaxBytes) when Size =< MaxBytes ->
+ notsup_to_error(
case MacSize of
- undefined ->
- do_hmac(Type, Key, Data);
- _ ->
- do_hmac(Type, Key, Data, MacSize)
- end;
-hmac(Type, Key, Data, MacSize, _, MaxBytes, initial) ->
- <<Increment:MaxBytes/binary, Rest/binary>> = Data,
+ undefined -> hmac_nif(Type, Key, Data);
+ _ -> hmac_nif(Type, Key, Data, MacSize)
+ end);
+hmac(Type, Key, Data, MacSize, Size, MaxBytes) ->
State0 = hmac_init(Type, Key),
- State = hmac_update(State0, Increment),
- hmac(State, Rest, MacSize, erlang:byte_size(Rest), max_bytes(), continue).
-hmac(State0, Data, MacSize, Size, MaxBytes, continue) when Size =< MaxBytes ->
- State = hmac_update(State0, Data),
+ State1 = hmac_update(State0, Data, Size, MaxBytes),
case MacSize of
- undefined ->
- hmac_final(State);
- _ ->
- hmac_final_n(State, MacSize)
- end;
-hmac(State0, Data, MacSize, _Size, MaxBytes, continue) ->
- <<Increment:MaxBytes/binary, Rest/binary>> = Data,
- State = hmac_update(State0, Increment),
- hmac(State, Rest, MacSize, erlang:byte_size(Rest), max_bytes(), continue).
+ undefined -> hmac_final(State1);
+ _ -> hmac_final_n(State1, MacSize)
+ end.
hmac_update(State, Data, Size, MaxBytes) when Size =< MaxBytes ->
- do_hmac_update(State, Data);
+ notsup_to_error(hmac_update_nif(State, Data));
hmac_update(State0, Data, _, MaxBytes) ->
<<Increment:MaxBytes/binary, Rest/binary>> = Data,
- State = do_hmac_update(State0, Increment),
+ State = notsup_to_error(hmac_update_nif(State0, Increment)),
hmac_update(State, Rest, erlang:byte_size(Rest), MaxBytes).
-do_hmac(md5, Key, Data) -> md5_mac(Key, Data);
-do_hmac(sha, Key, Data) -> sha_mac(Key, Data);
-do_hmac(sha224, Key, Data) -> sha224_mac(Key, Data);
-do_hmac(sha256, Key, Data) -> sha256_mac(Key, Data);
-do_hmac(sha384, Key, Data) -> sha384_mac(Key, Data);
-do_hmac(sha512, Key, Data) -> sha512_mac(Key, Data).
-
-do_hmac(md5, Key, Data, Size) -> md5_mac_n(Key, Data, Size);
-do_hmac(sha, Key, Data, Size) -> sha_mac_n(Key, Data, Size);
-do_hmac(sha224, Key, Data, Size) -> sha224_mac(Key, Data, Size);
-do_hmac(sha256, Key, Data, Size) -> sha256_mac(Key, Data, Size);
-do_hmac(sha384, Key, Data, Size) -> sha384_mac(Key, Data, Size);
-do_hmac(sha512, Key, Data, Size) -> sha512_mac(Key, Data, Size).
-
-do_hmac_update(_Context, _Data) -> ? nif_stub.
+hmac_nif(_Type, _Key, _Data) -> ?nif_stub.
+hmac_nif(_Type, _Key, _Data, _MacSize) -> ?nif_stub.
+hmac_init_nif(_Type, _Key) -> ?nif_stub.
+hmac_update_nif(_Context, _Data) -> ?nif_stub.
+hmac_final_nif(_Context) -> ?nif_stub.
+hmac_final_nif(_Context, _MacSize) -> ?nif_stub.
%%
%% MD5_MAC
@@ -1002,97 +801,39 @@ do_hmac_update(_Context, _Data) -> ? nif_stub.
-spec md5_mac(iodata(), iodata()) -> binary().
-spec md5_mac_96(iodata(), iodata()) -> binary().
-md5_mac(Key, Data) ->
- md5_mac_n(Key,Data,16).
+md5_mac(Key, Data) -> hmac(md5, Key, Data).
-md5_mac_96(Key, Data) ->
- md5_mac_n(Key,Data,12).
+md5_mac_96(Key, Data) -> hmac(md5, Key, Data, 12).
-md5_mac_n(_Key,_Data,_MacSz) -> ?nif_stub.
-
%%
%% SHA_MAC
%%
-spec sha_mac(iodata(), iodata()) -> binary().
-spec sha_mac_96(iodata(), iodata()) -> binary().
-sha_mac(Key, Data) ->
- sha_mac_n(Key,Data,20).
-
-sha_mac(Key, Data, Size) ->
- sha_mac_n(Key, Data, Size).
+sha_mac(Key, Data) -> hmac(sha, Key, Data).
-sha_mac_96(Key, Data) ->
- sha_mac_n(Key,Data,12).
+sha_mac(Key, Data, Size) -> hmac(sha, Key, Data, Size).
-sha_mac_n(_Key,_Data,_MacSz) -> ?nif_stub.
+sha_mac_96(Key, Data) -> hmac(sha, Key, Data, 12).
-%%
-%% SHA224_MAC
-%%
--spec sha224_mac(iodata(), iodata()) -> binary().
-
-sha224_mac(Key, Data) ->
- sha224_mac(Key, Data, 224 div 8).
-
-sha224_mac(Key, Data, Size) ->
- case sha224_mac_nif(Key, Data, Size) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-
-sha224_mac_nif(_Key,_Data,_MacSz) -> ?nif_stub.
-
-%%
-%% SHA256_MAC
-%%
--spec sha256_mac(iodata(), iodata()) -> binary().
-
-sha256_mac(Key, Data) ->
- sha256_mac(Key, Data, 256 div 8).
-
-sha256_mac(Key, Data, Size) ->
- case sha256_mac_nif(Key, Data, Size) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-
-sha256_mac_nif(_Key,_Data,_MacSz) -> ?nif_stub.
-
-%%
-%% SHA384_MAC
-%%
--spec sha384_mac(iodata(), iodata()) -> binary().
-
-sha384_mac(Key, Data) ->
- sha384_mac(Key, Data, 384 div 8).
-
-sha384_mac(Key, Data, Size) ->
- case sha384_mac_nif(Key, Data, Size) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
+%% CIPHERS --------------------------------------------------------------------
-sha384_mac_nif(_Key,_Data,_MacSz) -> ?nif_stub.
+block_crypt_nif(_Type, _Key, _Ivec, _Text, _IsEncrypt) -> ?nif_stub.
+block_crypt_nif(_Type, _Key, _Text, _IsEncrypt) -> ?nif_stub.
-%%
-%% SHA512_MAC
-%%
--spec sha512_mac(iodata(), iodata()) -> binary().
+aes_cfb_128_crypt_nif(_Key, _Ivec, _Text, _IsEncrypt) -> ?nif_stub.
-sha512_mac(Key, Data) ->
- sha512_mac(Key, Data, 512 div 8).
-
-sha512_mac(Key, Data, MacSz) ->
- case sha512_mac_nif(Key, Data, MacSz) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
+check_des3_key(Key) ->
+ case lists:map(fun erlang:iolist_to_binary/1, Key) of
+ ValidKey = [B1, B2, B3] when byte_size(B1) =:= 8,
+ byte_size(B2) =:= 8,
+ byte_size(B3) =:= 8 ->
+ ValidKey;
+ _ ->
+ error(badarg)
end.
-sha512_mac_nif(_Key,_Data,_MacSz) -> ?nif_stub.
-
-%% CIPHERS --------------------------------------------------------------------
-
%%
%% DES - in electronic codebook mode (ECB)
%%
@@ -1100,10 +841,9 @@ sha512_mac_nif(_Key,_Data,_MacSz) -> ?nif_stub.
-spec des_ecb_decrypt(iodata(), iodata()) -> binary().
des_ecb_encrypt(Key, Data) ->
- des_ecb_crypt(Key, Data, true).
+ block_encrypt(des_ecb, Key, Data).
des_ecb_decrypt(Key, Data) ->
- des_ecb_crypt(Key, Data, false).
-des_ecb_crypt(_Key, _Data, _IsEncrypt) -> ?nif_stub.
+ block_decrypt(des_ecb, Key, Data).
%%
%% DES3 - in cipher block chaining mode (CBC)
@@ -1114,16 +854,14 @@ des_ecb_crypt(_Key, _Data, _IsEncrypt) -> ?nif_stub.
binary().
des3_cbc_encrypt(Key1, Key2, Key3, IVec, Data) ->
- des_ede3_cbc_crypt(Key1, Key2, Key3, IVec, Data, true).
+ block_encrypt(des3_cbc, [Key1, Key2, Key3], IVec, Data).
des_ede3_cbc_encrypt(Key1, Key2, Key3, IVec, Data) ->
- des_ede3_cbc_crypt(Key1, Key2, Key3, IVec, Data, true).
+ block_encrypt(des_ede3, [Key1, Key2, Key3], IVec, Data).
des3_cbc_decrypt(Key1, Key2, Key3, IVec, Data) ->
- des_ede3_cbc_crypt(Key1, Key2, Key3, IVec, Data, false).
+ block_decrypt(des3_cbc, [Key1, Key2, Key3], IVec, Data).
des_ede3_cbc_decrypt(Key1, Key2, Key3, IVec, Data) ->
- des_ede3_cbc_crypt(Key1, Key2, Key3, IVec, Data, false).
-
-des_ede3_cbc_crypt(_Key1, _Key2, _Key3, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
+ block_decrypt(des_ede3, [Key1, Key2, Key3], IVec, Data).
%%
%% DES3 - in 8-bits cipher feedback mode (CFB)
@@ -1134,18 +872,10 @@ des_ede3_cbc_crypt(_Key1, _Key2, _Key3, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
binary().
des3_cfb_encrypt(Key1, Key2, Key3, IVec, Data) ->
- des_ede3_cfb_crypt(Key1, Key2, Key3, IVec, Data, true).
+ block_encrypt(des3_cfb, [Key1, Key2, Key3], IVec, Data).
des3_cfb_decrypt(Key1, Key2, Key3, IVec, Data) ->
- des_ede3_cfb_crypt(Key1, Key2, Key3, IVec, Data, false).
-
-des_ede3_cfb_crypt(Key1, Key2, Key3, IVec, Data, IsEncrypt) ->
- case des_ede3_cfb_crypt_nif(Key1,Key2,Key3,IVec,Data,IsEncrypt) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-
-des_ede3_cfb_crypt_nif(_Key1, _Key2, _Key3, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
+ block_decrypt(des3_cfb, [Key1, Key2, Key3], IVec, Data).
%%
%% Blowfish
@@ -1159,67 +889,48 @@ des_ede3_cfb_crypt_nif(_Key1, _Key2, _Key3, _IVec, _Data, _IsEncrypt) -> ?nif_st
-spec blowfish_ofb64_encrypt(iodata(), binary(), iodata()) -> binary().
blowfish_ecb_encrypt(Key, Data) ->
- bf_ecb_crypt(Key,Data, true).
+ block_encrypt(blowfish_ecb, Key, Data).
blowfish_ecb_decrypt(Key, Data) ->
- bf_ecb_crypt(Key,Data, false).
-
-bf_ecb_crypt(_Key,_Data,_IsEncrypt) -> ?nif_stub.
+ block_decrypt(blowfish_ecb, Key, Data).
blowfish_cbc_encrypt(Key, IVec, Data) ->
- bf_cbc_crypt(Key,IVec,Data,true).
+ block_encrypt(blowfish_cbc, Key, IVec, Data).
blowfish_cbc_decrypt(Key, IVec, Data) ->
- bf_cbc_crypt(Key,IVec,Data,false).
-
-bf_cbc_crypt(_Key,_IVec,_Data,_IsEncrypt) -> ?nif_stub.
+ block_decrypt(blowfish_cbc, Key, IVec, Data).
blowfish_cfb64_encrypt(Key, IVec, Data) ->
- bf_cfb64_crypt(Key, IVec, Data, true).
+ block_encrypt(blowfish_cfb64, Key, IVec, Data).
blowfish_cfb64_decrypt(Key, IVec, Data) ->
- bf_cfb64_crypt(Key, IVec, Data, false).
-
-bf_cfb64_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
-
-blowfish_ofb64_decrypt(Key, Ivec, Data) ->
- blowfish_ofb64_encrypt(Key, Ivec, Data).
+ block_decrypt(blowfish_cfb64, Key, IVec, Data).
-blowfish_ofb64_encrypt(_Key, _IVec, _Data) -> ?nif_stub.
+blowfish_ofb64_encrypt(Key, IVec, Data) ->
+ block_encrypt(blowfish_ofb64, Key, IVec, Data).
%%
-%% AES in cipher feedback mode (CFB) - 8 bit shift
-%%
--spec aes_cfb_8_encrypt(iodata(), binary(), iodata()) -> binary().
--spec aes_cfb_8_decrypt(iodata(), binary(), iodata()) -> binary().
-
-aes_cfb_8_encrypt(Key, IVec, Data) ->
- aes_cfb_8_crypt(Key, IVec, Data, true).
-
-aes_cfb_8_decrypt(Key, IVec, Data) ->
- aes_cfb_8_crypt(Key, IVec, Data, false).
-
-aes_cfb_8_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
-
-%%
%% AES in cipher feedback mode (CFB) - 128 bit shift
%%
-spec aes_cfb_128_encrypt(iodata(), binary(), iodata()) -> binary().
-spec aes_cfb_128_decrypt(iodata(), binary(), iodata()) -> binary().
aes_cfb_128_encrypt(Key, IVec, Data) ->
- aes_cfb_128_crypt(Key, IVec, Data, true).
+ %% block_encrypt(aes_cfb128, Key, IVec, Data).
+ aes_cfb_128_crypt_nif(Key, IVec, Data, true).
-aes_cfb_128_decrypt(Key, IVec, Data) ->
- aes_cfb_128_crypt(Key, IVec, Data, false).
-aes_cfb_128_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
+aes_cfb_128_decrypt(Key, IVec, Data) ->
+ block_decrypt(aes_cfb128, Key, IVec, Data).
%%
%% AES - in Galois/Counter Mode (GCM)
%%
-aes_gcm_encrypt(_Key, _Ivec, _AAD, _In) -> ?nif_stub.
+%% The default tag length is EVP_GCM_TLS_TAG_LEN(16),
+aes_gcm_encrypt(Key, Ivec, AAD, In) ->
+ aes_gcm_encrypt(Key, Ivec, AAD, In, 16).
+aes_gcm_encrypt(_Key, _Ivec, _AAD, _In, _TagLength) -> ?nif_stub.
aes_gcm_decrypt(_Key, _Ivec, _AAD, _In, _Tag) -> ?nif_stub.
%%
@@ -1235,12 +946,10 @@ chacha20_poly1305_decrypt(_Key, _Ivec, _AAD, _In, _Tag) -> ?nif_stub.
-spec des_cbc_decrypt(iodata(), binary(), iodata()) -> binary().
des_cbc_encrypt(Key, IVec, Data) ->
- des_cbc_crypt(Key, IVec, Data, true).
+ block_encrypt(des_cbc, Key, IVec, Data).
des_cbc_decrypt(Key, IVec, Data) ->
- des_cbc_crypt(Key, IVec, Data, false).
-
-des_cbc_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
+ block_decrypt(des_cbc, Key, IVec, Data).
%%
%% dec_cbc_ivec(Data) -> binary()
@@ -1250,11 +959,8 @@ des_cbc_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
%%
-spec des_cbc_ivec(iodata()) -> binary().
-des_cbc_ivec(Data) when is_binary(Data) ->
- {_, IVec} = split_binary(Data, size(Data) - 8),
- IVec;
-des_cbc_ivec(Data) when is_list(Data) ->
- des_cbc_ivec(list_to_binary(Data)).
+des_cbc_ivec(Data) ->
+ next_iv(des_cbc, Data).
%%
%% DES - in 8-bits cipher feedback mode (CFB)
@@ -1263,12 +969,10 @@ des_cbc_ivec(Data) when is_list(Data) ->
-spec des_cfb_decrypt(iodata(), binary(), iodata()) -> binary().
des_cfb_encrypt(Key, IVec, Data) ->
- des_cfb_crypt(Key, IVec, Data, true).
+ block_encrypt(des_cfb, Key, IVec, Data).
des_cfb_decrypt(Key, IVec, Data) ->
- des_cfb_crypt(Key, IVec, Data, false).
-
-des_cfb_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
+ block_decrypt(des_cfb, Key, IVec, Data).
%%
%% dec_cfb_ivec(IVec, Data) -> binary()
@@ -1280,9 +984,7 @@ des_cfb_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
-spec des_cfb_ivec(iodata(), iodata()) -> binary().
des_cfb_ivec(IVec, Data) ->
- IVecAndData = list_to_binary([IVec, Data]),
- {_, NewIVec} = split_binary(IVecAndData, byte_size(IVecAndData) - 8),
- NewIVec.
+ next_iv(des_cfb, Data, IVec).
%%
@@ -1298,18 +1000,16 @@ des_cfb_ivec(IVec, Data) ->
binary().
aes_cbc_128_encrypt(Key, IVec, Data) ->
- aes_cbc_crypt(Key, IVec, Data, true).
+ block_encrypt(aes_cbc128, Key, IVec, Data).
aes_cbc_128_decrypt(Key, IVec, Data) ->
- aes_cbc_crypt(Key, IVec, Data, false).
+ block_decrypt(aes_cbc128, Key, IVec, Data).
aes_cbc_256_encrypt(Key, IVec, Data) ->
- aes_cbc_crypt(Key, IVec, Data, true).
+ block_encrypt(aes_cbc256, Key, IVec, Data).
aes_cbc_256_decrypt(Key, IVec, Data) ->
- aes_cbc_crypt(Key, IVec, Data, false).
-
-aes_cbc_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
+ block_decrypt(aes_cbc256, Key, IVec, Data).
%%
%% aes_cbc_ivec(Data) -> binary()
@@ -1318,47 +1018,15 @@ aes_cbc_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
%% aes_cbc_*_[encrypt|decrypt].
%% IVec size: 16 bytes
%%
-aes_cbc_ivec(Data) when is_binary(Data) ->
- {_, IVec} = split_binary(Data, size(Data) - 16),
- IVec;
-aes_cbc_ivec(Data) when is_list(Data) ->
- aes_cbc_ivec(list_to_binary(Data)).
-
+aes_cbc_ivec(Data) ->
+ next_iv(aes_cbc, Data).
%%
%% AES - with 256 bit key in infinite garble extension mode (IGE)
%%
--spec aes_ige_256_decrypt(iodata(), binary(), iodata()) ->
- binary().
-
-aes_ige_256_encrypt(Key, IVec, Data) ->
- aes_ige_crypt(Key, IVec, Data, true).
-
-aes_ige_256_decrypt(Key, IVec, Data) ->
- aes_ige_crypt(Key, IVec, Data, false).
-
-aes_ige_crypt(Key, IVec, Data, IsEncrypt) ->
- case aes_ige_crypt_nif(Key,IVec,Data,IsEncrypt) of
- notsup -> erlang:error(notsup);
- Bin -> Bin
- end.
-
aes_ige_crypt_nif(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
-%%
-%% aes_ige_ivec(Data) -> binary()
-%%
-%% Returns the IVec to be used in the next iteration of
-%% aes_ige_*_[encrypt|decrypt].
-%% IVec size: 32 bytes
-%%
-aes_ige_ivec(Data) when is_binary(Data) ->
- {_, IVec} = split_binary(Data, size(Data) - 32),
- IVec;
-aes_ige_ivec(Data) when is_list(Data) ->
- aes_ige_ivec(list_to_binary(Data)).
-
%% Stream ciphers --------------------------------------------------------------------
@@ -1397,22 +1065,11 @@ do_stream_decrypt({rc4, State0}, Data) ->
aes_ctr_encrypt(_Key, _IVec, _Data) -> ?nif_stub.
aes_ctr_decrypt(_Key, _IVec, _Cipher) -> ?nif_stub.
-%%
-%% AES - in electronic codebook mode (ECB)
-%%
-aes_ecb_encrypt(Key, Data) ->
- aes_ecb_crypt(Key, Data, true).
-
-aes_ecb_decrypt(Key, Data) ->
- aes_ecb_crypt(Key, Data, false).
-
-aes_ecb_crypt(_Key, __Data, _IsEncrypt) -> ?nif_stub.
-
%%
%% AES - in counter mode (CTR) with state maintained for multi-call streaming
%%
--type ctr_state() :: { iodata(), binary(), binary(), integer() }.
+-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()) ->
@@ -1420,10 +1077,9 @@ aes_ecb_crypt(_Key, __Data, _IsEncrypt) -> ?nif_stub.
-spec aes_ctr_stream_decrypt(ctr_state(), binary()) ->
{ ctr_state(), binary() }.
-aes_ctr_stream_init(Key, IVec) ->
- {Key, IVec, << 0:128 >>, 0}.
-aes_ctr_stream_encrypt({_Key, _IVec, _ECount, _Num}=_State, _Data) -> ?nif_stub.
-aes_ctr_stream_decrypt({_Key, _IVec, _ECount, _Num}=_State, _Cipher) -> ?nif_stub.
+aes_ctr_stream_init(_Key, _IVec) -> ?nif_stub.
+aes_ctr_stream_encrypt(_State, _Data) -> ?nif_stub.
+aes_ctr_stream_decrypt(_State, _Cipher) -> ?nif_stub.
%%
%% RC4 - symmetric stream cipher
@@ -1438,21 +1094,19 @@ rc4_encrypt_with_state(_State, _Data) -> ?nif_stub.
%% RC2 block cipher
rc2_cbc_encrypt(Key, IVec, Data) ->
- rc2_cbc_crypt(Key,IVec,Data,true).
+ block_encrypt(rc2_cbc, Key, IVec, Data).
rc2_cbc_decrypt(Key, IVec, Data) ->
- rc2_cbc_crypt(Key,IVec,Data,false).
-
-rc2_cbc_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
+ block_decrypt(rc2_cbc, Key, IVec, Data).
%%
%% RC2 - 40 bits block cipher - Backwards compatibility not documented.
%%
rc2_40_cbc_encrypt(Key, IVec, Data) when erlang:byte_size(Key) == 5 ->
- rc2_cbc_crypt(Key,IVec,Data,true).
+ block_encrypt(rc2_cbc, Key, IVec, Data).
rc2_40_cbc_decrypt(Key, IVec, Data) when erlang:byte_size(Key) == 5 ->
- rc2_cbc_crypt(Key,IVec,Data,false).
+ block_decrypt(rc2_cbc, Key, IVec, Data).
%% Secure remote password -------------------------------------------------------------------
@@ -1470,16 +1124,18 @@ host_srp_gen_key(Private, Verifier, Generator, Prime, Version) ->
case srp_value_B_nif(Multiplier, Verifier, Generator, Private, Prime) of
error ->
error;
+ notsup ->
+ erlang:error(notsup);
Public ->
{Public, Private}
end.
srp_multiplier('6a', Generator, Prime) ->
%% k = SHA1(N | PAD(g)) from http://srp.stanford.edu/design.html
- C0 = sha_init(),
- C1 = sha_update(C0, Prime),
- C2 = sha_update(C1, srp_pad_to(erlang:byte_size(Prime), Generator)),
- sha_final(C2);
+ C0 = hash_init(sha),
+ C1 = hash_update(C0, Prime),
+ C2 = hash_update(C1, srp_pad_to(erlang:byte_size(Prime), Generator)),
+ hash_final(C2);
srp_multiplier('6', _, _) ->
<<3/integer>>;
srp_multiplier('3', _, _) ->
@@ -1488,10 +1144,10 @@ srp_multiplier('3', _, _) ->
srp_scrambler(Version, UserPublic, HostPublic, Prime) when Version == '6'; Version == '6a'->
%% SHA1(PAD(A) | PAD(B)) from http://srp.stanford.edu/design.html
PadLength = erlang:byte_size(Prime),
- C0 = sha_init(),
- C1 = sha_update(C0, srp_pad_to(PadLength, UserPublic)),
- C2 = sha_update(C1, srp_pad_to(PadLength, HostPublic)),
- sha_final(C2);
+ C0 = hash_init(sha),
+ C1 = hash_update(C0, srp_pad_to(PadLength, UserPublic)),
+ C2 = hash_update(C1, srp_pad_to(PadLength, HostPublic)),
+ hash_final(C2);
srp_scrambler('3', _, HostPublic, _Prime) ->
%% The parameter u is a 32-bit unsigned integer which takes its value
%% from the first 32 bits of the SHA1 hash of B, MSB first.
@@ -1515,13 +1171,13 @@ srp_value_B_nif(_Multiplier, _Verifier, _Generator, _Exponent, _Prime) -> ?nif_s
%% Digital signatures --------------------------------------------------------------------
-rsa_sign_nif(_Type,_Data,_Key) -> ?nif_stub.
-dss_sign_nif(_Type,_Data,_Key) -> ?nif_stub.
-ecdsa_sign_nif(_Type, _DataOrDigest, _Curve, _Key) -> ?nif_stub.
+rsa_sign_nif(_Type,_Digest,_Key) -> ?nif_stub.
+dss_sign_nif(_Type,_Digest,_Key) -> ?nif_stub.
+ecdsa_sign_nif(_Type, _Digest, _Curve, _Key) -> ?nif_stub.
-dss_verify_nif(_Type, _Data, _Signature, _Key) -> ?nif_stub.
-rsa_verify_nif(_Type, _Data, _Signature, _Key) -> ?nif_stub.
-ecdsa_verify_nif(_Type, _DataOrDigest, _Signature, _Curve, _Key) -> ?nif_stub.
+dss_verify_nif(_Type, _Digest, _Signature, _Key) -> ?nif_stub.
+rsa_verify_nif(_Type, _Digest, _Signature, _Key) -> ?nif_stub.
+ecdsa_verify_nif(_Type, _Digest, _Signature, _Curve, _Key) -> ?nif_stub.
%% Public Keys --------------------------------------------------------------------
%% DH Diffie-Hellman functions
@@ -1555,11 +1211,11 @@ dh_check([_Prime,_Gen]) -> ?nif_stub.
{binary(),binary()}.
dh_generate_key(DHParameters) ->
- dh_generate_key_nif(undefined, map_mpint_to_bin(DHParameters), 4).
+ dh_generate_key_nif(undefined, map_mpint_to_bin(DHParameters), 4, 0).
dh_generate_key(PrivateKey, DHParameters) ->
- dh_generate_key_nif(mpint_to_bin(PrivateKey), map_mpint_to_bin(DHParameters), 4).
+ dh_generate_key_nif(mpint_to_bin(PrivateKey), map_mpint_to_bin(DHParameters), 4, 0).
-dh_generate_key_nif(_PrivateKey, _DHParameters, _Mpint) -> ?nif_stub.
+dh_generate_key_nif(_PrivateKey, _DHParameters, _Mpint, _Length) -> ?nif_stub.
%% DHParameters = [P (Prime)= mpint(), G(Generator) = mpint()]
%% MyPrivKey, OthersPublicKey = mpint()
diff --git a/lib/crypto/test/Makefile b/lib/crypto/test/Makefile
index 07e5c1b754..928a1b1d73 100644
--- a/lib/crypto/test/Makefile
+++ b/lib/crypto/test/Makefile
@@ -28,7 +28,7 @@ RELSYSDIR = $(RELEASE_PATH)/crypto_test
# FLAGS
# ----------------------------------------------------
ERL_MAKE_FLAGS +=
-ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include
+ERL_COMPILE_FLAGS +=
EBIN = .
MAKE_EMAKE = $(wildcard $(ERL_TOP)/make/make_emakefile)
diff --git a/lib/crypto/test/blowfish_SUITE.erl b/lib/crypto/test/blowfish_SUITE.erl
index b0d6954820..d7c50dc6de 100644
--- a/lib/crypto/test/blowfish_SUITE.erl
+++ b/lib/crypto/test/blowfish_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -24,8 +24,7 @@
%% Note: This directive should only be used in test suites.
-compile(export_all).
--include_lib("test_server/include/test_server.hrl").
--include("test_server_line.hrl").
+-include_lib("common_test/include/ct.hrl").
-define(TIMEOUT, 120000). % 2 min
diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl
index 307fc4b019..dbd335c693 100644
--- a/lib/crypto/test/crypto_SUITE.erl
+++ b/lib/crypto/test/crypto_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -50,6 +50,7 @@ all() ->
{group, des_cfb},
{group, des3_cbc},
{group, des3_cbf},
+ {group, des3_cfb},
{group, des_ede3},
{group, blowfish_cbc},
{group, blowfish_ecb},
@@ -66,6 +67,7 @@ all() ->
{group, aes_ctr},
{group, aes_gcm},
{group, chacha20_poly1305},
+ {group, aes_cbc},
mod_pow,
exor,
rand_uniform
@@ -93,6 +95,7 @@ groups() ->
{des3_cbc,[], [block]},
{des_ede3,[], [block]},
{des3_cbf,[], [block]},
+ {des3_cfb,[], [block]},
{rc2_cbc,[], [block]},
{aes_cbc128,[], [block]},
{aes_cfb8,[], [block]},
@@ -107,7 +110,8 @@ groups() ->
{rc4, [], [stream]},
{aes_ctr, [], [stream]},
{aes_gcm, [], [aead]},
- {chacha20_poly1305, [], [aead]}
+ {chacha20_poly1305, [], [aead]},
+ {aes_cbc, [], [block]}
].
%%-------------------------------------------------------------------
@@ -118,10 +122,10 @@ init_per_suite(Config) ->
_ ->
Config
catch error:low_entropy ->
- %% Make sure we are on OSE, otherwise we want to crash
- {ose,_} = os:type(),
+ %% We are testing on an OS with low entropy in its random
+ %% seed. So we have to seed it with a binary to get started.
- %% This is NOT how you want to seed this, it is just here
+ %% This is NOT how you want to do seeding, it is just here
%% to make the tests pass. Check your OS manual for how you
%% really want to seed.
{H,M,L} = erlang:now(),
@@ -267,7 +271,6 @@ rand_uniform() ->
[{doc, "rand_uniform and random_bytes testing"}].
rand_uniform(Config) when is_list(Config) ->
rand_uniform_aux_test(10),
- 10 = byte_size(crypto:rand_bytes(10)),
10 = byte_size(crypto:strong_rand_bytes(10)).
%%--------------------------------------------------------------------
@@ -355,6 +358,16 @@ block_cipher({Type, Key, PlainText}) ->
ct:fail({{crypto, block_decrypt, [Type, Key, CipherText]}, {expected, Plain}, {got, Other}})
end;
+block_cipher({aes_cfb128, Key, IV, PlainText}) ->
+ Plain = iolist_to_binary(PlainText),
+ CipherText = crypto:aes_cfb_128_encrypt(Key, IV, PlainText),
+ case crypto:block_decrypt(aes_cfb128, Key, IV, CipherText) of
+ Plain ->
+ ok;
+ Other ->
+ ct:fail({{crypto, block_decrypt, [aes_cfb128, Key, IV, CipherText]}, {expected, Plain}, {got, Other}})
+ end;
+
block_cipher({Type, Key, IV, PlainText}) ->
Plain = iolist_to_binary(PlainText),
CipherText = crypto:block_encrypt(Type, Key, IV, PlainText),
@@ -363,14 +376,30 @@ block_cipher({Type, Key, IV, PlainText}) ->
ok;
Other ->
ct:fail({{crypto, block_decrypt, [Type, Key, IV, CipherText]}, {expected, Plain}, {got, Other}})
+ end;
+
+block_cipher({Type, Key, IV, PlainText, CipherText}) ->
+ Plain = iolist_to_binary(PlainText),
+ case crypto:block_encrypt(Type, Key, IV, Plain) of
+ CipherText ->
+ ok;
+ Other0 ->
+ ct:fail({{crypto, block_encrypt, [Type, Key, IV, Plain]}, {expected, CipherText}, {got, Other0}})
+ end,
+ case crypto:block_decrypt(Type, Key, IV, CipherText) of
+ Plain ->
+ ok;
+ Other1 ->
+ ct:fail({{crypto, block_decrypt, [Type, Key, IV, CipherText]}, {expected, Plain}, {got, Other1}})
end.
-block_cipher_increment({Type, Key, IV, PlainTexts}) when Type == des_cbc;
- Type == des3_cbc;
- Type == aes_cbc;
- Type == des_cbf
- ->
- block_cipher_increment(Type, Key, IV, IV, PlainTexts, iolist_to_binary(PlainTexts), []);
+block_cipher_increment({Type, Key, IV, PlainTexts})
+ when Type == des_cbc; Type == aes_cbc; Type == des3_cbc ->
+ block_cipher_increment(Type, Key, IV, IV, PlainTexts, iolist_to_binary(PlainTexts), []);
+block_cipher_increment({Type, Key, IV, PlainTexts, _CipherText}) when Type == aes_cbc ->
+ Plain = iolist_to_binary(PlainTexts),
+ Blocks = [iolistify(Block) || << Block:128/bitstring >> <= Plain],
+ block_cipher_increment(Type, Key, IV, IV, Blocks, Plain, []);
block_cipher_increment({_Type, _, _, _}) ->
ok;
block_cipher_increment({_,_,_}) ->
@@ -441,6 +470,21 @@ aead_cipher({Type, Key, PlainText, IV, AAD, CipherText, CipherTag}) ->
ok;
Other1 ->
ct:fail({{crypto, block_decrypt, [CipherText]}, {expected, Plain}, {got, Other1}})
+ end;
+aead_cipher({Type, Key, PlainText, IV, AAD, CipherText, CipherTag, TagLen}) ->
+ <<TruncatedCipherTag:TagLen/binary, _/binary>> = CipherTag,
+ Plain = iolist_to_binary(PlainText),
+ case crypto:block_encrypt(Type, Key, IV, {AAD, Plain, TagLen}) of
+ {CipherText, TruncatedCipherTag} ->
+ ok;
+ Other0 ->
+ ct:fail({{crypto, block_encrypt, [Plain, PlainText]}, {expected, {CipherText, TruncatedCipherTag}}, {got, Other0}})
+ end,
+ case crypto:block_decrypt(Type, Key, IV, {AAD, CipherText, TruncatedCipherTag}) of
+ Plain ->
+ ok;
+ Other1 ->
+ ct:fail({{crypto, block_decrypt, [CipherText]}, {expected, Plain}, {got, Other1}})
end.
do_sign_verify({Type, Hash, Public, Private, Msg}) ->
@@ -547,12 +591,16 @@ do_block_iolistify({des3_cbc = Type, Key, IV, PlainText}) ->
{Type, Key, IV, des_iolistify(PlainText)};
do_block_iolistify({des3_cbf = Type, Key, IV, PlainText}) ->
{Type, Key, IV, des_iolistify(PlainText)};
+do_block_iolistify({des3_cfb = Type, Key, IV, PlainText}) ->
+ {Type, Key, IV, des_iolistify(PlainText)};
do_block_iolistify({des_ede3 = Type, Key, IV, PlainText}) ->
{Type, Key, IV, des_iolistify(PlainText)};
do_block_iolistify({Type, Key, PlainText}) ->
{Type, iolistify(Key), iolistify(PlainText)};
do_block_iolistify({Type, Key, IV, PlainText}) ->
- {Type, iolistify(Key), IV, iolistify(PlainText)}.
+ {Type, iolistify(Key), IV, iolistify(PlainText)};
+do_block_iolistify({Type, Key, IV, PlainText, CipherText}) ->
+ {Type, iolistify(Key), IV, iolistify(PlainText), CipherText}.
iolistify(<<"Test With Truncation">>)->
%% Do not iolistify as it spoils this special case
@@ -611,8 +659,8 @@ ipow(A, B, M, Prod) ->
do_exor(B) ->
Z1 = zero_bin(B),
Z1 = crypto:exor(B, B),
- B1 = crypto:rand_bytes(100),
- B2 = crypto:rand_bytes(100),
+ B1 = crypto:strong_rand_bytes(100),
+ B2 = crypto:strong_rand_bytes(100),
Z2 = zero_bin(B1),
Z2 = crypto:exor(B1, B1),
Z2 = crypto:exor(B2, B2),
@@ -755,6 +803,9 @@ group_config(des3_cbc, Config) ->
group_config(des3_cbf, Config) ->
Block = des3_cbf(),
[{block, Block} | Config];
+group_config(des3_cfb, Config) ->
+ Block = des3_cfb(),
+ [{block, Block} | Config];
group_config(des_ede3, Config) ->
Block = des_ede3(),
[{block, Block} | Config];
@@ -803,6 +854,9 @@ group_config(aes_gcm, Config) ->
group_config(chacha20_poly1305, Config) ->
AEAD = chacha20_poly1305(),
[{aead, AEAD} | Config];
+group_config(aes_cbc, Config) ->
+ Block = aes_cbc(),
+ [{block, Block} | Config];
group_config(_, Config) ->
Config.
@@ -1153,7 +1207,16 @@ des_ede3() ->
des3_cbf() ->
[{des3_cbf,
- [hexstr2bin("0123456789abcdef"),
+ [hexstr2bin("0123456789abcdef"),
+ hexstr2bin("fedcba9876543210"),
+ hexstr2bin("0f2d4b6987a5c3e1")],
+ hexstr2bin("1234567890abcdef"),
+ <<"Now is the time for all ">>
+ }].
+
+des3_cfb() ->
+ [{des3_cfb,
+ [hexstr2bin("0123456789abcdef"),
hexstr2bin("fedcba9876543210"),
hexstr2bin("0f2d4b6987a5c3e1")],
hexstr2bin("1234567890abcdef"),
@@ -1166,6 +1229,50 @@ rc2_cbc() ->
<<72,91,135,182,25,42,35,210>>,
<<36,245,206,158,168,230,58,69,148,137,32,192,250,41,237,181,181,251, 192,2,175,135,177,171,57,30,111,117,159,149,15,28,88,158,28,81,28,115, 85,219,241,82,117,222,91,85,73,117,164,25,182,52,191,64,123,57,26,19, 211,27,253,31,194,219,231,104,247,240,172,130,119,21,225,154,101,247, 32,216,42,216,133,169,78,22,97,27,227,26,196,224,172,168,17,9,148,55, 203,91,252,40,61,226,236,221,215,160,78,63,13,181,68,57,196,241,185, 207, 116,129,152,237,60,139,247,153,27,146,161,246,222,98,185,222,152, 187,135, 236,86,34,7,110,91,230,173,34,160,242,202,222,121,127,181,140, 101,203,195, 190,88,250,86,147,127,87,72,126,171,16,71,47,110,248,88, 14,29,143,161,152, 129,236,148,22,152,186,208,119,70,8,174,193,203,100, 193,203,200,117,102,242, 134,142,96,125,135,200,217,190,76,117,50,70, 209,186,101,241,200,91,40,193,54, 90,195,38,47,59,197,38,234,86,223,16, 51,253,204,129,20,171,66,21,241,26,135,216, 196,114,110,91,15,53,40, 164,201,136,113,95,247,51,181,208,241,68,168,98,151,36, 155,72,24,57, 42,191,14,125,204,10,167,214,233,138,115,125,234,121,134,227,26,247, 77,200,117,110,117,111,168,156,206,67,159,149,189,173,150,193,91,199, 216,153,22, 189,137,185,89,160,13,131,132,58,109,28,110,246,252,251,14, 232,91,38,52,29,101,188,69,123,50,0,130,178,93,73,239,118,7,77,35,59, 253,10,159,45,86,142,37,78,232,48>>
}].
+
+%% AES CBC test vectors from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
+aes_cbc() ->
+ [
+ %% F.2.1 CBC-AES128.Encrypt, F.2.2 CBC-AES128.Decrypt
+ {aes_cbc,
+ hexstr2bin("2b7e151628aed2a6abf7158809cf4f3c"), %% Key
+ hexstr2bin("000102030405060708090a0b0c0d0e0f"), %% IV
+ hexstr2bin("6bc1bee22e409f96e93d7e117393172a" %% PlainText
+ "ae2d8a571e03ac9c9eb76fac45af8e51"
+ "30c81c46a35ce411e5fbc1191a0a52ef"
+ "f69f2445df4f9b17ad2b417be66c3710"),
+ hexstr2bin("7649abac8119b246cee98e9b12e9197d" %% CipherText
+ "5086cb9b507219ee95db113a917678b2"
+ "73bed6b8e3c1743b7116e69e22229516"
+ "3ff1caa1681fac09120eca307586e1a7")},
+ %% F.2.3 CBC-AES192.Encrypt, F.2.4 CBC-AES192.Decrypt
+ {aes_cbc,
+ hexstr2bin("8e73b0f7da0e6452c810f32b809079e5" %% Key
+ "62f8ead2522c6b7b"),
+ hexstr2bin("000102030405060708090a0b0c0d0e0f"), %% IV
+ hexstr2bin("6bc1bee22e409f96e93d7e117393172a" %% PlainText
+ "ae2d8a571e03ac9c9eb76fac45af8e51"
+ "30c81c46a35ce411e5fbc1191a0a52ef"
+ "f69f2445df4f9b17ad2b417be66c3710"),
+ hexstr2bin("4f021db243bc633d7178183a9fa071e8" %% CipherText
+ "b4d9ada9ad7dedf4e5e738763f69145a"
+ "571b242012fb7ae07fa9baac3df102e0"
+ "08b0e27988598881d920a9e64f5615cd")},
+ %% F.2.5 CBC-AES256.Encrypt, F.2.6 CBC-AES256.Decrypt
+ {aes_cbc,
+ hexstr2bin("603deb1015ca71be2b73aef0857d7781" %% Key
+ "1f352c073b6108d72d9810a30914dff4"),
+ hexstr2bin("000102030405060708090a0b0c0d0e0f"), %% IV
+ hexstr2bin("6bc1bee22e409f96e93d7e117393172a" %% PlainText
+ "ae2d8a571e03ac9c9eb76fac45af8e51"
+ "30c81c46a35ce411e5fbc1191a0a52ef"
+ "f69f2445df4f9b17ad2b417be66c3710"),
+ hexstr2bin("f58c4c04d6e5f1ba779eabfb5f7bfbd6" %% CipherText
+ "9cfc4e967edb808d679f777bc6702c7d"
+ "39f23369a9d9bacfa530e26304231461"
+ "b2eb05e2c39be9fcda6c19078c6a9d1b")}
+ ].
+
aes_cbc128() ->
[{aes_cbc128,
hexstr2bin("2b7e151628aed2a6abf7158809cf4f3c"),
@@ -1310,6 +1417,14 @@ aes_ecb() ->
"ae2d8a571e03ac9c9eb76fac45af8e51"
"30c81c46a35ce411e5fbc1191a0a52ef"
"f69f2445df4f9b17ad2b417be66c3710")},
+ %% F.1.3 ECB-AES192.Encrypt, F.1.4 ECB-AES192.Decrypt
+ {aes_ecb,
+ hexstr2bin("8e73b0f7da0e6452c810f32b809079e5"
+ "62f8ead2522c6b7b"),
+ hexstr2bin("6bc1bee22e409f96e93d7e117393172a"
+ "ae2d8a571e03ac9c9eb76fac45af8e51"
+ "30c81c46a35ce411e5fbc1191a0a52ef"
+ "f69f2445df4f9b17ad2b417be66c3710")},
%% F.1.5 ECB-AES256.Encrypt, F.1.6 ECB-AES256.Decrypt
{aes_ecb,
hexstr2bin("603deb1015ca71be2b73aef0857d7781"
@@ -1860,7 +1975,36 @@ aes_gcm() ->
"eeb2b22aafde6419a058ab4f6f746bf4"
"0fc0c3b780f244452da3ebf1c5d82cde"
"a2418997200ef82e44ae7e3f"),
- hexstr2bin("a44a8266ee1c8eb0c8b5d4cf5ae9f19a")} %% CipherTag
+ hexstr2bin("a44a8266ee1c8eb0c8b5d4cf5ae9f19a")}, %% CipherTag
+
+ %% Test Case 0 for TagLength = 1
+ {aes_gcm, hexstr2bin("00000000000000000000000000000000"), %% Key
+ hexstr2bin(""), %% PlainText
+ hexstr2bin("000000000000000000000000"), %% IV
+ hexstr2bin(""), %% AAD
+ hexstr2bin(""), %% CipherText
+ hexstr2bin("58"), %% CipherTag
+ 1}, %% TagLength
+
+ %% Test Case 18 for TagLength = 1
+ {aes_gcm, hexstr2bin("feffe9928665731c6d6a8f9467308308" %% Key
+ "feffe9928665731c6d6a8f9467308308"),
+ hexstr2bin("d9313225f88406e5a55909c5aff5269a" %% PlainText
+ "86a7a9531534f7da2e4c303d8a318a72"
+ "1c3c0c95956809532fcf0e2449a6b525"
+ "b16aedf5aa0de657ba637b39"),
+ hexstr2bin("9313225df88406e555909c5aff5269aa" %% IV
+ "6a7a9538534f7da1e4c303d2a318a728"
+ "c3c0c95156809539fcf0e2429a6b5254"
+ "16aedbf5a0de6a57a637b39b"),
+ hexstr2bin("feedfacedeadbeeffeedfacedeadbeef" %% AAD
+ "abaddad2"),
+ hexstr2bin("5a8def2f0c9e53f1f75d7853659e2a20" %% CipherText
+ "eeb2b22aafde6419a058ab4f6f746bf4"
+ "0fc0c3b780f244452da3ebf1c5d82cde"
+ "a2418997200ef82e44ae7e3f"),
+ hexstr2bin("a4"), %% CipherTag
+ 1} %% TagLength
].
%% http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
diff --git a/lib/crypto/test/old_crypto_SUITE.erl b/lib/crypto/test/old_crypto_SUITE.erl
index 1e7f3a1438..324ed39c6d 100644
--- a/lib/crypto/test/old_crypto_SUITE.erl
+++ b/lib/crypto/test/old_crypto_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -19,7 +19,7 @@
%%
-module(old_crypto_SUITE).
--include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct.hrl").
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2,
init_per_testcase/2,
@@ -58,6 +58,7 @@
des_cfb_iter/1,
des_ecb/1,
des3_cbc/1,
+ des3_cbf/1,
des3_cfb/1,
rc2_cbc/1,
aes_cfb/1,
@@ -102,7 +103,7 @@ groups() ->
hmac_rfc2202, hmac_rfc4231_sha224, hmac_rfc4231_sha256,
hmac_rfc4231_sha384, hmac_rfc4231_sha512,
des_cbc, aes_cfb, aes_cbc,
- des_cfb, des_cfb_iter, des3_cbc, des3_cfb, rc2_cbc,
+ des_cfb, des_cfb_iter, des3_cbc, des3_cbf, des3_cfb, rc2_cbc,
aes_cbc_iter, aes_ctr, aes_ctr_stream, des_cbc_iter, des_ecb,
rand_uniform_test, strong_rand_test,
rsa_verify_test, dsa_verify_test, rsa_sign_test,
@@ -187,7 +188,9 @@ ldd_program() ->
case os:find_executable("otool") of
false -> none;
Otool -> Otool ++ " -L"
- end
+ end;
+ _ ->
+ none
end;
Ldd when is_list(Ldd) -> Ldd
end.
@@ -967,6 +970,9 @@ des_cbc(doc) ->
des_cbc(suite) ->
[];
des_cbc(Config) when is_list(Config) ->
+ if_supported(des_cbc, fun des_cbc_do/0).
+
+des_cbc_do() ->
?line Key = hexstr2bin("0123456789abcdef"),
?line IVec = hexstr2bin("1234567890abcdef"),
?line Plain = "Now is the time for all ",
@@ -990,6 +996,9 @@ des_cbc_iter(doc) ->
des_cbc_iter(suite) ->
[];
des_cbc_iter(Config) when is_list(Config) ->
+ if_supported(des_cbc, fun des_cbc_iter_do/0).
+
+des_cbc_iter_do() ->
?line Key = hexstr2bin("0123456789abcdef"),
?line IVec = hexstr2bin("1234567890abcdef"),
?line Plain1 = "Now is the time ",
@@ -1009,6 +1018,9 @@ des_cfb(doc) ->
des_cfb(suite) ->
[];
des_cfb(Config) when is_list(Config) ->
+ if_supported(des_cfb, fun des_cfb_do/0).
+
+des_cfb_do() ->
?line Key = hexstr2bin("0123456789abcdef"),
?line IVec = hexstr2bin("1234567890abcdef"),
?line Plain = "Now is the",
@@ -1025,6 +1037,9 @@ des_cfb_iter(doc) ->
des_cfb_iter(suite) ->
[];
des_cfb_iter(Config) when is_list(Config) ->
+ if_supported(des_cfb, fun des_cfb_iter_do/0).
+
+des_cfb_iter_do() ->
?line Key = hexstr2bin("0123456789abcdef"),
?line IVec = hexstr2bin("1234567890abcdef"),
?line Plain1 = "Now i",
@@ -1043,6 +1058,9 @@ des_ecb(doc) ->
des_ecb(suite) ->
[];
des_ecb(Config) when is_list(Config) ->
+ if_supported(des_ecb, fun des_ecb_do/0).
+
+des_ecb_do() ->
?line Key = hexstr2bin("0123456789abcdef"),
?line Cipher1 = crypto:des_ecb_encrypt(Key, "Now is t"),
?line m(Cipher1, hexstr2bin("3fa40e8a984d4815")),
@@ -1062,7 +1080,9 @@ rc2_cbc(doc) ->
"Encrypt and decrypt according to RC2 CBC and check the result. "
"Example stripped out from public_key application test";
rc2_cbc(Config) when is_list(Config) ->
-
+ if_supported(rc2_cbc, fun rc2_cbc_do/0).
+
+rc2_cbc_do() ->
Key = <<146,210,160,124,215,227,153,239,227,17,222,140,3,93,27,191>>,
IV = <<72,91,135,182,25,42,35,210>>,
@@ -1079,6 +1099,9 @@ des3_cbc(doc) ->
des3_cbc(suite) ->
[];
des3_cbc(Config) when is_list(Config) ->
+ if_supported(des3_cbc, fun des3_cbc_do/0).
+
+des3_cbc_do() ->
?line Key1 = hexstr2bin("0123456789abcdef"),
?line Key2 = hexstr2bin("fedcba9876543210"),
?line Key3 = hexstr2bin("0f2d4b6987a5c3e1"),
@@ -1110,6 +1133,19 @@ des3_cbc(Config) when is_list(Config) ->
%%
%%
+des3_cbf(doc) ->
+ "Encrypt and decrypt according to CFB 3DES, and check the result.";
+des3_cbf(suite) ->
+ [];
+des3_cbf(Config) when is_list(Config) ->
+ case openssl_version() of
+ V when V < 16#90705F -> {skipped,"OpenSSL version too old"};
+ _ ->
+ if_supported(des3_cbf, fun des3_cfb_do/0)
+ end.
+
+%%
+%%
des3_cfb(doc) ->
"Encrypt and decrypt according to CFB 3DES, and check the result.";
des3_cfb(suite) ->
@@ -1117,7 +1153,8 @@ des3_cfb(suite) ->
des3_cfb(Config) when is_list(Config) ->
case openssl_version() of
V when V < 16#90705F -> {skipped,"OpenSSL version too old"};
- _ -> des3_cfb_do()
+ _ ->
+ if_supported(des3_cfb, fun des3_cfb_do/0)
end.
des3_cfb_do() ->
@@ -2066,8 +2103,8 @@ exor_test(Config) when is_list(Config) ->
B = <<1, 2, 3, 4, 5, 6, 7, 8, 9, 10>>,
Z1 = zero_bin(B),
Z1 = crypto:exor(B, B),
- B1 = crypto:rand_bytes(100),
- B2 = crypto:rand_bytes(100),
+ B1 = crypto:strong_rand_bytes(100),
+ B2 = crypto:strong_rand_bytes(100),
Z2 = zero_bin(B1),
Z2 = crypto:exor(B1, B1),
Z2 = crypto:exor(B2, B2),
@@ -2082,6 +2119,9 @@ rc4_test(doc) ->
rc4_test(suite) ->
[];
rc4_test(Config) when is_list(Config) ->
+ if_supported(rc4, fun rc4_test_do/0).
+
+rc4_test_do() ->
CT1 = <<"Yo baby yo">>,
R1 = <<118,122,68,110,157,166,141,212,139,39>>,
K = "apaapa",
@@ -2097,6 +2137,9 @@ rc4_stream_test(doc) ->
rc4_stream_test(suite) ->
[];
rc4_stream_test(Config) when is_list(Config) ->
+ if_supported(rc4, fun rc4_stream_test_do/0).
+
+rc4_stream_test_do() ->
CT1 = <<"Yo ">>,
CT2 = <<"baby yo">>,
K = "apaapa",
diff --git a/lib/crypto/vsn.mk b/lib/crypto/vsn.mk
index 6dcb28ec8a..f3e0623ac9 100644
--- a/lib/crypto/vsn.mk
+++ b/lib/crypto/vsn.mk
@@ -1 +1 @@
-CRYPTO_VSN = 3.6.3
+CRYPTO_VSN = 3.7.4