aboutsummaryrefslogtreecommitdiffstats
path: root/lib/crypto
diff options
context:
space:
mode:
authorErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
committerErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
commit84adefa331c4159d432d22840663c38f155cd4c1 (patch)
treebff9a9c66adda4df2106dfd0e5c053ab182a12bd /lib/crypto
downloadotp-84adefa331c4159d432d22840663c38f155cd4c1.tar.gz
otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.bz2
otp-84adefa331c4159d432d22840663c38f155cd4c1.zip
The R13B03 release.OTP_R13B03
Diffstat (limited to 'lib/crypto')
-rw-r--r--lib/crypto/AUTHORS4
-rw-r--r--lib/crypto/Makefile38
-rw-r--r--lib/crypto/c_src/Makefile5
-rw-r--r--lib/crypto/c_src/Makefile.in144
-rw-r--r--lib/crypto/c_src/crypto_drv.c1721
-rw-r--r--lib/crypto/doc/html/.gitignore0
-rw-r--r--lib/crypto/doc/man3/.gitignore0
-rw-r--r--lib/crypto/doc/man6/.gitignore0
-rw-r--r--lib/crypto/doc/pdf/.gitignore0
-rw-r--r--lib/crypto/doc/src/Makefile113
-rw-r--r--lib/crypto/doc/src/book.xml50
-rw-r--r--lib/crypto/doc/src/crypto.xml785
-rw-r--r--lib/crypto/doc/src/crypto_app.xml108
-rw-r--r--lib/crypto/doc/src/fascicules.xml18
-rw-r--r--lib/crypto/doc/src/insidecover.xml26
-rw-r--r--lib/crypto/doc/src/licenses.xml155
-rw-r--r--lib/crypto/doc/src/make.dep20
-rw-r--r--lib/crypto/doc/src/note.gifbin0 -> 1539 bytes
-rw-r--r--lib/crypto/doc/src/notes.xml469
-rw-r--r--lib/crypto/doc/src/ref_man.xml49
-rw-r--r--lib/crypto/doc/src/release_notes.xml50
-rw-r--r--lib/crypto/doc/src/usersguide.xml50
-rw-r--r--lib/crypto/doc/src/warning.gifbin0 -> 1498 bytes
-rw-r--r--lib/crypto/ebin/.gitignore0
-rw-r--r--lib/crypto/info2
-rw-r--r--lib/crypto/priv/Makefile78
-rw-r--r--lib/crypto/src/Makefile99
-rw-r--r--lib/crypto/src/crypto.app.src31
-rw-r--r--lib/crypto/src/crypto.appup.src22
-rw-r--r--lib/crypto/src/crypto.erl665
-rw-r--r--lib/crypto/src/crypto_app.erl39
-rw-r--r--lib/crypto/src/crypto_server.erl138
-rw-r--r--lib/crypto/src/crypto_sup.erl39
-rw-r--r--lib/crypto/vsn.mk1
34 files changed, 4919 insertions, 0 deletions
diff --git a/lib/crypto/AUTHORS b/lib/crypto/AUTHORS
new file mode 100644
index 0000000000..57084debac
--- /dev/null
+++ b/lib/crypto/AUTHORS
@@ -0,0 +1,4 @@
+Original Authors and Contributors:
+
+Peter H�gfeldt
+Jakob Cederlund
diff --git a/lib/crypto/Makefile b/lib/crypto/Makefile
new file mode 100644
index 0000000000..13eebea6a9
--- /dev/null
+++ b/lib/crypto/Makefile
@@ -0,0 +1,38 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 1999-2009. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+#
+# Macros
+#
+
+SUB_DIRECTORIES = src c_src doc/src
+
+include vsn.mk
+VSN = $(CRYPTO_VSN)
+
+SPECIAL_TARGETS =
+
+#
+# Default Subdir Targets
+#
+include $(ERL_TOP)/make/otp_subdir.mk
+
+
diff --git a/lib/crypto/c_src/Makefile b/lib/crypto/c_src/Makefile
new file mode 100644
index 0000000000..19184f2e8d
--- /dev/null
+++ b/lib/crypto/c_src/Makefile
@@ -0,0 +1,5 @@
+#
+# Invoke with GNU make or clearmake -C gnu.
+#
+include $(ERL_TOP)/make/run_make.mk
+
diff --git a/lib/crypto/c_src/Makefile.in b/lib/crypto/c_src/Makefile.in
new file mode 100644
index 0000000000..29263d7ac7
--- /dev/null
+++ b/lib/crypto/c_src/Makefile.in
@@ -0,0 +1,144 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 1999-2009. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+include $(ERL_TOP)/make/$(TARGET)/otp_ded.mk
+
+# ----------------------------------------------------
+# Application version
+# ----------------------------------------------------
+include ../vsn.mk
+VSN=$(CRYPTO_VSN)
+
+# ----------------------------------------------------
+# The following variables differ between systems.
+# Set by configure.
+# ----------------------------------------------------
+CC = $(DED_CC)
+LD = $(DED_LD)
+SHELL = /bin/sh
+LIBS = $(DED_LIBS)
+LDFLAGS += $(DED_LDFLAGS)
+CFLAGS = $(DED_CFLAGS)
+
+# From erts/configure
+SSL_LIBDIR = @SSL_LIBDIR@
+SSL_INCLUDE = @SSL_INCLUDE@
+
+
+
+INCLUDES = $(SSL_INCLUDE) $(DED_INCLUDES)
+
+ifeq ($(TYPE),debug)
+TYPEMARKER = .debug
+TYPE_FLAGS = $(subst -O3,,$(subst -O2,,$(CFLAGS))) -DDEBUG
+else
+ifeq ($(TYPE),valgrind)
+TYPEMARKER = .valgrind
+TYPE_FLAGS = $(subst -O3,,$(subst -O2,,$(CFLAGS))) -DVALGRIND
+else
+TYPEMARKER =
+TYPE_FLAGS = $(CFLAGS)
+endif
+endif
+
+ALL_CFLAGS = $(TYPE_FLAGS) $(INCLUDES)
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/lib/crypto-$(VSN)
+
+# ----------------------------------------------------
+# Misc Macros
+# ----------------------------------------------------
+OBJS = $(OBJDIR)/crypto_drv.o
+DRV_MAKEFILE = $(PRIVDIR)/Makefile
+
+ifeq ($(findstring win32,$(TARGET)), win32)
+DYN_DRIVER = $(LIBDIR)/crypto_drv.dll
+else
+DYN_DRIVER = $(LIBDIR)/crypto_drv.so
+endif
+
+ifeq ($(HOST_OS),)
+HOST_OS := $(shell $(ERL_TOP)/erts/autoconf/config.guess)
+endif
+DYNAMIC_CRYPTO_LIB=@SSL_DYNAMIC_ONLY@
+LD_R_FLAG=@DED_LD_FLAG_RUNTIME_LIBRARY_PATH@
+ifeq ($(strip $(LD_R_FLAG)),)
+LD_R_OPT =
+else
+ifeq ($(DYNAMIC_CRYPTO_LIB),yes)
+LD_R_OPT = $(LD_R_FLAG)$(SSL_LIBDIR)
+else
+LD_R_OPT =
+endif
+endif
+
+ifeq ($(DYNAMIC_CRYPTO_LIB),yes)
+CRYPTO_LINK_LIB=-L$(SSL_LIBDIR) -lcrypto
+else
+CRYPTO_LINK_LIB=$(SSL_LIBDIR)/libcrypto.a
+endif
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+
+debug opt valgrind: $(OBJDIR) $(LIBDIR) $(DYN_DRIVER)
+
+$(OBJDIR):
+ -@mkdir -p $(OBJDIR)
+
+$(LIBDIR):
+ -@mkdir -p $(LIBDIR)
+
+$(OBJDIR)/%.o: %.c
+ $(INSTALL_DIR) $(OBJDIR)
+ $(CC) -c -o $@ $(ALL_CFLAGS) $<
+
+$(LIBDIR)/crypto_drv.so: $(OBJS)
+ $(INSTALL_DIR) $(LIBDIR)
+ $(LD) $(LDFLAGS) $(LD_R_OPT) -o $@ $^ $(LDLIBS) $(CRYPTO_LINK_LIB)
+
+$(LIBDIR)/crypto_drv.dll: $(OBJS)
+ $(INSTALL_DIR) $(LIBDIR)
+ $(LD) $(LDFLAGS) -o $@ -L$(SSL_LIBDIR) $(OBJS) -llibeay32
+
+clean:
+ rm -f $(DYN_DRIVER) $(OBJS)
+ rm -f core *~
+
+docs:
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+release_spec: opt
+ $(INSTALL_DIR) $(RELSYSDIR)/priv/obj
+ $(INSTALL_DIR) $(RELSYSDIR)/priv/lib
+ $(INSTALL_PROGRAM) $(DRV_MAKEFILE) $(RELSYSDIR)/priv/obj
+ $(INSTALL_PROGRAM) $(OBJS) $(RELSYSDIR)/priv/obj
+ $(INSTALL_PROGRAM) $(DYN_DRIVER) $(RELSYSDIR)/priv/lib
+
+release_docs_spec:
+
diff --git a/lib/crypto/c_src/crypto_drv.c b/lib/crypto/c_src/crypto_drv.c
new file mode 100644
index 0000000000..241c4ec733
--- /dev/null
+++ b/lib/crypto/c_src/crypto_drv.c
@@ -0,0 +1,1721 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 1999-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Purpose: Dynamically loadable driver for cryptography libraries.
+ * Based on OpenSSL.
+ */
+
+#ifdef __WIN32__
+#include <windows.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "erl_driver.h"
+
+#define OPENSSL_THREAD_DEFINES
+#include <openssl/opensslconf.h>
+#ifndef OPENSSL_THREADS
+# ifdef __GNUC__
+# warning No thread support by openssl. Driver will use coarse grain locking.
+# endif
+#endif
+
+#include <openssl/crypto.h>
+#include <openssl/des.h>
+/* #include <openssl/idea.h> This is not supported on the openssl OTP requires */
+#include <openssl/dsa.h>
+#include <openssl/rsa.h>
+#include <openssl/aes.h>
+#include <openssl/md5.h>
+#include <openssl/md4.h>
+#include <openssl/sha.h>
+#include <openssl/bn.h>
+#include <openssl/objects.h>
+#include <openssl/rc4.h>
+#include <openssl/rc2.h>
+#include <openssl/blowfish.h>
+#include <openssl/rand.h>
+
+#ifdef VALGRIND
+# include <valgrind/memcheck.h>
+
+/* libcrypto mixes supplied buffer contents into its entropy pool,
+ which makes valgrind complain about the use of uninitialized data.
+ We use this valgrind "request" to make sure that no such seemingly
+ undefined data escapes the driver.
+*/
+# define ERL_VALGRIND_MAKE_MEM_DEFINED(ptr,size) \
+ VALGRIND_MAKE_MEM_DEFINED(ptr,size)
+
+# define ERL_VALGRIND_ASSERT_MEM_DEFINED(ptr,size) \
+ ((void) ((VALGRIND_CHECK_MEM_IS_DEFINED(ptr,size) == 0) ? 1 : \
+ (fprintf(stderr,"\r\n####### VALGRIND_ASSSERT(%p,%d) failed at %s:%d\r\n",\
+ (ptr),(size), __FILE__, __LINE__), abort(), 0)))
+#else
+# define ERL_VALGRIND_MAKE_MEM_DEFINED(ptr,size)
+# define ERL_VALGRIND_ASSERT_MEM_DEFINED(ptr,size)
+#endif
+
+#ifdef DEBUG
+# define ASSERT(e) \
+ ((void) ((e) ? 1 : (fprintf(stderr,"Assert '%s' failed at %s:%d\n",\
+ #e, __FILE__, __LINE__), abort(), 0)))
+#else
+# define ASSERT(e) ((void) 1)
+#endif
+
+#ifdef __GNUC__
+# define INLINE __inline__
+#elif defined(__WIN32__)
+# define INLINE __forceinline
+#else
+# define INLINE
+#endif
+
+
+#define get_int32(s) ((((unsigned char*) (s))[0] << 24) | \
+ (((unsigned char*) (s))[1] << 16) | \
+ (((unsigned char*) (s))[2] << 8) | \
+ (((unsigned char*) (s))[3]))
+
+#define put_int32(s,i) \
+{ (s)[0] = (char)(((i) >> 24) & 0xff);\
+ (s)[1] = (char)(((i) >> 16) & 0xff);\
+ (s)[2] = (char)(((i) >> 8) & 0xff);\
+ (s)[3] = (char)((i) & 0xff);\
+}
+
+/* Driver interface declarations */
+static int init(void);
+static void finish(void);
+static ErlDrvData start(ErlDrvPort port, char *command);
+static void stop(ErlDrvData drv_data);
+static int crypto_control(ErlDrvData drv_data, unsigned int command, char *buf,
+ int len, char **rbuf, int rlen);
+
+/* openssl callbacks */
+#ifdef OPENSSL_THREADS
+static void locking_function(int mode, int n, const char *file, int line);
+static unsigned long id_function(void);
+static struct CRYPTO_dynlock_value* dyn_create_function(const char *file,
+ int line);
+static void dyn_lock_function(int mode, struct CRYPTO_dynlock_value* ptr,
+ const char *file, int line);
+static void dyn_destroy_function(struct CRYPTO_dynlock_value *ptr,
+ const char *file, int line);
+#endif /* OPENSSL_THREADS */
+
+/* helpers */
+static void hmac_md5(char *key, int klen, char *dbuf, int dlen,
+ char *hmacbuf);
+static void hmac_sha1(char *key, int klen, char *dbuf, int dlen,
+ char *hmacbuf);
+
+static ErlDrvEntry crypto_driver_entry = {
+ init,
+ start,
+ stop,
+ NULL, /* output */
+ NULL, /* ready_input */
+ NULL, /* ready_output */
+ "crypto_drv",
+ finish,
+ NULL, /* handle */
+ crypto_control,
+ NULL, /* timeout */
+ NULL, /* outputv */
+
+ NULL, /* ready_async */
+ NULL, /* flush */
+ NULL, /* call */
+ NULL, /* event */
+ ERL_DRV_EXTENDED_MARKER,
+ ERL_DRV_EXTENDED_MAJOR_VERSION,
+ ERL_DRV_EXTENDED_MINOR_VERSION,
+#ifdef OPENSSL_THREADS
+ ERL_DRV_FLAG_USE_PORT_LOCKING,
+#else
+ 0,
+#endif
+ NULL, /* handle2 */
+ NULL /* process_exit */
+};
+
+
+/* Keep the following definitions in alignment with the FUNC_LIST
+ * in crypto.erl.
+ */
+
+#define DRV_INFO 0
+#define DRV_MD5 1
+#define DRV_MD5_INIT 2
+#define DRV_MD5_UPDATE 3
+#define DRV_MD5_FINAL 4
+#define DRV_SHA 5
+#define DRV_SHA_INIT 6
+#define DRV_SHA_UPDATE 7
+#define DRV_SHA_FINAL 8
+#define DRV_MD5_MAC 9
+#define DRV_MD5_MAC_96 10
+#define DRV_SHA_MAC 11
+#define DRV_SHA_MAC_96 12
+#define DRV_CBC_DES_ENCRYPT 13
+#define DRV_CBC_DES_DECRYPT 14
+#define DRV_EDE3_CBC_DES_ENCRYPT 15
+#define DRV_EDE3_CBC_DES_DECRYPT 16
+#define DRV_AES_CFB_128_ENCRYPT 17
+#define DRV_AES_CFB_128_DECRYPT 18
+#define DRV_RAND_BYTES 19
+#define DRV_RAND_UNIFORM 20
+#define DRV_MOD_EXP 21
+#define DRV_DSS_VERIFY 22
+#define DRV_RSA_VERIFY_SHA 23
+/* #define DRV_RSA_VERIFY_MD5 35 */
+#define DRV_CBC_AES128_ENCRYPT 24
+#define DRV_CBC_AES128_DECRYPT 25
+#define DRV_XOR 26
+#define DRV_RC4_ENCRYPT 27 /* no decrypt needed; symmetric */
+#define DRV_RC4_SETKEY 28
+#define DRV_RC4_ENCRYPT_WITH_STATE 29
+#define DRV_CBC_RC2_40_ENCRYPT 30
+#define DRV_CBC_RC2_40_DECRYPT 31
+#define DRV_CBC_AES256_ENCRYPT 32
+#define DRV_CBC_AES256_DECRYPT 33
+#define DRV_INFO_LIB 34
+/* #define DRV_RSA_VERIFY_SHA 23 */
+#define DRV_RSA_VERIFY_MD5 35
+#define DRV_RSA_SIGN_SHA 36
+#define DRV_RSA_SIGN_MD5 37
+#define DRV_DSS_SIGN 38
+#define DRV_RSA_PUBLIC_ENCRYPT 39
+#define DRV_RSA_PRIVATE_DECRYPT 40
+#define DRV_RSA_PRIVATE_ENCRYPT 41
+#define DRV_RSA_PUBLIC_DECRYPT 42
+#define DRV_DH_GENERATE_PARAMS 43
+#define DRV_DH_CHECK 44
+#define DRV_DH_GENERATE_KEY 45
+#define DRV_DH_COMPUTE_KEY 46
+#define DRV_MD4 47
+#define DRV_MD4_INIT 48
+#define DRV_MD4_UPDATE 49
+#define DRV_MD4_FINAL 50
+
+#define SSL_VERSION_0_9_8 0
+#if SSL_VERSION_0_9_8
+#define DRV_SHA256 51
+#define DRV_SHA256_INIT 52
+#define DRV_SHA256_UPDATE 53
+#define DRV_SHA256_FINAL 54
+#define DRV_SHA512 55
+#define DRV_SHA512_INIT 56
+#define DRV_SHA512_UPDATE 57
+#define DRV_SHA512_FINAL 58
+#endif
+
+#define DRV_BF_CFB64_ENCRYPT 59
+#define DRV_BF_CFB64_DECRYPT 60
+
+/* #define DRV_CBC_IDEA_ENCRYPT 34 */
+/* #define DRV_CBC_IDEA_DECRYPT 35 */
+
+/* Not DRV_DH_GENERATE_PARAMS DRV_DH_CHECK
+ * Calc RSA_VERIFY_* and RSA_SIGN once */
+#define NUM_CRYPTO_FUNCS 46
+
+#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 SHA_CTX_LEN (sizeof(SHA_CTX))
+#define SHA_LEN 20
+#define SHA_LEN_96 12
+#define HMAC_INT_LEN 64
+
+#define HMAC_IPAD 0x36
+#define HMAC_OPAD 0x5c
+
+#if SSL_VERSION_0_9_8
+#define SHA256_CTX_LEN (sizeof(SHA256_CTX))
+#define SHA256_LEN 32
+
+#define SHA512_CTX_LEN (sizeof(SHA512_CTX))
+#define SHA512_LEN 64
+#endif
+
+/* INITIALIZATION AFTER LOADING */
+
+/*
+ * This is the init function called after this driver has been loaded.
+ * It must *not* be declared static. Must return the address to
+ * the driver entry.
+ */
+
+#if !defined(__WIN32__)
+DRIVER_INIT(crypto_drv);
+#endif
+
+DRIVER_INIT(crypto_drv)
+{
+ return &crypto_driver_entry;
+}
+
+static ErlDrvRWLock** lock_vec = NULL; /* Static locks used by openssl */
+
+/* DRIVER INTERFACE */
+
+static int init(void)
+{
+ ErlDrvSysInfo sys_info;
+ int i;
+
+ CRYPTO_set_mem_functions(driver_alloc, driver_realloc, driver_free);
+
+#ifdef OPENSSL_THREADS
+ driver_system_info(&sys_info, sizeof(sys_info));
+
+ if(sys_info.scheduler_threads > 1) {
+ lock_vec = driver_alloc(CRYPTO_num_locks()*sizeof(*lock_vec));
+ if (lock_vec==NULL) return -1;
+ memset(lock_vec,0,CRYPTO_num_locks()*sizeof(*lock_vec));
+
+ for(i=CRYPTO_num_locks()-1; i>=0; --i) {
+ lock_vec[i] = erl_drv_rwlock_create("crypto_drv_stat");
+ if (lock_vec[i]==NULL) return -1;
+ }
+ CRYPTO_set_locking_callback(locking_function);
+ CRYPTO_set_id_callback(id_function);
+ CRYPTO_set_dynlock_create_callback(dyn_create_function);
+ CRYPTO_set_dynlock_lock_callback(dyn_lock_function);
+ CRYPTO_set_dynlock_destroy_callback(dyn_destroy_function);
+ }
+ /* else no need for locks */
+#endif /* OPENSSL_THREADS */
+
+ return 0;
+}
+
+static void finish(void)
+{
+ /* Moved here from crypto_control() as it's not thread safe */
+ CRYPTO_cleanup_all_ex_data();
+
+ if(lock_vec != NULL) {
+ int i;
+ for(i=CRYPTO_num_locks()-1; i>=0; --i) {
+ if (lock_vec[i] != NULL) {
+ erl_drv_rwlock_destroy(lock_vec[i]);
+ }
+ }
+ driver_free(lock_vec);
+ }
+}
+
+static ErlDrvData start(ErlDrvPort port, char *command)
+{
+ set_port_control_flags(port, PORT_CONTROL_FLAG_BINARY);
+ return 0; /* not used */
+}
+
+static void stop(ErlDrvData drv_data)
+{
+ return;
+}
+
+/* Helper functions for 'crypto_control'
+*/
+static INLINE unsigned char* return_binary(char **rbuf, int rlen, int len)
+{
+ if (len <= rlen) {
+ return (unsigned char *) *rbuf;
+ }
+ else {
+ ErlDrvBinary* bin;
+ *rbuf = (char*) (bin = driver_alloc_binary(len));
+ return (bin==NULL) ? NULL : (unsigned char *) bin->orig_bytes;
+ }
+}
+
+static INLINE unsigned char* return_binary_shrink(char **rbuf, int rlen, unsigned char* data, int len)
+{
+ if ((char *) data == *rbuf) { /* default buffer */
+ ASSERT(len <= rlen);
+ return (unsigned char *) data;
+ }
+ else {
+ ErlDrvBinary* bin = (ErlDrvBinary*) *rbuf;
+ *rbuf = (char*) (bin=driver_realloc_binary(bin, len));
+ return (bin==NULL) ? NULL : (unsigned char *) bin->orig_bytes;
+ }
+}
+
+/* Nowadays (R13) it does matter what value control returns
+ * as it may return data in default buffer.
+ */
+static int crypto_control(ErlDrvData drv_data, unsigned int command, char *buf,
+ int len, char **rbuf, int rlen)
+{
+ int klen, dlen, macsize, from_len, to_len, i;
+ int base_len, exponent_len, modulo_len;
+ int data_len, dsa_p_len, dsa_q_len;
+ int dsa_s_len, dsa_g_len, dsa_y_len;
+ int rsa_e_len, rsa_n_len, rsa_d_len, padding;
+ int or_mask;
+ int prime_len, generator;
+ int privkey_len, pubkey_len, dh_p_len, dh_g_len;
+ unsigned int rsa_s_len, j;
+ char *key, *key2, *dbuf;
+ unsigned char *p;
+ const_DES_cblock *des_key, *des_key2, *des_key3;
+ const unsigned char *des_dbuf;
+ BIGNUM *bn_from, *bn_to, *bn_rand, *bn_result;
+ BIGNUM *bn_base, *bn_exponent, *bn_modulo;
+ BIGNUM *dsa_p, *dsa_q, *dsa_g, *dsa_y;
+ BIGNUM *rsa_n, *rsa_e, *rsa_d;
+ BIGNUM *dh_p, *dh_g, *privkey, *pubkey;
+ DES_cblock *des_ivec;
+ unsigned char* bin;
+ DES_key_schedule schedule, schedule2, schedule3;
+ DH *dh_params;
+/* IDEA_KEY_SCHEDULE idea, idea2; */
+ char hmacbuf[SHA_DIGEST_LENGTH];
+ unsigned char *rsa_s, *dsa_s;
+ /* char hmacbuf[SHA_LEN]; */
+#if SSL_VERSION_0_9_8
+ SHA256_CTX sha256_ctx;
+ SHA512_CTX sha512_ctx;
+#endif
+ MD5_CTX md5_ctx;
+ MD4_CTX md4_ctx;
+ SHA_CTX sha_ctx;
+ int new_ivlen = 0;
+ BN_CTX *bn_ctx;
+ DSA *dsa;
+ RSA *rsa;
+ AES_KEY aes_key;
+ RC4_KEY rc4_key;
+ RC2_KEY rc2_key;
+
+ switch(command) {
+
+ case DRV_INFO:
+ bin = return_binary(rbuf,rlen,NUM_CRYPTO_FUNCS);
+ if (bin==NULL) return -1;
+
+ for (i = 0; i < NUM_CRYPTO_FUNCS; i++) {
+ bin[i] = i + 1;
+ }
+ return NUM_CRYPTO_FUNCS;
+
+ case DRV_MD5:
+ bin = return_binary(rbuf,rlen,MD5_LEN);
+ if (bin==NULL) return -1;
+ MD5((unsigned char *) buf, len, bin);
+ return MD5_LEN;
+
+ case DRV_MD5_INIT:
+ bin = return_binary(rbuf,rlen,MD5_CTX_LEN);
+ if (bin==NULL) return -1;
+ MD5_Init((MD5_CTX *)bin);
+ return MD5_CTX_LEN;
+
+ case DRV_MD5_UPDATE:
+ if (len < MD5_CTX_LEN)
+ return -1;
+ bin = return_binary(rbuf,rlen,MD5_CTX_LEN);
+ if (bin==NULL) return -1;
+ memcpy(bin, buf, MD5_CTX_LEN);
+ MD5_Update((MD5_CTX *)bin, buf + MD5_CTX_LEN,
+ len - MD5_CTX_LEN);
+ return MD5_CTX_LEN;
+
+ case DRV_MD5_FINAL:
+ if (len != MD5_CTX_LEN)
+ return -1;
+ memcpy(&md5_ctx, buf, MD5_CTX_LEN); /* XXX Use buf only? */
+ bin = return_binary(rbuf,rlen,MD5_LEN);
+ if (bin==NULL) return -1;
+ MD5_Final(bin, &md5_ctx);
+ return MD5_LEN;
+
+ case DRV_SHA:
+ bin = return_binary(rbuf,rlen,SHA_LEN);
+ if (bin==NULL) return -1;
+ SHA1((unsigned char *) buf, len, bin);
+ return SHA_LEN;
+
+ case DRV_SHA_INIT:
+ bin = return_binary(rbuf,rlen,SHA_CTX_LEN);
+ if (bin==NULL) return -1;
+ SHA1_Init((SHA_CTX*)bin);
+ return SHA_CTX_LEN;
+
+ case DRV_SHA_UPDATE:
+ if (len < SHA_CTX_LEN)
+ return -1;
+ bin = return_binary(rbuf,rlen,SHA_CTX_LEN);
+ if (bin==NULL) return -1;
+ memcpy(bin, buf, SHA_CTX_LEN);
+ SHA1_Update((SHA_CTX*)bin, buf + SHA_CTX_LEN, len - SHA_CTX_LEN);
+ return SHA_CTX_LEN;
+
+ case DRV_SHA_FINAL:
+ if (len != SHA_CTX_LEN)
+ return -1;
+ memcpy(&sha_ctx, buf, SHA_CTX_LEN); /* XXX Use buf only? */
+ bin = return_binary(rbuf,rlen,SHA_LEN);
+ if (bin==NULL) return -1;
+ SHA1_Final(bin, &sha_ctx);
+ return SHA_LEN;
+
+ case DRV_MD5_MAC:
+ case DRV_MD5_MAC_96:
+ /* buf = klen[4] key data */
+ klen = get_int32(buf);
+ key = buf + 4;
+ dlen = len - klen - 4;
+ dbuf = key + klen;
+ hmac_md5(key, klen, dbuf, dlen, hmacbuf);
+ macsize = (command == DRV_MD5_MAC) ? MD5_LEN : MD5_LEN_96;
+ bin = return_binary(rbuf,rlen,macsize);
+ if (bin==NULL) return -1;
+ memcpy(bin, hmacbuf, macsize);
+ return macsize;
+
+ case DRV_SHA_MAC:
+ case DRV_SHA_MAC_96:
+ /* buf = klen[4] key data */
+ klen = get_int32(buf);
+ key = buf + 4;
+ dlen = len - klen - 4;
+ dbuf = key + klen;
+ hmac_sha1(key, klen, dbuf, dlen, hmacbuf);
+ macsize = (command == DRV_SHA_MAC) ? SHA_LEN : SHA_LEN_96;
+ bin = return_binary(rbuf,rlen,macsize);
+ if (bin==NULL) return -1;
+ memcpy(bin, (unsigned char *) hmacbuf, macsize);
+ return macsize;
+
+ case DRV_CBC_DES_ENCRYPT:
+ case DRV_CBC_DES_DECRYPT:
+ /* buf = key[8] ivec[8] data */
+ dlen = len - 16;
+ if (dlen < 0)
+ return -1;
+ if (dlen % 8 != 0)
+ return -1;
+ des_key = (const_DES_cblock*) buf;
+ des_ivec = (DES_cblock*)(buf + 8);
+ des_dbuf = (unsigned char *) (buf + 16);
+ bin = return_binary(rbuf,rlen,dlen);
+ if (bin==NULL) return -1;
+ DES_set_key(des_key, &schedule);
+ DES_ncbc_encrypt(des_dbuf, bin, dlen, &schedule, des_ivec,
+ (command == DRV_CBC_DES_ENCRYPT));
+ return dlen;
+
+ case DRV_BF_CFB64_ENCRYPT:
+ case DRV_BF_CFB64_DECRYPT:
+ {
+ /* buf = klen[4] key ivec[8] data */
+ unsigned char* ivec;
+ unsigned char bf_tkey[8]; /* blowfish ivec */
+ int bf_n; /* blowfish ivec pos */
+ int bf_direction;
+ const unsigned char *bf_dbuf; /* blowfish input data */
+ BF_KEY bf_key; /* blowfish key 8 */
+
+ klen = get_int32(buf);
+ key = buf + 4;
+ ivec = (unsigned char *) (key + klen);
+ bf_dbuf = ivec + 8;
+ dlen = len - 4 - klen - 8;
+ if (dlen < 0) return -1;
+ BF_set_key(&bf_key, klen, (unsigned char *) key);
+ memcpy(bf_tkey, ivec, 8);
+ bin = return_binary(rbuf,rlen,dlen);
+ if (bin==NULL) return -1;
+ bf_direction = command == DRV_BF_CFB64_ENCRYPT ? BF_ENCRYPT : BF_DECRYPT;
+ bf_n = 0;
+ BF_cfb64_encrypt(bf_dbuf, bin, dlen, &bf_key, bf_tkey, &bf_n, bf_direction);
+ return dlen;
+ }
+
+/* case DRV_CBC_IDEA_ENCRYPT: */
+/* case DRV_CBC_IDEA_DECRYPT: */
+ /* buf = key[16] ivec[8] data */
+/* dlen = len - 24; */
+/* if (dlen < 0) */
+/* return -1; */
+/* if (dlen % 8 != 0) */
+/* return -1; */
+/* bin = return_binary(rbuf,rlen,dlen); */
+/* idea_set_encrypt_key(buf, &idea); */
+/* if (command == DRV_CBC_IDEA_DECRYPT) { */
+/* idea_set_decrypt_key(&idea, &idea2); */
+/* memcpy(&idea, &idea2, sizeof(idea)); */
+/* } */
+/* idea_cbc_encrypt(buf + 24, bin, dlen, &idea, buf + 8, */
+/* (command == DRV_CBC_IDEA_ENCRYPT)); */
+/* return dlen; */
+
+ case DRV_CBC_RC2_40_ENCRYPT:
+ case DRV_CBC_RC2_40_DECRYPT:
+ /* buf = key[5] ivec[8] data */
+ dlen = len - 13;
+ if (dlen < 0)
+ return -1;
+ bin = return_binary(rbuf,rlen,dlen);
+ if (bin==NULL) return -1;
+ RC2_set_key(&rc2_key, 5, (unsigned char *) buf, 40);
+ RC2_cbc_encrypt((unsigned char *) (buf + 13), bin, dlen, &rc2_key,
+ (unsigned char *) (buf + 5),
+ (command == DRV_CBC_RC2_40_ENCRYPT));
+ return dlen;
+
+ case DRV_EDE3_CBC_DES_ENCRYPT:
+ case DRV_EDE3_CBC_DES_DECRYPT:
+ dlen = len - 32;
+ if (dlen < 0)
+ return -1;
+ des_key = (const_DES_cblock*) buf;
+ des_key2 = (const_DES_cblock*) (buf + 8);
+ des_key3 = (const_DES_cblock*) (buf + 16);
+ des_ivec = (DES_cblock*) (buf + 24);
+ des_dbuf = (unsigned char *) (buf + 32);
+ bin = return_binary(rbuf,rlen,dlen);
+ if (bin==NULL) return -1;
+ DES_set_key(des_key, &schedule);
+ DES_set_key(des_key2, &schedule2);
+ DES_set_key(des_key3, &schedule3);
+ DES_ede3_cbc_encrypt(des_dbuf, bin, dlen, &schedule,
+ &schedule2, &schedule3, des_ivec,
+ (command == DRV_EDE3_CBC_DES_ENCRYPT));
+ return dlen;
+
+ case DRV_AES_CFB_128_ENCRYPT:
+ case DRV_AES_CFB_128_DECRYPT:
+ /* buf = key[16] ivec[16] data */
+ dlen = len - 32;
+ if (dlen < 0)
+ return -1;
+ bin = return_binary(rbuf,rlen,dlen);
+ if (bin==NULL) return -1;
+ AES_set_encrypt_key((unsigned char *) buf, 128, &aes_key);
+ AES_cfb128_encrypt((unsigned char *) (buf+32), bin, dlen, &aes_key,
+ (unsigned char *) (buf+16), &new_ivlen,
+ (command == DRV_AES_CFB_128_ENCRYPT));
+ return dlen;
+
+ case DRV_RC4_ENCRYPT:
+ /* buf = klen[4] key data */
+ klen = get_int32(buf);
+ key = buf + 4;
+ dlen = len - klen - 4;
+ dbuf = key + klen;
+ bin = return_binary(rbuf,rlen,dlen);
+ if (bin==NULL) return -1;
+ RC4_set_key(&rc4_key, klen, (unsigned char *) key);
+ RC4(&rc4_key, dlen, (unsigned char *) dbuf, bin);
+ return dlen;
+
+ case DRV_RC4_SETKEY:
+ /* buf = key */
+ dlen = sizeof(rc4_key);
+ bin = return_binary(rbuf,rlen,dlen);
+ if (bin==NULL) return -1;
+ RC4_set_key(&rc4_key, len, (unsigned char *) buf);
+ memcpy(bin, &rc4_key, dlen);
+ return dlen;
+
+ case DRV_RC4_ENCRYPT_WITH_STATE:
+ /* buf = statelength[4] state data, return statelength[4] state data */
+ klen = get_int32(buf);
+ key = buf + 4;
+ dlen = len - klen - 4;
+ dbuf = key + klen;
+ bin = return_binary(rbuf,rlen,len);
+ if (bin==NULL) return -1;
+ memcpy(&rc4_key, key, klen);
+ RC4(&rc4_key, dlen, (unsigned char *) dbuf, bin + klen + 4);
+ memcpy(bin, buf, 4);
+ memcpy(bin + 4, &rc4_key, klen);
+ return len;
+
+ case DRV_RAND_BYTES:
+ /* buf = <<rlen:32/integer,topmask:8/integer,bottommask:8/integer>> */
+
+ if (len != 6)
+ return -1;
+ dlen = get_int32(buf);
+ bin = return_binary(rbuf,rlen,dlen);
+ if (bin==NULL) return -1;
+ RAND_pseudo_bytes(bin,dlen);
+ ERL_VALGRIND_MAKE_MEM_DEFINED(bin, dlen);
+ or_mask = ((unsigned char*)buf)[4];
+ bin[dlen-1] |= or_mask; /* topmask */
+ or_mask = ((unsigned char*)buf)[5];
+ bin[0] |= or_mask; /* bottommask */
+ return dlen;
+
+ case DRV_RAND_UNIFORM:
+ /* buf = <<from_len:32/integer,bn_from:from_len/binary, *
+ * to_len:32/integer,bn_to:to_len/binary>> */
+ if (len < 8)
+ return -1;
+ from_len = get_int32(buf);
+ if (len < (8 + from_len))
+ return -1;
+ to_len = get_int32(buf + 4 + from_len);
+ if (len != (8 + from_len + to_len))
+ return -1;
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(buf, 4 + from_len + 4 + to_len);
+ bn_from = BN_new();
+ BN_bin2bn((unsigned char *)(buf + 4), from_len, bn_from);
+ bn_rand = BN_new();
+ BN_bin2bn((unsigned char *)(buf + 8 + from_len), to_len, bn_rand);
+ bn_to = BN_new();
+ BN_sub(bn_to, bn_rand, bn_from);
+ BN_pseudo_rand_range(bn_rand, bn_to);
+ BN_add(bn_rand, bn_rand, bn_from);
+ dlen = BN_num_bytes(bn_rand);
+ bin = return_binary(rbuf,rlen,dlen + 4);
+ if (bin==NULL) return -1;
+ put_int32(bin, dlen);
+ BN_bn2bin(bn_rand,(unsigned char*)(bin + 4));
+ ERL_VALGRIND_MAKE_MEM_DEFINED(bin+4, dlen);
+ BN_free(bn_rand);
+ BN_free(bn_from);
+ BN_free(bn_to);
+ return dlen + 4;
+
+ case DRV_MOD_EXP:
+ /* buf = <<base_len:32/integer,base/binary, *
+ * exponent_len:32/integer,exponent/binary, *
+ * modulo_len:32/integer, modulo/binary>> */
+ if (len < 12)
+ return -1;
+ base_len = get_int32(buf);
+ if (len < (12 + base_len))
+ return -1;
+ exponent_len = get_int32(buf + 4 + base_len);
+ if (len < (12 + base_len + exponent_len))
+ return -1;
+ modulo_len = get_int32(buf + 8 + base_len + exponent_len);
+ if (len != (12 + base_len + exponent_len + modulo_len))
+ return -1;
+ bn_base = BN_new();
+ BN_bin2bn((unsigned char *)(buf + 4),
+ base_len, bn_base);
+ bn_exponent = BN_new();
+ BN_bin2bn((unsigned char *)(buf + 8 + base_len),
+ exponent_len, bn_exponent);
+ bn_modulo = BN_new();
+ BN_bin2bn((unsigned char *)(buf + 12 + base_len + exponent_len),
+ modulo_len, bn_modulo);
+ bn_result = BN_new();
+ bn_ctx = BN_CTX_new();
+ BN_mod_exp(bn_result, bn_base, bn_exponent,
+ bn_modulo, bn_ctx);
+ dlen = BN_num_bytes(bn_result);
+ bin = return_binary(rbuf,rlen,dlen + 4);
+ if (bin==NULL) return -1;
+ put_int32(bin, dlen);
+ BN_bn2bin(bn_result,(unsigned char*)(bin + 4));
+ BN_free(bn_result);
+ BN_free(bn_modulo);
+ BN_free(bn_exponent);
+ BN_free(bn_base);
+ BN_CTX_free(bn_ctx);
+ return dlen + 4;
+
+ case DRV_DSS_VERIFY:
+ /* buf = <<data_len:32/integer, data:data_len/binary,
+ * dsa_s_len:32/integer, dsa_s:dsa_s_len/binary,
+ * dsa_p_len:32/integer, dsa_p:dsa_p_len/binary,
+ * dsa_q_len:32/integer, dsa_q:dsa_q_len/binary,
+ * dsa_g_len:32/integer, dsa_g:dsa_g_len/binary,
+ * dsa_y_len:32/integer, dsa_y:dsa_y_len/binary>> */
+ i = 0;
+ j = 0;
+ if (len < 24)
+ return -1;
+ data_len = get_int32(buf + i + j);
+ j += data_len; i += 4;
+ if (len < (24 + j))
+ return -1;
+ dsa_s_len = get_int32(buf + i + j);
+ j += dsa_s_len; i += 4;
+ if (len < (24 + j))
+ return -1;
+ dsa_p_len = get_int32(buf + i + j);
+ j += dsa_p_len; i += 4;
+ if (len < (24 + j))
+ return -1;
+ dsa_q_len = get_int32(buf + i + j);
+ j += dsa_q_len; i += 4;
+ if (len < (24 + j))
+ return -1;
+ dsa_g_len = get_int32(buf + i + j);
+ j += dsa_g_len; i += 4;
+ if (len < (24 + j))
+ return -1;
+ dsa_y_len = get_int32(buf + i + j);
+ j += dsa_y_len;
+ if (len != (24 + j))
+ return -1;
+ i = 4;
+ SHA1((unsigned char *) (buf + i), data_len, (unsigned char *) hmacbuf);
+ i += data_len + 4;
+ dsa_s = (unsigned char *)(buf + i);
+ i += (dsa_s_len + 4);
+ dsa_p = BN_new();
+ BN_bin2bn((unsigned char *)(buf + i), dsa_p_len, dsa_p);
+ i += (dsa_p_len + 4);
+ dsa_q = BN_new();
+ BN_bin2bn((unsigned char *)(buf + i), dsa_q_len, dsa_q);
+ i += (dsa_q_len + 4);
+ dsa_g = BN_new();
+ BN_bin2bn((unsigned char *)(buf + i), dsa_g_len, dsa_g);
+ i += (dsa_g_len + 4);
+ dsa_y = BN_new();
+ BN_bin2bn((unsigned char *)(buf + i), dsa_y_len, dsa_y);
+ dsa = DSA_new();
+ dsa->p = dsa_p;
+ dsa->q = dsa_q;
+ dsa->g = dsa_g;
+ dsa->priv_key = NULL;
+ dsa->pub_key = dsa_y;
+ i = DSA_verify(0, (unsigned char *) hmacbuf, SHA_DIGEST_LENGTH,
+ dsa_s, dsa_s_len, dsa);
+ bin = return_binary(rbuf,rlen,1);
+ if (bin==NULL) return -1;
+
+ DSA_free(dsa);
+ bin[0] = (i > 0) ? 1 : 0;
+ return 1;
+
+ case DRV_DSS_SIGN:
+ /* buf = <<data_len:32/integer, data:data_len/binary,
+ * dsa_p_len:32/integer, dsa_p:dsa_p_len/binary,
+ * dsa_q_len:32/integer, dsa_q:dsa_q_len/binary,
+ * dsa_g_len:32/integer, dsa_g:dsa_g_len/binary,
+ * dsa_y_len:32/integer, dsa_y:dsa_y_len/binary,
+ * dsa_x_len:32/integer, dsa_s:dsa_x_len/binary>> */
+ i = 0;
+ j = 0;
+ if (len < 20)
+ return -1;
+ data_len = get_int32(buf + i + j);
+ j += data_len; i += 4;
+ if (len < (20 + j))
+ return -1;
+ dsa_p_len = get_int32(buf + i + j);
+ j += dsa_p_len; i += 4;
+ if (len < (20 + j))
+ return -1;
+ dsa_q_len = get_int32(buf + i + j);
+ j += dsa_q_len; i += 4;
+ if (len < (20 + j))
+ return -1;
+ dsa_g_len = get_int32(buf + i + j);
+ j += dsa_g_len; i += 4;
+ if (len < (20 + j))
+ return -1;
+ dsa_y_len = get_int32(buf + i + j);
+ j += dsa_y_len;
+ if (len < (20 + j))
+ return -1;
+ if (len != (20 + j))
+ return -1;
+
+ i = 4;
+ SHA1((unsigned char *) (buf + i), data_len, (unsigned char *) hmacbuf);
+ i += data_len + 4;
+ dsa_p = BN_new();
+ BN_bin2bn((unsigned char *)(buf + i), dsa_p_len, dsa_p);
+ i += (dsa_p_len + 4);
+ dsa_q = BN_new();
+ BN_bin2bn((unsigned char *)(buf + i), dsa_q_len, dsa_q);
+ i += (dsa_q_len + 4);
+ dsa_g = BN_new();
+ BN_bin2bn((unsigned char *)(buf + i), dsa_g_len, dsa_g);
+ i += (dsa_g_len + 4);
+ dsa_y = BN_new();
+ BN_bin2bn((unsigned char *)(buf + i), dsa_y_len, dsa_y);
+ /* i += (dsa_y_len + 4); */
+
+ dsa = DSA_new();
+ dsa->p = dsa_p;
+ dsa->q = dsa_q;
+ dsa->g = dsa_g;
+ dsa->priv_key = dsa_y;
+ dsa->pub_key = NULL;
+ dlen = DSA_size(dsa);
+ bin = return_binary(rbuf,rlen, dlen+1);
+ if (bin==NULL) return -1;
+ i = DSA_sign(NID_sha1,
+ (unsigned char *) hmacbuf,SHA_DIGEST_LENGTH,
+ (unsigned char *) &bin[1],
+ (unsigned int *) &dsa_s_len, dsa);
+ DSA_free(dsa);
+ if (i) {
+ if (dsa_s_len != dlen) {
+ bin = return_binary_shrink(rbuf,rlen,bin,dsa_s_len+1);
+ }
+ bin[0] = 1;
+ return dsa_s_len + 1;
+ }
+ else {
+ bin[0] = 0;
+ return 1;
+ }
+
+ case DRV_RSA_VERIFY_MD5:
+ case DRV_RSA_VERIFY_SHA:
+ /* buf = <<data_len:32/integer, data:data_len/binary,
+ * rsa_s_len:32/integer, rsa_s:rsa_s_len/binary,
+ * rsa_e_len:32/integer, rsa_e:rsa_e_len/binary,
+ * rsa_n_len:32/integer, rsa_n:rsa_n_len/binary>> */
+ i = 0;
+ j = 0;
+ if (len < 16)
+ return -1;
+ data_len = get_int32(buf + i + j);
+ j += data_len; i += 4;
+ if (len < (16 + j))
+ return -1;
+ rsa_s_len = get_int32(buf + i + j);
+ j += rsa_s_len; i += 4;
+ if (len < (16 + j))
+ return -1;
+ rsa_e_len = get_int32(buf + i + j);
+ j += rsa_e_len; i += 4;
+ if (len < (16 + j))
+ return -1;
+ rsa_n_len = get_int32(buf + i + j);
+ j += rsa_n_len; i += 4;
+ if (len != (16 + j))
+ return -1;
+ i = 4;
+ i += (data_len + 4);
+ rsa_s = (unsigned char *)(buf + i);
+ i += (rsa_s_len + 4);
+ rsa_e = BN_new();
+ BN_bin2bn((unsigned char *)(buf + i), rsa_e_len, rsa_e);
+ i += (rsa_e_len + 4);
+ rsa_n = BN_new();
+ BN_bin2bn((unsigned char *)(buf + i), rsa_n_len, rsa_n);
+ rsa = RSA_new();
+ rsa->n = rsa_n;
+ rsa->e = rsa_e;
+ i = 4;
+ if(command == DRV_RSA_VERIFY_SHA) {
+ SHA1((unsigned char *) (buf + i), data_len,
+ (unsigned char *) hmacbuf);
+ i = RSA_verify(NID_sha1, (unsigned char *) hmacbuf, SHA_DIGEST_LENGTH,
+ rsa_s, rsa_s_len, rsa);
+ } else {
+ MD5((unsigned char *) (buf + i), data_len, (unsigned char *) hmacbuf);
+ i = RSA_verify(NID_md5, (unsigned char *) hmacbuf, MD5_DIGEST_LENGTH,
+ rsa_s, rsa_s_len, rsa);
+ }
+
+ bin = return_binary(rbuf,rlen,1);
+ if (bin==NULL) return -1;
+ bin[0] = (char)(i & 0xff);
+ RSA_free(rsa);
+ return 1;
+
+ case DRV_RSA_SIGN_MD5:
+ case DRV_RSA_SIGN_SHA:
+ /* buf = <<data_len:32/integer, data:data_len/binary,
+ * rsa_e_len:32/integer, rsa_e:rsa_e_len/binary,
+ * rsa_n_len:32/integer, rsa_n:rsa_n_len/binary,
+ * rsa_d_len:32/integer, rsa_d:rsa_d_len/binary>> */
+
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(buf,len);
+
+ i = 0;
+ j = 0;
+
+ if (len < 16)
+ return -1;
+ data_len = get_int32(buf + i + j);
+ j += data_len; i += 4;
+ if (len < (16 + j))
+ return -1;
+ rsa_e_len = get_int32(buf + i + j);
+ j += rsa_e_len; i += 4;
+ if (len < (16 + j))
+ return -1;
+ rsa_n_len = get_int32(buf + i + j);
+ j += rsa_n_len; i += 4;
+ if (len < (16 + j))
+ return -1;
+ rsa_d_len = get_int32(buf + i + j);
+ j += rsa_d_len; i += 4;
+ if (len != (16 + j))
+ return -1;
+
+ i = 4;
+ i += (data_len + 4);
+ rsa_e = BN_new();
+ BN_bin2bn((unsigned char *)(buf + i), rsa_e_len, rsa_e);
+ i += (rsa_e_len + 4);
+ rsa_n = BN_new();
+ BN_bin2bn((unsigned char *)(buf + i), rsa_n_len, rsa_n);
+ i += (rsa_n_len + 4);
+ rsa_d = BN_new();
+ BN_bin2bn((unsigned char *)(buf + i), rsa_d_len, rsa_d);
+ i += (rsa_d_len + 4);
+
+ rsa = RSA_new();
+ rsa->e = rsa_e;
+ rsa->n = rsa_n;
+ rsa->d = rsa_d;
+
+ dlen = RSA_size(rsa);
+ bin = return_binary(rbuf,rlen,dlen+1);
+ if (bin==NULL) return -1;
+ i = 4;
+ if (command == DRV_RSA_SIGN_MD5) {
+ MD5((unsigned char *) (buf + i), data_len, (unsigned char *) hmacbuf);
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(hmacbuf, MD5_DIGEST_LENGTH);
+ i = RSA_sign(NID_md5,
+ (unsigned char *) hmacbuf,MD5_DIGEST_LENGTH,
+ (unsigned char *) &bin[1],
+ &rsa_s_len, rsa);
+ } else {
+ SHA1((unsigned char *) (buf + i), data_len,
+ (unsigned char *) hmacbuf);
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(hmacbuf, SHA_DIGEST_LENGTH);
+ i = RSA_sign(NID_sha1,
+ (unsigned char *) hmacbuf,SHA_DIGEST_LENGTH,
+ (unsigned char *) &bin[1],
+ &rsa_s_len, rsa);
+ }
+ RSA_free(rsa);
+ if (i) {
+ ERL_VALGRIND_MAKE_MEM_DEFINED(bin+1, rsa_s_len);
+ if (rsa_s_len != dlen) {
+ bin = return_binary_shrink(rbuf,rlen,bin,rsa_s_len+1);
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(bin+1, rsa_s_len);
+ }
+ bin[0] = 1;
+ return rsa_s_len + 1;
+ }
+ else {
+ bin[0] = 0;
+ return 1;
+ }
+
+ case DRV_RSA_PRIVATE_DECRYPT:
+ case DRV_RSA_PRIVATE_ENCRYPT:
+ /* buf = <<data_len:32/integer, data:data_len/binary,
+ * rsa_e_len:32/integer, rsa_e:rsa_e_len/binary,
+ * rsa_n_len:32/integer, rsa_n:rsa_n_len/binary,
+ * rsa_d_len:32/integer, rsa_d:rsa_d_len/binary,
+ * pad:8/integer >> */
+
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(buf,len);
+ i = 0;
+ j = 0;
+
+ if (len < 17)
+ return -1;
+ data_len = get_int32(buf + i + j);
+ j += data_len; i += 4;
+ if (len < (17 + j))
+ return -1;
+ rsa_e_len = get_int32(buf + i + j);
+ j += rsa_e_len; i += 4;
+ if (len < (17 + j))
+ return -1;
+ rsa_n_len = get_int32(buf + i + j);
+ j += rsa_n_len; i += 4;
+ if (len < (17 + j))
+ return -1;
+ rsa_d_len = get_int32(buf + i + j);
+ j += rsa_d_len; i += 4;
+ padding = *(unsigned char *) (buf+i+j);
+ if (len != (17 + j))
+ return -1;
+
+ i = 4;
+ i += (data_len + 4);
+ rsa_e = BN_new();
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(buf+i,rsa_e_len);
+ BN_bin2bn((unsigned char *)(buf + i), rsa_e_len, rsa_e);
+ i += (rsa_e_len + 4);
+ rsa_n = BN_new();
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(buf+i,rsa_n_len);
+ BN_bin2bn((unsigned char *)(buf + i), rsa_n_len, rsa_n);
+ i += (rsa_n_len + 4);
+ rsa_d = BN_new();
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(buf+i,rsa_d_len);
+ BN_bin2bn((unsigned char *)(buf + i), rsa_d_len, rsa_d);
+ i += (rsa_d_len + 4);
+
+ switch(padding) {
+ case 0:
+ padding = RSA_NO_PADDING;
+ break;
+ case 1:
+ padding = RSA_PKCS1_PADDING;
+ break;
+ case 2:
+ padding = RSA_PKCS1_OAEP_PADDING;
+ break;
+ case 3:
+ padding = RSA_SSLV23_PADDING;
+ break;
+ default:
+ return -1;
+ }
+
+ rsa = RSA_new();
+ rsa->e = rsa_e;
+ rsa->n = rsa_n;
+ rsa->d = rsa_d;
+
+ dlen = RSA_size(rsa) + 1;
+ bin = return_binary(rbuf,rlen,dlen);
+ if (bin==NULL) return -1;
+ i = 4;
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(buf+i,data_len);
+ if(command == DRV_RSA_PRIVATE_DECRYPT) {
+ i = RSA_private_decrypt(data_len, (unsigned char *) (buf+i),
+ (unsigned char *) &bin[1],
+ rsa, padding);
+ if(i > 0) {
+ ERL_VALGRIND_MAKE_MEM_DEFINED(&bin[1],i);
+ bin = return_binary_shrink(rbuf,rlen, bin, i+1);
+ if (bin==NULL) return -1;
+ }
+ } else {
+ i = RSA_private_encrypt(data_len, (unsigned char *) (buf+i),
+ (unsigned char *) &bin[1],
+ rsa, padding);
+ if(i > 0) {
+ ERL_VALGRIND_MAKE_MEM_DEFINED(&bin[1],i);
+ }
+ }
+ RSA_free(rsa);
+ if(i > 0) {
+ bin[0] = 1;
+ return i + 1;
+ } else {
+ bin[0] = 0;
+ return 1;
+ }
+ break;
+
+ case DRV_RSA_PUBLIC_ENCRYPT:
+ case DRV_RSA_PUBLIC_DECRYPT:
+ /* buf = <<data_len:32/integer, data:data_len/binary,
+ * rsa_e_len:32/integer, rsa_e:rsa_e_len/binary,
+ * rsa_n_len:32/integer, rsa_n:rsa_n_len/binary,
+ * pad:8/integer >> */
+
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(buf,len);
+ i = 0;
+ j = 0;
+
+ if (len < 13)
+ return -1;
+ data_len = get_int32(buf + i + j);
+ j += data_len; i += 4;
+ if (len < (13 + j))
+ return -1;
+ rsa_e_len = get_int32(buf + i + j);
+ j += rsa_e_len; i += 4;
+ if (len < (13 + j))
+ return -1;
+ rsa_n_len = get_int32(buf + i + j);
+ j += rsa_n_len; i += 4;
+ if (len < (13 + j))
+ return -1;
+ padding = *(unsigned char *) (buf + i + j);
+ if (len != (13 + j))
+ return -1;
+
+ i = 4;
+ i += (data_len + 4);
+ rsa_e = BN_new();
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(buf+i,rsa_e_len);
+ BN_bin2bn((unsigned char *)(buf + i), rsa_e_len, rsa_e);
+ i += (rsa_e_len + 4);
+ rsa_n = BN_new();
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(buf+i,rsa_n_len);
+ BN_bin2bn((unsigned char *)(buf + i), rsa_n_len, rsa_n);
+ i += (rsa_n_len + 4);
+
+ switch(padding) {
+ case 0:
+ padding = RSA_NO_PADDING;
+ break;
+ case 1:
+ padding = RSA_PKCS1_PADDING;
+ break;
+ case 2:
+ padding = RSA_PKCS1_OAEP_PADDING;
+ break;
+ case 3:
+ padding = RSA_SSLV23_PADDING;
+ break;
+ default:
+ return -1;
+ }
+
+ rsa = RSA_new();
+ rsa->e = rsa_e;
+ rsa->n = rsa_n;
+
+ dlen = RSA_size(rsa) + 1;
+ bin = return_binary(rbuf,rlen,dlen);
+ if (bin==NULL) return -1;
+ i = 4;
+ if(command == DRV_RSA_PUBLIC_ENCRYPT) {
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(buf+i,data_len);
+ i = RSA_public_encrypt(data_len, (unsigned char *) (buf+i),
+ (unsigned char *) &bin[1],
+ rsa, padding);
+ if (i > 0) {
+ ERL_VALGRIND_MAKE_MEM_DEFINED(bin+1, i);
+ }
+ } else {
+ i = RSA_public_decrypt(data_len, (unsigned char *) (buf+i),
+ (unsigned char *) &bin[1],
+ rsa, padding);
+ if(i > 0) {
+ ERL_VALGRIND_MAKE_MEM_DEFINED(bin+1, i);
+ bin = return_binary_shrink(rbuf,rlen,bin, i+1);
+ if (bin==NULL) return -1;
+ }
+ }
+
+ RSA_free(rsa);
+ if(i > 0) {
+ bin[0] = 1;
+ return i + 1;
+ } else {
+/* ERR_load_crypto_strings(); */
+/* fprintf(stderr, "%d: %s \r\n", __LINE__, ERR_reason_error_string(ERR_get_error())); */
+ bin[0] = 0;
+ return 1;
+ }
+ break;
+
+ case DRV_CBC_AES128_ENCRYPT:
+ case DRV_CBC_AES256_ENCRYPT:
+ case DRV_CBC_AES128_DECRYPT:
+ case DRV_CBC_AES256_DECRYPT:
+ /* buf = key[klen] ivec[klen] data */
+ if (command == DRV_CBC_AES256_ENCRYPT || command == DRV_CBC_AES256_DECRYPT)
+ klen = 32;
+ else
+ klen = 16;
+ dlen = len - klen - 16;
+ if (dlen < 0)
+ return -1;
+ if (dlen % 16 != 0)
+ return -1;
+ if (command == DRV_CBC_AES128_ENCRYPT || command == DRV_CBC_AES256_ENCRYPT) {
+ i = AES_ENCRYPT;
+ AES_set_encrypt_key((unsigned char *) buf, klen*8, &aes_key);
+ } else {
+ i = AES_DECRYPT;
+ AES_set_decrypt_key((unsigned char *) buf, klen*8, &aes_key);
+ }
+ bin = return_binary(rbuf,rlen,dlen);
+ if (bin==NULL) return -1;
+ AES_cbc_encrypt((unsigned char *) (buf + klen+16),
+ (unsigned char *) bin,
+ dlen,
+ &aes_key,
+ (unsigned char *) (buf + klen),
+ i);
+ return dlen;
+
+/* case DRV_CBC_AES128_DECRYPT: */
+/* case DRV_CBC_AES256_DECRYPT: */
+/* /\* buf = key[klen] ivec[16] data *\/ */
+/* if (command == DRV_CBC_AES256_DECRYPT) */
+/* klen = 32; */
+/* else */
+/* klen = 16; */
+/* dlen = len - klen - 16; */
+/* if (dlen < 0) */
+/* return -1; */
+/* *rbuf = (char *)(bin = driver_alloc_binary(dlen)); */
+/* AES_set_decrypt_key((unsigned char *) buf, klen*8, &aes_key); */
+/* AES_cbc_encrypt((unsigned char *) (buf + klen+16), */
+/* (unsigned char *) bin->orig_bytes, */
+/* dlen, */
+/* &aes_key, */
+/* (unsigned char *) (buf + klen), */
+/* AES_DECRYPT); */
+/* return dlen; */
+/* break; */
+
+ case DRV_XOR:
+ /* buf = data1, data2 with same size */
+ dlen = len / 2;
+ if (len != dlen * 2)
+ return -1;
+ bin = return_binary(rbuf,rlen,dlen);
+ if (bin==NULL) return -1;
+ p = bin,
+ dbuf = buf + dlen;
+ for (key = buf, key2 = dbuf; key != dbuf; ++key, ++key2, ++p)
+ *p = *key ^ *key2;
+ return dlen;
+
+ case DRV_DH_GENERATE_PARAMS:
+ /* buf = <<PrimeLen:32 Generator:32>> */
+ if (len != 8)
+ return -1;
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(buf,len);
+ prime_len = get_int32(buf);
+ generator = get_int32(buf+4);
+ dh_params = DH_generate_parameters(prime_len, generator, NULL, NULL);
+
+ if(dh_params) {
+ dh_p_len = BN_num_bytes(dh_params->p);
+ dh_g_len = BN_num_bytes(dh_params->g);
+ dlen = 1 + 4 + 4 + dh_g_len + dh_p_len;
+ bin = return_binary(rbuf,rlen,dlen);
+ if (bin==NULL) return -1;
+ bin[0] = 1;
+ put_int32(bin+1, dh_p_len);
+ BN_bn2bin(dh_params->p, bin+5);
+ ERL_VALGRIND_MAKE_MEM_DEFINED(bin+5,dh_p_len);
+ put_int32(bin+5+dh_p_len, dh_g_len);
+ BN_bn2bin(dh_params->g, bin+5+dh_p_len+4);
+ ERL_VALGRIND_MAKE_MEM_DEFINED(bin+5+dh_p_len+4,dh_g_len);
+ } else {
+ dlen = 1;
+ bin = return_binary(rbuf,rlen,dlen);
+ if (bin==NULL) return -1;
+ bin[0] = 0;
+ }
+ DH_free(dh_params);
+ return dlen;
+
+ case DRV_DH_CHECK:
+ /* buf = <<dh_p_len:32/integer, dh_p:dh_p_len/binary,
+ * dh_g_len:32/integer, dh_g:dh_g_len/binary>> */
+ i = 0;
+ j = 0;
+ if(len < 8) return -1;
+ dh_p_len = get_int32(buf + i + j);
+ j += dh_p_len; i += 4;
+ if (len < (8 + j)) return -1;
+ dh_g_len = get_int32(buf + i + j);
+ j += dh_g_len; i += 4;
+ if(len != (8+j)) return -1;
+ i=4;
+ dh_p = BN_new();
+ BN_bin2bn((unsigned char *)(buf + i), dh_p_len, dh_p);
+ i += (dh_p_len + 4);
+ dh_g = BN_new();
+ BN_bin2bn((unsigned char *)(buf + i), dh_g_len, dh_g);
+ /* i += (dsa_g_len + 4); */
+
+ dh_params = DH_new();
+ dh_params->p = dh_p;
+ dh_params->g = dh_g;
+
+ i=0;
+ bin = return_binary(rbuf,rlen,4);
+ if (bin==NULL) return -1;
+ if(DH_check(dh_params, &i)) {
+ put_int32(bin, i);
+ } else {
+ /* Check Failed */
+ put_int32(bin, -1);
+ }
+ DH_free(dh_params);
+ return 4;
+
+ case DRV_DH_GENERATE_KEY:
+ /* buf = <<key_len:32, key:key_len/binary, *
+ * dh_p_len:32/integer, dh_p:dh_p_len/binary, *
+ * dh_g_len:32/integer, dh_g:dh_g_len/binary>> */
+ ERL_VALGRIND_ASSERT_MEM_DEFINED(buf,len);
+ i = 0;
+ j = 0;
+ if(len < 12) return -1;
+ base_len = get_int32(buf + i + j);
+ j += base_len; i += 4;
+ if (len < (12 + j)) return -1;
+ dh_p_len = get_int32(buf + i + j);
+ j += dh_p_len; i += 4;
+ if (len < (12 + j)) return -1;
+ dh_g_len = get_int32(buf + i + j);
+ j += dh_g_len; i += 4;
+ if(len != (12 + j)) return -1;
+ i=4;
+ i += (base_len + 4);
+ dh_p = BN_new();
+ BN_bin2bn((unsigned char *)(buf + i), dh_p_len, dh_p);
+ i += (dh_p_len + 4);
+ dh_g = BN_new();
+ BN_bin2bn((unsigned char *)(buf + i), dh_g_len, dh_g);
+ /* i += (dsa_g_len + 4); */
+
+ dh_params = DH_new();
+ dh_params->p = dh_p;
+ dh_params->g = dh_g;
+ if(base_len > 0) {
+ dh_params->priv_key = BN_new();
+ BN_bin2bn((unsigned char *)(buf + i), base_len,
+ dh_params->priv_key);
+ }
+ i=0;
+ if(DH_generate_key(dh_params)) {
+ privkey_len = BN_num_bytes(dh_params->priv_key);
+ pubkey_len = BN_num_bytes(dh_params->pub_key);
+ dlen = 1 + 4 + 4 + pubkey_len + privkey_len;
+ bin = return_binary(rbuf,rlen, dlen);
+ if (bin==NULL) return -1;
+ bin[0] = 1;
+ put_int32(bin+1, pubkey_len);
+ BN_bn2bin(dh_params->pub_key, bin+5);
+ ERL_VALGRIND_MAKE_MEM_DEFINED(bin+5, pubkey_len);
+ put_int32(bin+5+pubkey_len, privkey_len);
+ BN_bn2bin(dh_params->priv_key, bin+5+pubkey_len+4);
+ ERL_VALGRIND_MAKE_MEM_DEFINED(bin+5+pubkey_len+4, privkey_len);
+ } else {
+ dlen = 1;
+ bin = return_binary(rbuf,rlen,dlen);
+ if (bin==NULL) return -1;
+ bin[0] = 0;
+ }
+ DH_free(dh_params);
+ return dlen;
+
+ case DRV_DH_COMPUTE_KEY:
+ /* buf = <<pubkey_len:32, pubkey:pubkey_len/binary, *
+ * privkey_len:32, privkey:privkey_len/binary, *
+ * dh_p_len:32/integer, dh_p:dh_p_len/binary, *
+ * dh_g_len:32/integer, dh_g:dh_g_len/binary>> */
+ i = 0;
+ j = 0;
+ if(len < 16) return -1;
+ pubkey_len = get_int32(buf + i + j);
+ j += pubkey_len; i += 4;
+ if (len < (16 + j)) return -1;
+ privkey_len = get_int32(buf + i + j);
+ j += privkey_len; i += 4;
+ if (len < (16 + j)) return -1;
+ dh_p_len = get_int32(buf + i + j);
+ j += dh_p_len; i += 4;
+ if (len < (16 + j)) return -1;
+ dh_g_len = get_int32(buf + i + j);
+ j += dh_g_len; i += 4;
+ if(len != (16 + j)) return -1;
+ i=4;
+ pubkey = BN_new();
+ BN_bin2bn((unsigned char *)(buf + i), pubkey_len, pubkey);
+ i += (pubkey_len + 4);
+ privkey = BN_new();
+ BN_bin2bn((unsigned char *)(buf + i), privkey_len, privkey);
+ i += (privkey_len + 4);
+ dh_p = BN_new();
+ BN_bin2bn((unsigned char *)(buf + i), dh_p_len, dh_p);
+ i += (dh_p_len + 4);
+ dh_g = BN_new();
+ BN_bin2bn((unsigned char *)(buf + i), dh_g_len, dh_g);
+ /* i += (dsa_g_len + 4); */
+
+ dh_params = DH_new();
+ dh_params->p = dh_p;
+ dh_params->g = dh_g;
+ dh_params->priv_key = privkey;
+
+ klen = DH_size(dh_params);
+ bin = return_binary(rbuf,rlen,1+klen);
+ if (bin==NULL) return -1;
+ i = DH_compute_key(&bin[1], pubkey, dh_params);
+ DH_free(dh_params);
+ if (i > 0) {
+ if (i != klen) {
+ bin = return_binary_shrink(rbuf,rlen,bin,1+i);
+ }
+ bin[0] = 1;
+ return i + 1;
+ }
+ else {
+ bin[0] = 0;
+ return 1;
+ }
+
+ case DRV_MD4:
+ bin = return_binary(rbuf,rlen,MD4_LEN);
+ MD4((unsigned char *)buf, len, (unsigned char *)bin);
+ return MD4_LEN;
+
+ case DRV_MD4_INIT:
+ bin = return_binary(rbuf,rlen,MD4_CTX_LEN);
+ MD4_Init((MD4_CTX *) bin);
+ return MD4_CTX_LEN;
+
+ case DRV_MD4_UPDATE:
+ if (len < MD4_CTX_LEN)
+ return -1;
+ bin = return_binary(rbuf,rlen,MD4_CTX_LEN);
+ memcpy(bin, buf, MD4_CTX_LEN);
+ MD4_Update((MD4_CTX *) bin, buf + MD4_CTX_LEN, len - MD4_CTX_LEN);
+ return MD4_CTX_LEN;
+
+ case DRV_MD4_FINAL:
+ if (len != MD4_CTX_LEN)
+ return -1;
+ memcpy(&md4_ctx, buf, MD4_CTX_LEN); /* XXX Use buf only? */
+ bin = return_binary(rbuf,rlen,MD4_LEN);
+ MD4_Final((unsigned char *)bin, &md4_ctx);
+ return MD4_LEN;
+
+#if SSL_VERSION_0_9_8
+ case DRV_SHA256:
+ bin = return_binary(rbuf,rlen,SHA256_LEN);
+ SHA256(buf, len, bin);
+ return SHA256_LEN;
+
+ case DRV_SHA256_INIT:
+ bin = return_binary(rbuf,rlen,SHA256_CTX_LEN);
+ SHA256_Init((SHA256_CTX *)bin);
+ return SHA256_CTX_LEN;
+
+ case DRV_SHA256_UPDATE:
+ if (len < SHA256_CTX_LEN)
+ return -1;
+ bin = return_binary(rbuf,rlen,SHA256_CTX_LEN);
+ memcpy(bin, buf, SHA256_CTX_LEN);
+ SHA256_Update((SHA256_CTX *)bin, buf + SHA256_CTX_LEN,
+ len - SHA256_CTX_LEN);
+ return SHA256_CTX_LEN;
+
+ case DRV_SHA256_FINAL:
+ if (len != SHA256_CTX_LEN)
+ return -1;
+ memcpy(&sha256_ctx, buf, SHA256_CTX_LEN); /* XXX Use buf only? */
+ bin = return_binary(rbuf,rlen,SHA256_LEN);
+ SHA256_Final(bin, &sha256_ctx);
+ return SHA256_LEN;
+
+ case DRV_SHA512:
+ bin = return_binary(rbuf,rlen,SHA512_LEN);
+ SHA512(buf, len, bin);
+ return SHA512_LEN;
+
+ case DRV_SHA512_INIT:
+ bin = return_binary(rbuf,rlen,SHA512_CTX_LEN);
+ SHA512_Init((SHA512_CTX *)bin);
+ return SHA512_CTX_LEN;
+
+ case DRV_SHA512_UPDATE:
+ if (len < SHA512_CTX_LEN)
+ return -1;
+ bin = return_binary(rbuf,rlen,SHA512_CTX_LEN);
+ memcpy(bin, buf, SHA512_CTX_LEN);
+ SHA512_Update((SHA512_CTX *)bin, buf + SHA512_CTX_LEN,
+ len - SHA512_CTX_LEN);
+ return SHA512_CTX_LEN;
+
+ case DRV_SHA512_FINAL:
+ if (len != SHA512_CTX_LEN)
+ return -1;
+ memcpy(&sha512_ctx, buf, SHA512_CTX_LEN); /* XXX Use buf only? */
+ bin = return_binary(rbuf,rlen,SHA512_LEN));
+ SHA512_Final(bin, &sha512_ctx);
+ return SHA512_LEN;
+#endif
+
+ case DRV_INFO_LIB:
+ {/* <<DrvVer:8, NameSize:8, Name:NameSize/binary, VerNum:32, VerStr/binary>> */
+ static const char libname[] = "OpenSSL";
+ unsigned name_sz = strlen(libname);
+ const char* ver = SSLeay_version(SSLEAY_VERSION);
+ unsigned ver_sz = strlen(ver);
+ dlen = 1+1+name_sz+4+ver_sz;
+ bin = return_binary(rbuf, rlen, dlen);
+ if (bin==NULL) return -1;
+ p = bin;
+ *p++ = 0; /* "driver version" for future use */
+ *p++ = name_sz;
+ memcpy(p, libname, name_sz);
+ p += name_sz;
+ put_int32(p,SSLeay()); /* OPENSSL_VERSION_NUMBER */
+ p += 4;
+ memcpy(p, ver, ver_sz);
+ }
+ return dlen;
+
+ default:
+ break;
+ }
+ return -1;
+}
+
+
+#ifdef OPENSSL_THREADS /* vvvvvvvvvvvvvvv OPENSSL_THREADS vvvvvvvvvvvvvvvv */
+
+static INLINE void locking(int mode, ErlDrvRWLock* lock)
+{
+ switch(mode) {
+ case CRYPTO_LOCK|CRYPTO_READ:
+ erl_drv_rwlock_rlock(lock);
+ break;
+ case CRYPTO_LOCK|CRYPTO_WRITE:
+ erl_drv_rwlock_rwlock(lock);
+ break;
+ case CRYPTO_UNLOCK|CRYPTO_READ:
+ erl_drv_rwlock_runlock(lock);
+ break;
+ case CRYPTO_UNLOCK|CRYPTO_WRITE:
+ erl_drv_rwlock_rwunlock(lock);
+ break;
+ default:
+ ASSERT(!"Invalid lock mode");
+ }
+}
+
+/* Callback from openssl for static locking
+ */
+static void locking_function(int mode, int n, const char *file, int line)
+{
+ ASSERT(n>=0 && n<CRYPTO_num_locks());
+
+ locking(mode, lock_vec[n]);
+}
+
+/* Callback from openssl for thread id
+ */
+static unsigned long id_function(void)
+{
+ return (unsigned long) erl_drv_thread_self();
+}
+
+/* Callbacks for dynamic locking, not used by current openssl version (0.9.8)
+ */
+static struct CRYPTO_dynlock_value* dyn_create_function(const char *file, int line)
+{
+ return (struct CRYPTO_dynlock_value*) erl_drv_rwlock_create("crypto_drv_dyn");
+}
+static void dyn_lock_function(int mode, struct CRYPTO_dynlock_value* ptr,const char *file, int line)
+{
+ locking(mode, (ErlDrvRWLock*)ptr);
+}
+static void dyn_destroy_function(struct CRYPTO_dynlock_value *ptr, const char *file, int line)
+{
+ erl_drv_rwlock_destroy((ErlDrvRWLock*)ptr);
+}
+
+#endif /* ^^^^^^^^^^^^^^^^^^^^^^ OPENSSL_THREADS ^^^^^^^^^^^^^^^^^^^^^^ */
+
+/* HMAC */
+
+static void hmac_md5(char *key, int klen, char *dbuf, int dlen, 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_CTX kctx;
+
+ MD5_Init(&kctx);
+ MD5_Update(&kctx, key, klen);
+ MD5_Final(nkey, &kctx);
+ key = (char *) 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(char *key, int klen, char *dbuf, int dlen,
+ 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) {
+ SHA_CTX kctx;
+
+ SHA1_Init(&kctx);
+ SHA1_Update(&kctx, key, klen);
+ SHA1_Final(nkey, &kctx);
+ key = (char *) 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);
+}
diff --git a/lib/crypto/doc/html/.gitignore b/lib/crypto/doc/html/.gitignore
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/lib/crypto/doc/html/.gitignore
diff --git a/lib/crypto/doc/man3/.gitignore b/lib/crypto/doc/man3/.gitignore
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/lib/crypto/doc/man3/.gitignore
diff --git a/lib/crypto/doc/man6/.gitignore b/lib/crypto/doc/man6/.gitignore
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/lib/crypto/doc/man6/.gitignore
diff --git a/lib/crypto/doc/pdf/.gitignore b/lib/crypto/doc/pdf/.gitignore
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/lib/crypto/doc/pdf/.gitignore
diff --git a/lib/crypto/doc/src/Makefile b/lib/crypto/doc/src/Makefile
new file mode 100644
index 0000000000..d2cec9b11b
--- /dev/null
+++ b/lib/crypto/doc/src/Makefile
@@ -0,0 +1,113 @@
+# ``The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved via the world wide web at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# The Initial Developer of the Original Code is Ericsson Utvecklings AB.
+# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
+# AB. All Rights Reserved.''
+#
+# $Id$
+#
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+# ----------------------------------------------------
+# Application version
+# ----------------------------------------------------
+include ../../vsn.mk
+VSN=$(CRYPTO_VSN)
+APPLICATION=crypto
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN)
+
+# ----------------------------------------------------
+# Target Specs
+# ----------------------------------------------------
+XML_APPLICATION_FILES = ref_man.xml
+XML_REF3_FILES = crypto.xml
+XML_REF6_FILES = crypto_app.xml
+
+XML_PART_FILES = release_notes.xml usersguide.xml
+XML_CHAPTER_FILES = notes.xml licenses.xml
+
+BOOK_FILES = book.xml
+
+GIF_FILES =
+
+# ----------------------------------------------------
+
+HTML_FILES = $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%.html) \
+ $(XML_PART_FILES:%.xml=$(HTMLDIR)/%.html)
+
+INFO_FILE = ../../info
+
+MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3)
+MAN6_FILES = $(XML_REF6_FILES:%_app.xml=$(MAN6DIR)/%.6)
+
+HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
+
+TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+XML_FLAGS +=
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+$(HTMLDIR)/%.gif: %.gif
+ $(INSTALL_DATA) $< $@
+
+
+docs: pdf html man
+
+$(TOP_PDF_FILE): $(XML_FILES)
+
+pdf: $(TOP_PDF_FILE)
+
+html: gifs $(HTML_REF_MAN_FILE)
+
+man: $(MAN3_FILES) $(MAN6_FILES)
+
+gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
+
+debug opt valgrind:
+
+clean clean_docs clean_tex:
+ rm -rf $(HTMLDIR)/*
+ rm -f $(MAN3DIR)/*
+ rm -f $(MAN6DIR)/*
+ rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
+ rm -f errs core *~
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+release_docs_spec: docs
+ $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf
+ $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf
+ $(INSTALL_DIR) $(RELSYSDIR)/doc/html
+ $(INSTALL_DATA) $(HTMLDIR)/* \
+ $(RELSYSDIR)/doc/html
+ $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR)
+ $(INSTALL_DIR) $(RELEASE_PATH)/man/man3
+ $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3
+ $(INSTALL_DIR) $(RELEASE_PATH)/man/man6
+ $(INSTALL_DATA) $(MAN6DIR)/* $(RELEASE_PATH)/man/man6
+
+
+release_spec:
+
diff --git a/lib/crypto/doc/src/book.xml b/lib/crypto/doc/src/book.xml
new file mode 100644
index 0000000000..f07208482c
--- /dev/null
+++ b/lib/crypto/doc/src/book.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE book SYSTEM "book.dtd">
+
+<book xmlns:xi="http://www.w3.org/2001/XInclude">
+ <header titlestyle="normal">
+ <copyright>
+ <year>1999</year><year>2009</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ The contents of this file are subject to the Erlang Public License,
+ Version 1.1, (the "License"); you may not use this file except in
+ compliance with the License. You should have received a copy of the
+ Erlang Public License along with this software. If not, it can be
+ retrieved online at http://www.erlang.org/.
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and limitations
+ under the License.
+
+ </legalnotice>
+
+ <title>crypto</title>
+ <prepared>Peter H&ouml;gfeldt</prepared>
+ <docno></docno>
+ <date>1999-01-21</date>
+ <rev>A</rev>
+ <file>book.sgml</file>
+ </header>
+ <insidecover>
+ <include file="insidecover"></include>
+ </insidecover>
+ <pagetext>crypto</pagetext>
+ <preamble>
+ <contents level="2"></contents>
+ </preamble>
+ <parts lift="no">
+ <xi:include href="usersguide.xml"/>
+ </parts>
+ <applications>
+ <xi:include href="ref_man.xml"/>
+ </applications>
+ <releasenotes>
+ <xi:include href="notes.xml"/>
+ </releasenotes>
+ <listofterms></listofterms>
+ <index></index>
+</book>
+
diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml
new file mode 100644
index 0000000000..42ba523c8c
--- /dev/null
+++ b/lib/crypto/doc/src/crypto.xml
@@ -0,0 +1,785 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>1999</year><year>2009</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ The contents of this file are subject to the Erlang Public License,
+ Version 1.1, (the "License"); you may not use this file except in
+ compliance with the License. You should have received a copy of the
+ Erlang Public License along with this software. If not, it can be
+ retrieved online at http://www.erlang.org/.
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and limitations
+ under the License.
+
+ </legalnotice>
+
+ <title>crypto</title>
+ <prepared>Peter H&ouml;gfeldt</prepared>
+ <docno></docno>
+ <date>2000-06-20</date>
+ <rev>B</rev>
+ </header>
+ <module>crypto</module>
+ <modulesummary>Crypto Functions</modulesummary>
+ <description>
+ <p>This module provides a set of cryptographic functions.
+ </p>
+ <p>References:</p>
+ <list type="bulleted">
+ <item>
+ <p>md5: The MD5 Message Digest Algorithm (RFC 1321)</p>
+ </item>
+ <item>
+ <p>sha: Secure Hash Standard (FIPS 180-2)</p>
+ </item>
+ <item>
+ <p>hmac: Keyed-Hashing for Message Authentication (RFC 2104)</p>
+ </item>
+ <item>
+ <p>des: Data Encryption Standard (FIPS 46-3)</p>
+ </item>
+ <item>
+ <p>aes: Advanced Encryption Standard (AES) (FIPS 197) </p>
+ </item>
+ <item>
+ <p>ecb, cbc, cfb, ofb: Recommendation for Block Cipher Modes
+ of Operation (NIST SP 800-38A).</p>
+ </item>
+ <item>
+ <p>rsa: Recommendation for Block Cipher Modes of Operation
+ (NIST 800-38A)</p>
+ </item>
+ <item>
+ <p>dss: Digital Signature Standard (FIPS 186-2)</p>
+ </item>
+ </list>
+ <p>The above publications can be found at <url href="http://csrc.nist.gov/publications">NIST publications</url>, at <url href="http://www.ietf.org">IETF</url>.
+ </p>
+ <p><em>Types</em></p>
+ <pre>
+byte() = 0 ... 255
+ioelem() = byte() | binary() | iolist()
+iolist() = [ioelem()]
+Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]>
+ </pre>
+ <p></p>
+ </description>
+ <funcs>
+ <func>
+ <name>start() -> ok</name>
+ <fsummary>Start the crypto server.</fsummary>
+ <desc>
+ <p>Starts the crypto server.</p>
+ </desc>
+ </func>
+ <func>
+ <name>stop() -> ok</name>
+ <fsummary>Stop the crypto server.</fsummary>
+ <desc>
+ <p>Stops the crypto server.</p>
+ </desc>
+ </func>
+ <func>
+ <name>info() -> [atom()]</name>
+ <fsummary>Provide a list of available crypto functions.</fsummary>
+ <desc>
+ <p>Provides the available crypto functions in terms of a list
+ of atoms.</p>
+ </desc>
+ </func>
+ <func>
+ <name>info_lib() -> [{Name,VerNum,VerStr}]</name>
+ <fsummary>Provides information about the libraries used by crypto.</fsummary>
+ <type>
+ <v>Name = binary()</v>
+ <v>VerNum = integer()</v>
+ <v>VerStr = binary()</v>
+ </type>
+ <desc>
+ <p>Provides the name and version of the libraries used by crypto.</p>
+ <p><c>Name</c> is the name of the library. <c>VerNum</c> is
+ the numeric version according to the library's own versioning
+ scheme. <c>VerStr</c> contains a text variant of the version.</p>
+ <pre>
+> <input>info_lib().</input>
+[{&lt;&lt;"OpenSSL"&gt;&gt;,9469983,&lt;&lt;"OpenSSL 0.9.8a 11 Oct 2005"&gt;&gt;}]
+ </pre>
+ </desc>
+ </func>
+ <func>
+ <name>md5(Data) -> Digest</name>
+ <fsummary>Compute an <c>MD5</c>message digest from <c>Data</c></fsummary>
+ <type>
+ <v>Data = iolist() | binary()</v>
+ <v>Digest = binary()</v>
+ </type>
+ <desc>
+ <p>Computes an <c>MD5</c> message digest from <c>Data</c>, where
+ the length of the digest is 128 bits (16 bytes).</p>
+ </desc>
+ </func>
+ <func>
+ <name>md5_init() -> Context</name>
+ <fsummary>Creates an MD5 context</fsummary>
+ <type>
+ <v>Context = binary()</v>
+ </type>
+ <desc>
+ <p>Creates an MD5 context, to be used in subsequent calls to
+ <c>md5_update/2</c>.</p>
+ </desc>
+ </func>
+ <func>
+ <name>md5_update(Context, Data) -> NewContext</name>
+ <fsummary>Update an MD5 <c>Context</c>with <c>Data</c>, and return a <c>NewContext</c></fsummary>
+ <type>
+ <v>Data = iolist() | binary()</v>
+ <v>Context = NewContext = binary()</v>
+ </type>
+ <desc>
+ <p>Updates an MD5 <c>Context</c> with <c>Data</c>, and returns
+ a <c>NewContext</c>.</p>
+ </desc>
+ </func>
+ <func>
+ <name>md5_final(Context) -> Digest</name>
+ <fsummary>Finish the update of an MD5 <c>Context</c>and return the computed <c>MD5</c>message digest</fsummary>
+ <type>
+ <v>Context = Digest = binary()</v>
+ </type>
+ <desc>
+ <p>Finishes the update of an MD5 <c>Context</c> and returns
+ the computed <c>MD5</c> message digest.</p>
+ </desc>
+ </func>
+ <func>
+ <name>sha(Data) -> Digest</name>
+ <fsummary>Compute an <c>SHA</c>message digest from <c>Data</c></fsummary>
+ <type>
+ <v>Data = iolist() | binary()</v>
+ <v>Digest = binary()</v>
+ </type>
+ <desc>
+ <p>Computes an <c>SHA</c> message digest from <c>Data</c>, where
+ the length of the digest is 160 bits (20 bytes).</p>
+ </desc>
+ </func>
+ <func>
+ <name>sha_init() -> Context</name>
+ <fsummary>Create an SHA context</fsummary>
+ <type>
+ <v>Context = binary()</v>
+ </type>
+ <desc>
+ <p>Creates an SHA context, to be used in subsequent calls to
+ <c>sha_update/2</c>.</p>
+ </desc>
+ </func>
+ <func>
+ <name>sha_update(Context, Data) -> NewContext</name>
+ <fsummary>Update an SHA context</fsummary>
+ <type>
+ <v>Data = iolist() | binary()</v>
+ <v>Context = NewContext = binary()</v>
+ </type>
+ <desc>
+ <p>Updates an SHA <c>Context</c> with <c>Data</c>, and returns
+ a <c>NewContext</c>.</p>
+ </desc>
+ </func>
+ <func>
+ <name>sha_final(Context) -> Digest</name>
+ <fsummary>Finish the update of an SHA context</fsummary>
+ <type>
+ <v>Context = Digest = binary()</v>
+ </type>
+ <desc>
+ <p>Finishes the update of an SHA <c>Context</c> and returns
+ the computed <c>SHA</c> message digest.</p>
+ </desc>
+ </func>
+ <func>
+ <name>md5_mac(Key, Data) -> Mac</name>
+ <fsummary>Compute an <c>MD5 MAC</c>message authentification code</fsummary>
+ <type>
+ <v>Key = Data = iolist() | binary()</v>
+ <v>Mac = binary()</v>
+ </type>
+ <desc>
+ <p>Computes an <c>MD5 MAC</c> message authentification code
+ from <c>Key</c> and <c>Data</c>, where the the length of the
+ Mac is 128 bits (16 bytes).</p>
+ </desc>
+ </func>
+ <func>
+ <name>md5_mac_96(Key, Data) -> Mac</name>
+ <fsummary>Compute an <c>MD5 MAC</c>message authentification code</fsummary>
+ <type>
+ <v>Key = Data = iolist() | binary()</v>
+ <v>Mac = binary()</v>
+ </type>
+ <desc>
+ <p>Computes an <c>MD5 MAC</c> message authentification code
+ from <c>Key</c> and <c>Data</c>, where the length of the Mac
+ is 96 bits (12 bytes).</p>
+ </desc>
+ </func>
+ <func>
+ <name>sha_mac(Key, Data) -> Mac</name>
+ <fsummary>Compute an <c>MD5 MAC</c>message authentification code</fsummary>
+ <type>
+ <v>Key = Data = iolist() | binary()</v>
+ <v>Mac = binary()</v>
+ </type>
+ <desc>
+ <p>Computes an <c>SHA MAC</c> message authentification code
+ from <c>Key</c> and <c>Data</c>, where the length of the Mac
+ is 160 bits (20 bytes).</p>
+ </desc>
+ </func>
+ <func>
+ <name>sha_mac_96(Key, Data) -> Mac</name>
+ <fsummary>Compute an <c>MD5 MAC</c>message authentification code</fsummary>
+ <type>
+ <v>Key = Data = iolist() | binary()</v>
+ <v>Mac = binary()</v>
+ </type>
+ <desc>
+ <p>Computes an <c>SHA MAC</c> message authentification code
+ from <c>Key</c> and <c>Data</c>, where the length of the Mac
+ is 96 bits (12 bytes).</p>
+ </desc>
+ </func>
+ <func>
+ <name>des_cbc_encrypt(Key, IVec, Text) -> Cipher</name>
+ <fsummary>Encrypt <c>Text</c>according to DES in CBC mode</fsummary>
+ <type>
+ <v>Key = Text = iolist() | binary()</v>
+ <v>IVec = Cipher = binary()</v>
+ </type>
+ <desc>
+ <p>Encrypts <c>Text</c> according to DES in CBC
+ mode. <c>Text</c> must be a multiple of 64 bits (8
+ bytes). <c>Key</c> is the DES key, and <c>IVec</c> is an
+ arbitrary initializing vector. The lengths of <c>Key</c> and
+ <c>IVec</c> must be 64 bits (8 bytes).</p>
+ </desc>
+ </func>
+ <func>
+ <name>des_cbc_decrypt(Key, IVec, Cipher) -> Text</name>
+ <fsummary>Decrypt <c>Cipher</c>according to DES in CBC mode</fsummary>
+ <type>
+ <v>Key = Cipher = iolist() | binary()</v>
+ <v>IVec = Text = binary()</v>
+ </type>
+ <desc>
+ <p>Decrypts <c>Cipher</c> according to DES in CBC mode.
+ <c>Key</c> is the DES key, and <c>IVec</c> is an arbitrary
+ initializing vector. <c>Key</c> and <c>IVec</c> must have
+ the same values as those used when encrypting. <c>Cipher</c>
+ must be a multiple of 64 bits (8 bytes). The lengths of
+ <c>Key</c> and <c>IVec</c> must be 64 bits (8 bytes).</p>
+ </desc>
+ </func>
+ <func>
+ <name>des_cbc_ivec(Data) -> IVec</name>
+ <fsummary>Get <c>IVec</c> to be used in next iteration of
+ <c>des_cbc_[ecrypt|decrypt]</c></fsummary>
+ <type>
+ <v>Data = iolist() | binary()</v>
+ <v>IVec = binary()</v>
+ </type>
+ <desc>
+ <p>Returns the <c>IVec</c> to be used in a next iteration of
+ <c>des_cbc_[encrypt|decrypt]</c>. <c>Data</c> is the encrypted
+ data from the previous iteration step.</p>
+ </desc>
+ </func>
+ <func>
+ <name>des3_cbc_encrypt(Key1, Key2, Key3, IVec, Text) -> Cipher</name>
+ <fsummary>Encrypt <c>Text</c>according to DES3 in CBC mode</fsummary>
+ <type>
+ <v>Key1 =Key2 = Key3 Text = iolist() | binary()</v>
+ <v>IVec = Cipher = binary()</v>
+ </type>
+ <desc>
+ <p>Encrypts <c>Text</c> according to DES3 in CBC
+ mode. <c>Text</c> must be a multiple of 64 bits (8
+ bytes). <c>Key1</c>, <c>Key2</c>, <c>Key3</c>, are the DES
+ keys, and <c>IVec</c> is an arbitrary initializing
+ vector. The lengths of each of <c>Key1</c>, <c>Key2</c>,
+ <c>Key3</c> and <c>IVec</c> must be 64 bits (8 bytes).</p>
+ </desc>
+ </func>
+ <func>
+ <name>des3_cbc_decrypt(Key1, Key2, Key3, IVec, Cipher) -> Text</name>
+ <fsummary>Decrypt <c>Cipher</c>according to DES in CBC mode</fsummary>
+ <type>
+ <v>Key1 = Key2 = Key3 = Cipher = iolist() | binary()</v>
+ <v>IVec = Text = binary()</v>
+ </type>
+ <desc>
+ <p>Decrypts <c>Cipher</c> according to DES3 in CBC mode.
+ <c>Key1</c>, <c>Key2</c>, <c>Key3</c> are the DES key, and
+ <c>IVec</c> is an arbitrary initializing vector.
+ <c>Key1</c>, <c>Key2</c>, <c>Key3</c> and <c>IVec</c> must
+ and <c>IVec</c> must have the same values as those used when
+ encrypting. <c>Cipher</c> must be a multiple of 64 bits (8
+ bytes). The lengths of <c>Key1</c>, <c>Key2</c>,
+ <c>Key3</c>, and <c>IVec</c> must be 64 bits (8 bytes).</p>
+ </desc>
+ </func>
+ <func>
+ <name>blowfish_cfb64_encrypt(Key, IVec, Text) -> Cipher</name>
+ <fsummary>Encrypt <c>Text</c>using Blowfish in CFB mode with 64
+ bit feedback</fsummary>
+ <type>
+ <v>Key = Text = iolist() | binary()</v>
+ <v>IVec = Cipher = binary()</v>
+ </type>
+ <desc>
+ <p>Encrypts <c>Text</c> using Blowfish in CFB mode with 64 bit
+ feedback. <c>Key</c> is the Blowfish key, and <c>IVec</c> is an
+ arbitrary initializing vector. The length of <c>IVec</c>
+ must be 64 bits (8 bytes).</p>
+ </desc>
+ </func>
+ <func>
+ <name>blowfish_cfb64_decrypt(Key, IVec, Text) -> Cipher</name>
+ <fsummary>Decrypt <c>Text</c>using Blowfish in CFB mode with 64
+ bit feedback</fsummary>
+ <type>
+ <v>Key = Text = iolist() | binary()</v>
+ <v>IVec = Cipher = binary()</v>
+ </type>
+ <desc>
+ <p>Decrypts <c>Text</c> using Blowfish in CFB mode with 64 bit
+ feedback. <c>Key</c> is the Blowfish key, and <c>IVec</c> is an
+ arbitrary initializing vector. The length of <c>IVec</c>
+ must be 64 bits (8 bytes).</p>
+ </desc>
+ </func>
+ <func>
+ <name>aes_cfb_128_encrypt(Key, IVec, Text) -> Cipher</name>
+ <name>aes_cbc_128_encrypt(Key, IVec, Text) -> Cipher</name>
+ <fsummary>Encrypt <c>Text</c>according to AES in Cipher Feedback mode or Cipher Block Chaining mode</fsummary>
+ <type>
+ <v>Key = Text = iolist() | binary()</v>
+ <v>IVec = Cipher = binary()</v>
+ </type>
+ <desc>
+ <p>Encrypts <c>Text</c> according to AES in Cipher Feedback
+ mode (CFB) or Cipher Block Chaining mode (CBC). <c>Text</c>
+ must be a multiple of 128 bits (16 bytes). <c>Key</c> is the
+ AES key, and <c>IVec</c> is an arbitrary initializing vector.
+ The lengths of <c>Key</c> and <c>IVec</c> must be 128 bits
+ (16 bytes).</p>
+ </desc>
+ </func>
+ <func>
+ <name>aes_cfb_128_decrypt(Key, IVec, Cipher) -> Text</name>
+ <name>aes_cbc_128_decrypt(Key, IVec, Cipher) -> Text</name>
+ <fsummary>Decrypt <c>Cipher</c>according to AES in Cipher Feedback mode or Cipher Block Chaining mode</fsummary>
+ <type>
+ <v>Key = Cipher = iolist() | binary()</v>
+ <v>IVec = Text = binary()</v>
+ </type>
+ <desc>
+ <p>Decrypts <c>Cipher</c> according to Cipher Feedback Mode (CFB)
+ or Cipher Block Chaining mode (CBC).
+ <c>Key</c> is the AES key, and <c>IVec</c> is an arbitrary
+ initializing vector. <c>Key</c> and <c>IVec</c> must have
+ the same values as those used when encrypting. <c>Cipher</c>
+ must be a multiple of 128 bits (16 bytes). The lengths of
+ <c>Key</c> and <c>IVec</c> must be 128 bits (16 bytes).</p>
+ </desc>
+ </func>
+ <func>
+ <name>aes_cbc_ivec(Data) -> IVec</name>
+ <fsummary>Get <c>IVec</c> to be used in next iteration of
+ <c>aes_cbc_*_[ecrypt|decrypt]</c></fsummary>
+ <type>
+ <v>Data = iolist() | binary()</v>
+ <v>IVec = binary()</v>
+ </type>
+ <desc>
+ <p>Returns the <c>IVec</c> to be used in a next iteration of
+ <c>aes_cbc_*_[encrypt|decrypt]</c>. <c>Data</c> is the encrypted
+ data from the previous iteration step.</p>
+ </desc>
+ </func>
+ <func>
+ <name>erlint(Mpint) -> N</name>
+ <name>mpint(N) -> Mpint</name>
+ <fsummary>Convert between binary multi-precision integer and erlang big integer</fsummary>
+ <type>
+ <v>Mpint = binary()</v>
+ <v>N = integer()</v>
+ </type>
+ <desc>
+ <p>Convert a binary multi-precision integer <c>Mpint</c> to and from
+ an erlang big integer. A multi-precision integer is a binary
+ with the following form:
+ <c><![CDATA[<<ByteLen:32/integer, Bytes:ByteLen/binary>>]]></c> where both
+ <c>ByteLen</c> and <c>Bytes</c> are big-endian. Mpints are used in
+ some of the functions in <c>crypto</c> and are not translated
+ in the API for performance reasons.</p>
+ </desc>
+ </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>
+ </desc>
+ </func>
+ <func>
+ <name>rand_uniform(Lo, Hi) -> N</name>
+ <fsummary>Generate a random number</fsummary>
+ <type>
+ <v>Lo, Hi, N = Mpint | integer()</v>
+ <v>Mpint = binary()</v>
+ </type>
+ <desc>
+ <p>Generate a random number <c><![CDATA[N, Lo =< N < Hi.]]></c> Uses the
+ <c>crypto</c> library pseudo-random number generator. The
+ arguments (and result) can be either erlang integers or binary
+ multi-precision integers.</p>
+ </desc>
+ </func>
+ <func>
+ <name>mod_exp(N, P, M) -> Result</name>
+ <fsummary>Perform N ^ P mod M</fsummary>
+ <type>
+ <v>N, P, M, Result = Mpint</v>
+ <v>Mpint = binary()</v>
+ </type>
+ <desc>
+ <p>This function performs the exponentiation <c>N ^ P mod M</c>,
+ using the <c>crypto</c> library.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>rsa_sign(Data, Key) -> Signature</name>
+ <name>rsa_sign(DigestType, Data, Key) -> Signature</name>
+ <fsummary>Sign the data using rsa with the given key.</fsummary>
+ <type>
+ <v>Data = Mpint</v>
+ <v>Key = [E, N, D]</v>
+ <v>E, N, D = Mpint</v>
+ <d>Where <c>E</c> is the public exponent, <c>N</c> is public modulus and
+ <c>D</c> is the private exponent.</d>
+ <v>DigestType = md5 | sha</v>
+ <d>The default <c>DigestType</c> is sha.</d>
+ <v>Mpint = binary()</v>
+ <v>Signature = binary()</v>
+ </type>
+ <desc>
+ <p>Calculates a <c>DigestType</c> digest of the <c>Data</c>
+ and creates a RSA signature with the private key <c>Key</c>
+ of the digest.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>rsa_verify(Data, Signature, Key) -> Verified</name>
+ <name>rsa_verify(DigestType, Data, Signature, Key) -> Verified </name>
+ <fsummary>Verify the digest and signature using rsa with given public key.</fsummary>
+ <type>
+ <v>Verified = boolean()</v>
+ <v>Data, Signature = Mpint</v>
+ <v>Key = [E, N]</v>
+ <v>E, N = Mpint</v>
+ <d>Where <c>E</c> is the public exponent and <c>N</c> is public modulus.</d>
+ <v>DigestType = md5 | sha</v>
+ <d> The default <c>DigestType</c> is sha.</d>
+ <v>Mpint = binary()</v>
+ </type>
+ <desc>
+ <p>Calculates a <c>DigestType</c> digest of the <c>Data</c>
+ and verifies that the digest matches the RSA signature using the
+ signer's public key <c>Key</c>.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>rsa_public_encrypt(PlainText, PublicKey, Padding) -> ChipherText</name>
+ <fsummary>Encrypts Msg using the public Key.</fsummary>
+ <type>
+ <v>PlainText = binary()</v>
+ <v>PublicKey = [E, N]</v>
+ <v>E, N = Mpint</v>
+ <d>Where <c>E</c> is the public exponent and <c>N</c> is public modulus.</d>
+ <v>Padding = rsa_pkcs1_padding | rsa_pkcs1_oaep_padding | rsa_no_padding</v>
+ <v>ChipherText = binary()</v>
+ </type>
+ <desc>
+ <p>Encrypts the <c>PlainText</c> (usually a session key) using the <c>PublicKey</c>
+ and returns the cipher. The <c>Padding</c> decides what padding mode is used,
+ <c>rsa_pkcs1_padding</c> is PKCS #1 v1.5 currently the most
+ used mode and <c>rsa_pkcs1_oaep_padding</c> is EME-OAEP as
+ defined in PKCS #1 v2.0 with SHA-1, MGF1 and an empty encoding
+ parameter. This mode is recommended for all new applications.
+ The size of the <c>Msg</c> must be less
+ than <c>byte_size(N)-11</c> if
+ <c>rsa_pkcs1_padding</c> is used, <c>byte_size(N)-41</c> if
+ <c>rsa_pkcs1_oaep_padding</c> is used and <c>byte_size(N)</c> if <c>rsa_no_padding</c>
+ is used.
+ Where byte_size(N) is the size part of an <c>Mpint-1</c>.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>rsa_private_decrypt(ChipherText, PrivateKey, Padding) -> PlainText</name>
+ <fsummary>Decrypts ChipherText using the private Key.</fsummary>
+ <type>
+ <v>ChipherText = binary()</v>
+ <v>PrivateKey = [E, N, D]</v>
+ <v>E, N, D = Mpint</v>
+ <d>Where <c>E</c> is the public exponent, <c>N</c> is public modulus and
+ <c>D</c> is the private exponent.</d>
+ <v>Padding = rsa_pkcs1_padding | rsa_pkcs1_oaep_padding | rsa_no_padding</v>
+ <v>PlainText = binary()</v>
+ </type>
+ <desc>
+ <p>Decrypts the <c>ChipherText</c> (usually a session key encrypted with
+ <seealso marker="#rsa_public_encrypt/3">rsa_public_encrypt/3</seealso>)
+ using the <c>PrivateKey</c> and returns the
+ message. The <c>Padding</c> is the padding mode that was
+ used to encrypt the data,
+ see <seealso marker="#rsa_public_encrypt/3">rsa_public_encrypt/3</seealso>.
+ </p>
+ </desc>
+ </func>
+ <func>
+ <name>rsa_private_encrypt(PlainText, PrivateKey, Padding) -> ChipherText</name>
+ <fsummary>Encrypts Msg using the private Key.</fsummary>
+ <type>
+ <v>PlainText = binary()</v>
+ <v>PrivateKey = [E, N, D]</v>
+ <v>E, N, D = Mpint</v>
+ <d>Where <c>E</c> is the public exponent, <c>N</c> is public modulus and
+ <c>D</c> is the private exponent.</d>
+ <v>Padding = rsa_pkcs1_padding | rsa_no_padding</v>
+ <v>ChipherText = binary()</v>
+ </type>
+ <desc>
+ <p>Encrypts the <c>PlainText</c> using the <c>PrivateKey</c>
+ and returns the cipher. The <c>Padding</c> decides what padding mode is used,
+ <c>rsa_pkcs1_padding</c> is PKCS #1 v1.5 currently the most
+ used mode.
+ The size of the <c>Msg</c> must be less than <c>byte_size(N)-11</c> if
+ <c>rsa_pkcs1_padding</c> is used, and <c>byte_size(N)</c> if <c>rsa_no_padding</c>
+ is used. Where byte_size(N) is the size part of an <c>Mpint-1</c>.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>rsa_public_decrypt(ChipherText, PublicKey, Padding) -> PlainText</name>
+ <fsummary>Decrypts ChipherText using the public Key.</fsummary>
+ <type>
+ <v>ChipherText = binary()</v>
+ <v>PublicKey = [E, N]</v>
+ <v>E, N = Mpint</v>
+ <d>Where <c>E</c> is the public exponent and <c>N</c> is public modulus</d>
+ <v>Padding = rsa_pkcs1_padding | rsa_no_padding</v>
+ <v>PlainText = binary()</v>
+ </type>
+ <desc>
+ <p>Decrypts the <c>ChipherText</c> (encrypted with
+ <seealso marker="#rsa_private_encrypt/3">rsa_private_encrypt/3</seealso>)
+ using the <c>PrivateKey</c> and returns the
+ message. The <c>Padding</c> is the padding mode that was
+ used to encrypt the data,
+ see <seealso marker="#rsa_private_encrypt/3">rsa_private_encrypt/3</seealso>.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>dss_sign(Data, Key) -> Signature</name>
+ <fsummary>Sign the data using dsa with given private key.</fsummary>
+ <type>
+ <v>Digest = Mpint</v>
+ <v>Key = [P, Q, G, X]</v>
+ <v>P, Q, G, X = Mpint</v>
+ <d> Where <c>P</c>, <c>Q</c> and <c>G</c> are the dss
+ parameters and <c>X</c> is the private key.</d>
+ <v>Mpint = binary()</v>
+ <v>Signature = binary()</v>
+ </type>
+ <desc>
+ <p>Calculates the sha digest of the <c>Data</c>
+ and creates a DSS signature with the private key <c>Key</c>
+ of the digest.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>dss_verify(Data, Signature, Key) -> Verified</name>
+ <fsummary>Verify the data and signature using dsa with given public key.</fsummary>
+ <type>
+ <v>Verified = boolean()</v>
+ <v>Digest, Signature = Mpint</v>
+ <v>Key = [P, Q, G, Y]</v>
+ <v>P, Q, G, Y = Mpint</v>
+ <d> Where <c>P</c>, <c>Q</c> and <c>G</c> are the dss
+ parameters and <c>Y</c> is the public key.</d>
+ <v>Mpint = binary()</v>
+ </type>
+ <desc>
+ <p>Calculates the sha digest of the <c>Data</c> and verifies that the
+ digest matches the DSS signature using the public key <c>Key</c>.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>rc4_encrypt(Key, Data) -> Result</name>
+ <fsummary>Encrypt data using RC4</fsummary>
+ <type>
+ <v>Key, Data = iolist() | binary()</v>
+ <v>Result = binary()</v>
+ </type>
+ <desc>
+ <p>Encrypts the data with RC4 symmetric stream encryption.
+ Since it is symmetric, the same function is used for
+ decryption.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>dh_generate_key(DHParams) -> {PublicKey,PrivateKey} </name>
+ <name>dh_generate_key(PrivateKey, DHParams) -> {PublicKey,PrivateKey} </name>
+ <fsummary>Generates a Diffie-Hellman public key</fsummary>
+ <type>
+ <v>DHParameters = [P, G]</v>
+ <v>P, G = Mpint</v>
+ <d> Where <c>P</c> is the shared prime number and <c>G</c> is the shared generator.</d>
+ <v>PublicKey, PrivateKey = Mpint()</v>
+ </type>
+ <desc>
+ <p>Generates a Diffie-Hellman <c>PublicKey</c> and <c>PrivateKey</c> (if not given).
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>dh_compute_key(OthersPublicKey, MyPrivateKey, DHParams) -> SharedSecret</name>
+ <fsummary>Computes the shared secret</fsummary>
+ <type>
+ <v>DHParameters = [P, G]</v>
+ <v>P, G = Mpint</v>
+ <d> Where <c>P</c> is the shared prime number and <c>G</c> is the shared generator.</d>
+ <v>OthersPublicKey, MyPrivateKey = Mpint()</v>
+ <v>SharedSecret = binary()</v>
+ </type>
+ <desc>
+ <p>Computes the shared secret from the private key and the other party's public key.
+ </p>
+ </desc>
+ </func>
+
+
+ <func>
+ <name>exor(Data1, Data2) -> Result</name>
+ <fsummary>XOR data</fsummary>
+ <type>
+ <v>Data1, Data2 = iolist() | binary()</v>
+ <v>Result = binary()</v>
+ </type>
+ <desc>
+ <p>Performs bit-wise XOR (exclusive or) on the data supplied.</p>
+ </desc>
+ </func>
+ </funcs>
+
+ <section>
+ <title>DES in CBC mode</title>
+ <p>The Data Encryption Standard (DES) defines an algorithm for
+ encrypting and decrypting an 8 byte quantity using an 8 byte key
+ (actually only 56 bits of the key is used).
+ </p>
+ <p>When it comes to encrypting and decrypting blocks that are
+ multiples of 8 bytes various modes are defined (NIST SP
+ 800-38A). One of those modes is the Cipher Block Chaining (CBC)
+ mode, where the encryption of an 8 byte segment depend not only
+ of the contents of the segment itself, but also on the result of
+ encrypting the previous segment: the encryption of the previous
+ segment becomes the initializing vector of the encryption of the
+ current segment.
+ </p>
+ <p>Thus the encryption of every segment depends on the encryption
+ key (which is secret) and the encryption of the previous
+ segment, except the first segment which has to be provided with
+ an initial initializing vector. That vector could be chosen at
+ random, or be a counter of some kind. It does not have to be
+ secret.
+ </p>
+ <p>The following example is drawn from the old FIPS 81 standard
+ (replaced by NIST SP 800-38A), where both the plain text and the
+ resulting cipher text is settled. The following code fragment
+ returns `true'.
+ </p>
+ <pre><![CDATA[
+
+ Key = <<16#01,16#23,16#45,16#67,16#89,16#ab,16#cd,16#ef>>,
+ IVec = <<16#12,16#34,16#56,16#78,16#90,16#ab,16#cd,16#ef>>,
+ P = "Now is the time for all ",
+ C = crypto:des_cbc_encrypt(Key, IVec, P),
+ % Which is the same as
+ P1 = "Now is t", P2 = "he time ", P3 = "for all ",
+ C1 = crypto:des_cbc_encrypt(Key, IVec, P1),
+ C2 = crypto:des_cbc_encrypt(Key, C1, P2),
+ C3 = crypto:des_cbc_encrypt(Key, C2, P3),
+
+ C = <<C1/binary, C2/binary, C3/binary>>,
+ C = <<16#e5,16#c7,16#cd,16#de,16#87,16#2b,16#f2,16#7c,
+ 16#43,16#e9,16#34,16#00,16#8c,16#38,16#9c,16#0f,
+ 16#68,16#37,16#88,16#49,16#9a,16#7c,16#05,16#f6>>,
+ <<"Now is the time for all ">> ==
+ crypto:des_cbc_decrypt(Key, IVec, C).
+ ]]></pre>
+ <p>The following is true for the DES CBC mode. For all
+ decompositions <c>P1 ++ P2 = P</c> of a plain text message
+ <c>P</c> (where the length of all quantities are multiples of 8
+ bytes), the encryption <c>C</c> of <c>P</c> is equal to <c>C1 ++
+ C2</c>, where <c>C1</c> is obtained by encrypting <c>P1</c> with
+ <c>Key</c> and the initializing vector <c>IVec</c>, and where
+ <c>C2</c> is obtained by encrypting <c>P2</c> with <c>Key</c>
+ and the initializing vector <c>last8(C1)</c>,
+ where <c>last(Binary)</c> denotes the last 8 bytes of the
+ binary <c>Binary</c>.
+ </p>
+ <p>Similarly, for all decompositions <c>C1 ++ C2 = C</c> of a
+ cipher text message <c>C</c> (where the length of all quantities
+ are multiples of 8 bytes), the decryption <c>P</c> of <c>C</c>
+ is equal to <c>P1 ++ P2</c>, where <c>P1</c> is obtained by
+ decrypting <c>C1</c> with <c>Key</c> and the initializing vector
+ <c>IVec</c>, and where <c>P2</c> is obtained by decrypting
+ <c>C2</c> with <c>Key</c> and the initializing vector
+ <c>last8(C1)</c>, where <c>last8(Binary)</c> is as above.
+ </p>
+ <p>For DES3 (which uses three 64 bit keys) the situation is the
+ same.
+ </p>
+ </section>
+</erlref>
+
diff --git a/lib/crypto/doc/src/crypto_app.xml b/lib/crypto/doc/src/crypto_app.xml
new file mode 100644
index 0000000000..bf1d1ae1f7
--- /dev/null
+++ b/lib/crypto/doc/src/crypto_app.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE appref SYSTEM "appref.dtd">
+
+<appref>
+ <header>
+ <copyright>
+ <year>1999</year>
+ <year>2007</year>
+ <holder>Ericsson AB, All Rights Reserved</holder>
+ </copyright>
+ <legalnotice>
+ The contents of this file are subject to the Erlang Public License,
+ Version 1.1, (the "License"); you may not use this file except in
+ compliance with the License. You should have received a copy of the
+ Erlang Public License along with this software. If not, it can be
+ retrieved online at http://www.erlang.org/.
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and limitations
+ under the License.
+
+ The Initial Developer of the Original Code is Ericsson AB.
+ </legalnotice>
+
+ <title>crypto</title>
+ <prepared>Peter H&ouml;gfeldt</prepared>
+ <responsible>Peter H&ouml;gfeldt</responsible>
+ <docno></docno>
+ <approved>Peter H&ouml;gfeldt</approved>
+ <checked>Peter H&ouml;gfeldt</checked>
+ <date>2003-06-01</date>
+ <rev>B</rev>
+ <file>crypto_app.sgml</file>
+ </header>
+ <app>crypto</app>
+ <appsummary>The Crypto Application</appsummary>
+ <description>
+ <p>The purpose of the Crypto application is to provide message
+ digest and DES encryption for SMNPv3. It provides computation of
+ message digests MD5 and SHA, and CBC-DES encryption and
+ decryption.</p>
+ <p></p>
+ </description>
+
+ <section>
+ <title>Configuration</title>
+ <p>The following environment configuration parameters are defined
+ for the Crypto application. Refer to application(3) for more
+ information about configuration parameters.
+ </p>
+ <taglist>
+ <tag><c><![CDATA[debug = true | false <optional>]]></c></tag>
+ <item>
+ <p>Causes debug information to be written to standard
+ error or standard output. Default is <c>false</c>.
+ </p>
+ </item>
+ </taglist>
+ </section>
+
+ <section>
+ <title>OpenSSL libraries</title>
+ <p>The current implementation of the Erlang Crypto application is
+ based on the <em>OpenSSL</em> package version 0.9.7 or higher.
+ There are source and binary releases on the web.
+ </p>
+ <p>Source releases of OpenSSL can be downloaded from the <url href="http://www.openssl.org">OpenSSL</url> project home page,
+ or mirror sites listed there.
+ </p>
+ <p>The same URL also contains links to some compiled binaries and
+ libraries of OpenSSL (see the <c>Related/Binaries</c> menu) of
+ which the <url href="http://www.shininglightpro.com/search.php?searchname=Win32+OpenSSL">Shining Light Productions Win32 and OpenSSL</url> pages are of
+ interest for the Win32 user.
+ </p>
+ <p>For some Unix flavours there are binary packages available
+ on the net.
+ </p>
+ <p>If you cannot find a suitable binary OpenSSL package, you
+ have to fetch an OpenSSL source release and compile it.
+ </p>
+ <p>You then have to compile and install the library
+ <c>libcrypto.so</c> (Unix), or the library <c>libeay32.dll</c>
+ (Win32).
+ </p>
+ <p>For Unix The <c>crypto_drv</c> dynamic driver is delivered linked
+ to OpenSSL libraries in <c>/usr/local/lib</c>, but the default
+ dynamic linking will also accept libraries in <c>/lib</c> and
+ <c>/usr/lib</c>.
+ </p>
+ <p>If that is not applicable to the particular Unix operating
+ system used, the example <c>Makefile</c> in the Crypto
+ <c>priv/obj</c> directory, should be used as a basis for
+ relinking the final version of the port program.
+ </p>
+ <p>For <c>Win32</c> it is only required that the library can be
+ found from the <c>PATH</c> environment variable, or that they
+ reside in the appropriate <c>SYSTEM32</c> directory; hence no
+ particular relinking is need. Hence no example <c>Makefile</c>
+ for Win32 is provided.</p>
+ </section>
+
+ <section>
+ <title>SEE ALSO</title>
+ <p>application(3)</p>
+ </section>
+</appref>
+
diff --git a/lib/crypto/doc/src/fascicules.xml b/lib/crypto/doc/src/fascicules.xml
new file mode 100644
index 0000000000..8fc250bc75
--- /dev/null
+++ b/lib/crypto/doc/src/fascicules.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE fascicules SYSTEM "fascicules.dtd">
+
+<fascicules>
+ <fascicule file="usersguide" href="usersguide_frame.html" entry="no">
+ User's Guide
+ </fascicule>
+ <fascicule file="ref_man" href="ref_man_frame.html" entry="yes">
+ Reference Manual
+ </fascicule>
+ <fascicule file="release_notes" href="release_notes_frame.html" entry="no">
+ Release Notes
+ </fascicule>
+ <fascicule file="" href="../../../../doc/print.html" entry="no">
+ Off-Print
+ </fascicule>
+</fascicules>
+
diff --git a/lib/crypto/doc/src/insidecover.xml b/lib/crypto/doc/src/insidecover.xml
new file mode 100644
index 0000000000..e7407b8052
--- /dev/null
+++ b/lib/crypto/doc/src/insidecover.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE bookinsidecover SYSTEM "bookinsidecover.dtd">
+
+<bookinsidecover>
+
+ The Erlang/OTP SSL application includes software developed by the
+ OpenSSL Project for use in the OpenSSL Toolkit
+ (http://www.openssl.org/). Copyright (c) 1998-2002 The OpenSSL
+ Project. All rights reserved.
+
+ <br/>
+ This product includes cryptographic software written by Eric Young
+ ([email protected]). This product includes software written by Tim
+ Hudson ([email protected]). Copyright (C) 1995-1998 Eric Young
+ ([email protected]). All rights reserved.
+
+ <br/>
+ For further OpenSSL and SSLeay license information se the chapter
+ <bold>Licenses</bold>.
+
+ <vfill/>
+ <br/>
+ <tt>http://www.erlang.org</tt>
+ <br/>
+</bookinsidecover>
+
diff --git a/lib/crypto/doc/src/licenses.xml b/lib/crypto/doc/src/licenses.xml
new file mode 100644
index 0000000000..bae87a373e
--- /dev/null
+++ b/lib/crypto/doc/src/licenses.xml
@@ -0,0 +1,155 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>2003</year><year>2009</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ The contents of this file are subject to the Erlang Public License,
+ Version 1.1, (the "License"); you may not use this file except in
+ compliance with the License. You should have received a copy of the
+ Erlang Public License along with this software. If not, it can be
+ retrieved online at http://www.erlang.org/.
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and limitations
+ under the License.
+
+ </legalnotice>
+
+ <title>Licenses</title>
+ <prepared>Peter H&ouml;gfeldt</prepared>
+ <docno></docno>
+ <date>2003-05-26</date>
+ <rev>A</rev>
+ <file>licenses.xml</file>
+ </header>
+ <p> <marker id="licenses"></marker>
+This chapter contains in extenso versions
+ of the OpenSSL and SSLeay licenses.
+ </p>
+
+ <section>
+ <title>OpenSSL License</title>
+ <code type="none">
+/* ====================================================================
+ * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * ([email protected]). This product includes software written by Tim
+ * Hudson ([email protected]).
+ *
+ */ </code>
+ </section>
+
+ <section>
+ <title>SSLeay License</title>
+ <code type="none">
+/* Copyright (C) 1995-1998 Eric Young ([email protected])
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young ([email protected]).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson ([email protected]).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young ([email protected])"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson ([email protected])"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */ </code>
+ </section>
+</chapter>
+
diff --git a/lib/crypto/doc/src/make.dep b/lib/crypto/doc/src/make.dep
new file mode 100644
index 0000000000..73b090bbb6
--- /dev/null
+++ b/lib/crypto/doc/src/make.dep
@@ -0,0 +1,20 @@
+# ----------------------------------------------------
+# >>>> Do not edit this file <<<<
+# This file was automaticly generated by
+# /home/otp/bin/docdepend
+# ----------------------------------------------------
+
+
+# ----------------------------------------------------
+# TeX files that the DVI file depend on
+# ----------------------------------------------------
+
+book.dvi: book.tex crypto.tex crypto_app.tex licenses.tex \
+ ref_man.tex usersguide.tex
+
+# ----------------------------------------------------
+# Source inlined when transforming from source to LaTeX
+# ----------------------------------------------------
+
+book.tex: ref_man.xml
+
diff --git a/lib/crypto/doc/src/note.gif b/lib/crypto/doc/src/note.gif
new file mode 100644
index 0000000000..6fffe30419
--- /dev/null
+++ b/lib/crypto/doc/src/note.gif
Binary files differ
diff --git a/lib/crypto/doc/src/notes.xml b/lib/crypto/doc/src/notes.xml
new file mode 100644
index 0000000000..bbdd2d873b
--- /dev/null
+++ b/lib/crypto/doc/src/notes.xml
@@ -0,0 +1,469 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>1999</year><year>2009</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ The contents of this file are subject to the Erlang Public License,
+ Version 1.1, (the "License"); you may not use this file except in
+ compliance with the License. You should have received a copy of the
+ Erlang Public License along with this software. If not, it can be
+ retrieved online at http://www.erlang.org/.
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and limitations
+ under the License.
+
+ </legalnotice>
+
+ <title>Crypto Release Notes</title>
+ <prepared>Peter H&ouml;gfeldt</prepared>
+ <docno></docno>
+ <date>2003-06-06</date>
+ <rev>B</rev>
+ <file>notes.xml</file>
+ </header>
+ <p>This document describes the changes made to the Crypto application.</p>
+
+<section><title>Crypto 1.6.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Suppressed false valgrind errors caused by libcrypto
+ using uninitialized data as entropy.</p>
+ <p>
+ Own Id: OTP-8200</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The documentation is now built with open source tools
+ (xsltproc and fop) that exists on most platforms. One
+ visible change is that the frames are removed.</p>
+ <p>
+ Own Id: OTP-8201</p>
+ </item>
+ <item>
+ <p>
+ When the crypto application failed to load the
+ OpenSSL/LibEAY shared object, error indication was
+ sparse. Now a more specific error message is sent to the
+ error logger.</p>
+ <p>
+ Own Id: OTP-8281</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Crypto 1.6.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed emulator crash caused by crypto using an old
+ openssl version that did not cope with large file
+ descriptors.</p>
+ <p>
+ Own Id: OTP-8261 Aux Id: seq11434 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Crypto 1.6.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ <c>Makefile.in</c> has been updated to use the LDFLAGS
+ environment variable (if set). (Thanks to Davide
+ Pesavento.)</p>
+ <p>
+ Own Id: OTP-8157</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Support for Blowfish cfb64 added to <c>crypto</c>.</p>
+ <p>
+ Own Id: OTP-8096</p>
+ </item>
+ <item>
+ <p>
+ New function <c>crypto:aes_cbc_ivec</c></p>
+ <p>
+ Own Id: OTP-8141</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Crypto 1.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The <c>dh_compute_key</c> sometimes returned a
+ SharedSecret of incorrect size.</p>
+ <p>
+ Own Id: OTP-7674</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Optimization for drivers by creating small binaries
+ direct on process heap.</p>
+ <p>
+ Own Id: OTP-7762</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Crypto 1.5.3</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Added new functions: dss_verify/3, rsa_verify/3,
+ rsa_verify/4, dss_sign/2, rsa_sign/2, rsa_sign/3,
+ rsa_public_encrypt, rsa_private_decrypt/3,
+ rsa_private_encrypt/3, rsa_public_decrypt/3,
+ dh_generate_key/1, dh_generate_key/2, dh_compute_key/3.</p>
+ <p>
+ Own Id: OTP-7545</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Crypto 1.5.2.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Minor performance optimization.</p>
+ <p>
+ Own Id: OTP-7521</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Crypto 1.5.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ ./configure has been improved to find 64-bit OpenSSL
+ libraries.</p>
+ <p>
+ Own Id: OTP-7270</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ crypto and zlib drivers improved to allow concurent smp
+ access.</p>
+ <p>
+ Own Id: OTP-7262</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+ <section>
+ <title>Crypto 1.5.1.1</title>
+
+ <section>
+ <title>Improvements and New Features</title>
+ <list type="bulleted">
+ <item>
+ <p>The linked in driver for the crypto application is now
+ linked statically against the OpenSSL libraries, to avoid
+ installation and runtime problems in connection to the
+ OpenSSL library locations.</p>
+ <p>Own Id: OTP-6680</p>
+ </item>
+ <item>
+ <p>Minor Makefile changes.</p>
+ <p>Own Id: OTP-6689</p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
+ <title>Crypto 1.5</title>
+
+ <section>
+ <title>Improvements and New Features</title>
+ <list type="bulleted">
+ <item>
+ <p>It is now explicitly checked at start-up that the crypto
+ driver is properly loaded (Thanks to Claes Wikstrom).</p>
+ <p>Own Id: OTP-6109</p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
+ <title>Crypto 1.4</title>
+
+ <section>
+ <title>Improvements and New Features</title>
+ <list type="bulleted">
+ <item>
+ <p>The previously undocumented and UNSUPPORTED <c>ssh</c>
+ application has been updated and documented. This release
+ of the <c>ssh</c> application is still considered to be a
+ beta release and (if necessary) there could still be
+ changes in its API before it reaches 1.0.</p>
+ <p>Also, more cryptographic algorithms have been added to
+ the <c>crypto</c> application.</p>
+ <p>*** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>Own Id: OTP-5631</p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
+ <title>Crypto 1.3</title>
+
+ <section>
+ <title>Improvements and New Features</title>
+ <list type="bulleted">
+ <item>
+ <p>Added support for RFC 3826 - The Advanced Encryption Standard
+ (AES) Cipher Algorithm in the SNMP User-based Security Model.
+ <br></br>
+Martin Bj&ouml;rklund</p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
+ <title>Crypto 1.2.3</title>
+
+ <section>
+ <title>Fixed Bugs and Malfunctions</title>
+ <list type="bulleted">
+ <item>
+ <p>Linked in drivers in the crypto, and asn1 applications
+ are now compiled with the -D_THREAD_SAFE and -D_REENTRANT
+ switches on unix when the emulator has thread support
+ enabled.</p>
+ <p>Linked in drivers on MacOSX are not compiled with the
+ undocumented -lbundle1.o switch anymore. Thanks to Sean
+ Hinde who sent us a patch.</p>
+ <p>Linked in driver in crypto, and port programs in ssl, now
+ compiles on OSF1.</p>
+ <p>Minor makefile improvements in runtime_tools.</p>
+ <p>Own Id: OTP-5346</p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
+ <title>Crypto 1.2.2</title>
+
+ <section>
+ <title>Improvements and New Features</title>
+ <list type="bulleted">
+ <item>
+ <p>Corrected error handling. If the port to the driver that
+ crypto uses is unexpectedly closed (which should not
+ happen during normal operation of crypto), crypto will
+ terminate immediately (rather than crashing the next time
+ crypto is used). Also corrected build problems on Mac OS
+ X.</p>
+ <p>Own Id: OTP-5279</p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
+ <title>Crypto 1.2.1</title>
+
+ <section>
+ <title>Fixed Bugs and Malfunctions</title>
+ <list type="bulleted">
+ <item>
+ <p>It was not possible in R9 to relink the crypto driver.
+ The object file was missing as well as an example
+ makefile. The crypto driver object file is now released
+ with the application (installed in priv/obj). An example
+ makefile has also been added to the priv/obj directory.
+ The makefile serves as an example of how to relink the
+ driver on Unix (crypto_drv.so) or Windows
+ (crypto_drv.dll).</p>
+ <p>Own Id: OTP-4828 Aux Id: seq8193 </p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
+ <title>Crypto 1.2</title>
+
+ <section>
+ <title>Improvements and New Features</title>
+ <list type="bulleted">
+ <item>
+ <p>Previous versions of Crypto where delivered with
+ statically linked binaries based on SSLeay. That is not
+ longer the case. The current version of Crypto requires
+ dynamically linked OpenSSL libraries that the user has to
+ install. The library needed is <c>libcrypto.so</c> (Unix)
+ or <c>libeay32.[lib|dll]</c> (Win32). For further details
+ see the crypto(6) application manual page.</p>
+ </item>
+ <item>
+ <p>This version of Crypto uses the new DES interface of
+ OpenSSL 0.9.7, which is not backward compatible with
+ earlier versions of OpenSSL.
+ </p>
+ </item>
+ <item>The functions <c>des_ede3_cbc_encrypt/5</c> and
+ <c>des_ede3_cbc_decrypt/5</c> have been renamed to
+ <c>des3_cbc_encrypt/5</c> and <c>des3_cbc_decrypt/5</c>,
+ respectively. The old functions have been retained (they are
+ deprecated and not listed in the crypto(3) manual page).</item>
+ </list>
+ </section>
+
+ <section>
+ <title>Reported Fixed Bugs and Malfunctions</title>
+ <list type="bulleted">
+ <item>
+ <p>The start of crypto failed on Windows, due to erroneous addition
+ of a DES3 algorithm.</p>
+ <p>Own Id: OTP-4684
+ <br></br>
+Aux Id: seq7864</p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
+ <title>Crypto 1.1.3</title>
+
+ <section>
+ <title>Reported Fixed Bugs and Malfunctions</title>
+ <list type="bulleted">
+ <item>To obtain backward compatibility with the old SSLeay
+ package, and with earlier versions of OpenSSL, the macro
+ OPENSSL_DES_LIBDES_COMPATIBILITY has been added to
+ <c>crypto_drv.c</c>. This is of importance only for the open
+ source version of Crypto.
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
+ <title>Crypto 1.1.2</title>
+
+ <section>
+ <title>Reported Fixed Bugs and Malfunctions</title>
+ <list type="bulleted">
+ <item>
+ <p>In the manual page <c>crypto(3)</c> the function names
+ <c>md5_finish</c> and <c>sha_finish</c> have been changed to
+ <c>md5_final</c> and <c>sha_final</c> to correctly document
+ the implementation.</p>
+ <p>Own Id: OTP-3409
+ </p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
+ <title>Crypto 1.1.1</title>
+ <p>Code replacement in runtime is supported. Upgrade can be done from
+ from version 1.1 and downgrade to version 1.1.
+ </p>
+
+ <section>
+ <title>Improvements and New Features</title>
+ <list type="bulleted">
+ <item>
+ <p>The driver part of the Crypto application has been
+ updated to use the erl_driver header file. Version 1.1.1
+ requires emulator version 4.9.1 or later.</p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
+ <title>Crypto 1.1</title>
+
+ <section>
+ <title>Reported Fixed Bugs and Malfunctions</title>
+ <list type="bulleted">
+ <item>
+ <p>On Windows the crypto_drv was incorrectly linked to
+ static run-time libraries instead of dynamic ones.</p>
+ <p>Own Id: OTP-3240
+ </p>
+ </item>
+ </list>
+ </section>
+ </section>
+
+ <section>
+ <title>Crypto 1.0</title>
+ <p>New application.
+ </p>
+ </section>
+</chapter>
+
diff --git a/lib/crypto/doc/src/ref_man.xml b/lib/crypto/doc/src/ref_man.xml
new file mode 100644
index 0000000000..f801221c81
--- /dev/null
+++ b/lib/crypto/doc/src/ref_man.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE application SYSTEM "application.dtd">
+
+<application xmlns:xi="http://www.w3.org/2001/XInclude">
+ <header>
+ <copyright>
+ <year>1999</year><year>2009</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ The contents of this file are subject to the Erlang Public License,
+ Version 1.1, (the "License"); you may not use this file except in
+ compliance with the License. You should have received a copy of the
+ Erlang Public License along with this software. If not, it can be
+ retrieved online at http://www.erlang.org/.
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and limitations
+ under the License.
+
+ </legalnotice>
+
+ <title>Crypto Reference Manual</title>
+ <prepared>Peter H&ouml;gfeldt</prepared>
+ <docno></docno>
+ <date>2003-06-01</date>
+ <rev>B</rev>
+ <file>refman.sgml</file>
+ </header>
+ <description>
+ <p>The Crypto Application provides functions for computation of
+ message digests, and encryption and decryption functions.
+ </p>
+ <p>This product includes software developed by the OpenSSL Project for
+ use in the OpenSSL Toolkit (http://www.openssl.org/).
+ </p>
+ <p>This product includes cryptographic software written by Eric Young
+ </p>
+ <p>This product includes software written by Tim Hudson
+ </p>
+ <p>For full OpenSSL and SSLeay license texts, see <seealso marker="licenses#licenses">Licenses</seealso>.</p>
+ </description>
+ <xi:include href="crypto_app.xml"/>
+ <xi:include href="crypto.xml"/>
+</application>
+
diff --git a/lib/crypto/doc/src/release_notes.xml b/lib/crypto/doc/src/release_notes.xml
new file mode 100644
index 0000000000..0c2ee23e22
--- /dev/null
+++ b/lib/crypto/doc/src/release_notes.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE part SYSTEM "part.dtd">
+
+<part>
+ <header>
+ <copyright>
+ <year>1999</year>
+ <year>2007</year>
+ <holder>Ericsson AB, All Rights Reserved</holder>
+ </copyright>
+ <legalnotice>
+ The contents of this file are subject to the Erlang Public License,
+ Version 1.1, (the "License"); you may not use this file except in
+ compliance with the License. You should have received a copy of the
+ Erlang Public License along with this software. If not, it can be
+ retrieved online at http://www.erlang.org/.
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and limitations
+ under the License.
+
+ The Initial Developer of the Original Code is Ericsson AB.
+ </legalnotice>
+
+ <title>Crypto Release Notes</title>
+ <prepared>Peter Hj&ouml;gfeldt</prepared>
+ <docno></docno>
+ <date>2003-06-01</date>
+ <rev>B</rev>
+ <file>release_notes.sgml</file>
+ </header>
+ <description>
+ <p>The Crypto Application provides functions for computation of
+ message digests, and encryption and decryption functions.
+ </p>
+ <p>This product includes software developed by the OpenSSL Project for
+ use in the OpenSSL Toolkit (http://www.openssl.org/).
+ </p>
+ <p>This product includes cryptographic software written by Eric Young
+ </p>
+ <p>This product includes software written by Tim Hudson
+ </p>
+ <p>For full OpenSSL and SSLeay license texts, see <seealso marker="licenses#licenses">Licenses</seealso>.</p>
+ </description>
+ <include file="notes"></include>
+</part>
+
diff --git a/lib/crypto/doc/src/usersguide.xml b/lib/crypto/doc/src/usersguide.xml
new file mode 100644
index 0000000000..dc5bf520a9
--- /dev/null
+++ b/lib/crypto/doc/src/usersguide.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE part SYSTEM "part.dtd">
+
+<part xmlns:xi="http://www.w3.org/2001/XInclude">
+ <header>
+ <copyright>
+ <year>2003</year><year>2009</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ The contents of this file are subject to the Erlang Public License,
+ Version 1.1, (the "License"); you may not use this file except in
+ compliance with the License. You should have received a copy of the
+ Erlang Public License along with this software. If not, it can be
+ retrieved online at http://www.erlang.org/.
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and limitations
+ under the License.
+
+ </legalnotice>
+
+ <title>Crypto User's Guide</title>
+ <prepared>OTP Team</prepared>
+ <docno></docno>
+ <date>2003-06-01</date>
+ <rev>C</rev>
+ <file>usersguide.sgml</file>
+ </header>
+ <description>
+ <p>The <em>Crypto</em> application provides functions for
+ computation of message digests, and functions for encryption and
+ decryption.
+ </p>
+ <p>This product includes software developed by the OpenSSL Project
+ for use in the OpenSSL Toolkit (http://www.openssl.org/).
+ </p>
+ <p>This product includes cryptographic software written by Eric
+ </p>
+ <p>This product includes software written by Tim Hudson
+ </p>
+ <p>For full OpenSSL and SSLeay license texts, see <seealso marker="licenses#licenses">Licenses</seealso>.
+ </p>
+ </description>
+ <xi:include href="licenses.xml"/>
+</part>
+
diff --git a/lib/crypto/doc/src/warning.gif b/lib/crypto/doc/src/warning.gif
new file mode 100644
index 0000000000..96af52360e
--- /dev/null
+++ b/lib/crypto/doc/src/warning.gif
Binary files differ
diff --git a/lib/crypto/ebin/.gitignore b/lib/crypto/ebin/.gitignore
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/lib/crypto/ebin/.gitignore
diff --git a/lib/crypto/info b/lib/crypto/info
new file mode 100644
index 0000000000..bb73f019b1
--- /dev/null
+++ b/lib/crypto/info
@@ -0,0 +1,2 @@
+group: comm
+short: Cryptographical support
diff --git a/lib/crypto/priv/Makefile b/lib/crypto/priv/Makefile
new file mode 100644
index 0000000000..b8acdacc00
--- /dev/null
+++ b/lib/crypto/priv/Makefile
@@ -0,0 +1,78 @@
+# ``The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved via the world wide web at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# The Initial Developer of the Original Code is Ericsson Utvecklings AB.
+# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
+# AB. All Rights Reserved.''
+#
+# $Id$
+#
+
+# ----------------------------------------------------
+# THIS MAKEFILE SERVES AS AN EXAMPLE OF
+# HOW TO RELINK THE CRYPTO DRIVER
+# ----------------------------------------------------
+
+# ----------------------------------------------------
+# Variables for linking a .so driver on unix.
+# Note: These may differ between systems.
+# ----------------------------------------------------
+
+SO_LD = gcc
+SO_LDFLAGS = -G
+SO_SSL_LIBDIR = /usr/local/lib
+SO_DRIVER = $(LIBDIR)/$(DRIVER_NAME).so
+
+# ----------------------------------------------------
+# Variables for linking a win32 .dll driver.
+# Note: These may differ between systems.
+# ----------------------------------------------------
+
+DLL_LD = link.exe
+DLL_LDFLAGS = -release -nologo -incremental:no -dll
+DLL_LIBDIR = "c:\\OpenSSL\\lib\\VC"
+DLL_LIBS = libeay32.lib MSVCRT.LIB kernel32.lib \
+ advapi32.lib gdi32.lib user32.lib \
+ comctl32.lib comdlg32.lib shell32.lib
+DLL_DRIVER = $(LIBDIR)/$(DRIVER_NAME).dll
+DLL_EXP = $(LIBDIR)/$(DRIVER_NAME).exp
+DLL_LIB = $(LIBDIR)/$(DRIVER_NAME).lib
+
+# ----------------------------------------------------
+# Common variables
+# ----------------------------------------------------
+
+OBJDIR = ./
+LIBDIR = ../lib
+DRIVER_NAME = crypto_drv
+OBJS = $(OBJDIR)/crypto_drv.o
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+
+$(SO_DRIVER): $(OBJS)
+ $(SO_LD) $(SO_LDFLAGS) -L$(SO_SSL_LIBDIR) -Wl,-R$(SO_SSL_LIBDIR) \
+ -o $@ $^ -lcrypto
+
+$(DLL_DRIVER): $(OBJS)
+ $(DLL_LD) $(DLL_LDFLAGS) -out:$@ -libpath:$(DLL_LIBDIR) $(OBJS) \
+ $(DLL_LIBS)
+
+so: $(SO_DRIVER)
+
+dll: $(DLL_DRIVER)
+
+clean:
+ rm -f $(SO_DRIVER) $(DLL_DRIVER)
+ rm -f $(DLL_EXP) $(DLL_LIB)
+ rm -f core *~
+
diff --git a/lib/crypto/src/Makefile b/lib/crypto/src/Makefile
new file mode 100644
index 0000000000..51092d16a5
--- /dev/null
+++ b/lib/crypto/src/Makefile
@@ -0,0 +1,99 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 1999-2009. All Rights Reserved.
+#
+# The contents of this file are subject to the Erlang Public License,
+# Version 1.1, (the "License"); you may not use this file except in
+# compliance with the License. You should have received a copy of the
+# Erlang Public License along with this software. If not, it can be
+# retrieved online at http://www.erlang.org/.
+#
+# Software distributed under the License is distributed on an "AS IS"
+# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+# the License for the specific language governing rights and limitations
+# under the License.
+#
+# %CopyrightEnd%
+#
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+# ----------------------------------------------------
+# Application version
+# ----------------------------------------------------
+include ../vsn.mk
+VSN=$(CRYPTO_VSN)
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/lib/crypto-$(VSN)
+
+# ----------------------------------------------------
+# Common Macros
+# ----------------------------------------------------
+
+MODULES= \
+ crypto_app \
+ crypto \
+ crypto_server \
+ crypto_sup
+
+HRL_FILES=
+
+ERL_FILES= $(MODULES:%=%.erl)
+
+TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
+
+APP_FILE= crypto.app
+APPUP_FILE= crypto.appup
+
+APP_SRC= $(APP_FILE).src
+APP_TARGET= $(EBIN)/$(APP_FILE)
+APPUP_SRC= $(APPUP_FILE).src
+APPUP_TARGET= $(EBIN)/$(APPUP_FILE)
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+ERL_COMPILE_FLAGS += +warn_obsolete_guard
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+
+debug opt valgrind: $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
+
+clean:
+ rm -f $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET)
+ rm -f errs core *~
+
+$(APP_TARGET): $(APP_SRC) ../vsn.mk
+ sed -e 's;%VSN%;$(VSN);' $< > $@
+
+$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
+ sed -e 's;%VSN%;$(VSN);' $< > $@
+
+docs:
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+release_spec: opt
+ $(INSTALL_DIR) $(RELSYSDIR)/src
+ $(INSTALL_DATA) $(ERL_FILES) $(RELSYSDIR)/src
+ $(INSTALL_DIR) $(RELSYSDIR)/ebin
+ $(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) \
+ $(APPUP_TARGET) $(RELSYSDIR)/ebin
+
+release_docs_spec:
+
+
+
+
+
+
+
diff --git a/lib/crypto/src/crypto.app.src b/lib/crypto/src/crypto.app.src
new file mode 100644
index 0000000000..a24760a781
--- /dev/null
+++ b/lib/crypto/src/crypto.app.src
@@ -0,0 +1,31 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+{application, crypto,
+ [{description, "CRYPTO version 1"},
+ {vsn, "%VSN%"},
+ {modules, [crypto,
+ crypto_app,
+ crypto_sup,
+ crypto_server]},
+ {registered, [crypto_sup, crypto_server]},
+ {applications, [kernel, stdlib]},
+ {env, []},
+ {mod, {crypto_app, []}}]}.
+
+
diff --git a/lib/crypto/src/crypto.appup.src b/lib/crypto/src/crypto.appup.src
new file mode 100644
index 0000000000..b39ef734eb
--- /dev/null
+++ b/lib/crypto/src/crypto.appup.src
@@ -0,0 +1,22 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+{"%VSN%",
+ [],
+ []
+}.
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
new file mode 100644
index 0000000000..5189677dd0
--- /dev/null
+++ b/lib/crypto/src/crypto.erl
@@ -0,0 +1,665 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%% Purpose : Main Crypto API module.
+
+-module(crypto).
+
+-export([start/0, stop/0, info/0, info_lib/0]).
+-export([md4/1, md4_init/0, md4_update/2, md4_final/1]).
+-export([md5/1, md5_init/0, md5_update/2, md5_final/1]).
+-export([sha/1, sha_init/0, sha_update/2, sha_final/1]).
+%-export([sha256/1, sha256_init/0, sha256_update/2, sha256_final/1]).
+%-export([sha512/1, sha512_init/0, sha512_update/2, sha512_final/1]).
+-export([md5_mac/2, md5_mac_96/2, sha_mac/2, sha_mac_96/2]).
+-export([des_cbc_encrypt/3, des_cbc_decrypt/3, des_cbc_ivec/1]).
+-export([des3_cbc_encrypt/5, des3_cbc_decrypt/5]).
+-export([blowfish_cfb64_encrypt/3,blowfish_cfb64_decrypt/3]).
+-export([des_ede3_cbc_encrypt/5, des_ede3_cbc_decrypt/5]).
+-export([aes_cfb_128_encrypt/3, aes_cfb_128_decrypt/3]).
+-export([exor/2]).
+-export([rc4_encrypt/2, rc4_set_key/1, rc4_encrypt_with_state/2]).
+-export([rc2_40_cbc_encrypt/3, rc2_40_cbc_decrypt/3]).
+-export([dss_verify/3, rsa_verify/3, rsa_verify/4]).
+-export([dss_sign/2, rsa_sign/2, rsa_sign/3]).
+-export([rsa_public_encrypt/3, rsa_private_decrypt/3]).
+-export([rsa_private_encrypt/3, rsa_public_decrypt/3]).
+-export([dh_generate_key/1, dh_generate_key/2, dh_compute_key/3]).
+-export([rand_bytes/1, rand_bytes/3, rand_uniform/2]).
+-export([mod_exp/3, mpint/1, erlint/1]).
+%% -export([idea_cbc_encrypt/3, idea_cbc_decrypt/3]).
+-export([aes_cbc_128_encrypt/3, aes_cbc_128_decrypt/3]).
+-export([aes_cbc_256_encrypt/3, aes_cbc_256_decrypt/3]).
+-export([aes_cbc_ivec/1]).
+
+-export([dh_generate_parameters/2, dh_check/1]). %% Testing see below
+
+-define(INFO, 0).
+-define(MD5, 1).
+-define(MD5_INIT, 2).
+-define(MD5_UPDATE, 3).
+-define(MD5_FINAL, 4).
+-define(SHA, 5).
+-define(SHA_INIT, 6).
+-define(SHA_UPDATE, 7).
+-define(SHA_FINAL, 8).
+-define(MD5_MAC, 9).
+-define(MD5_MAC_96, 10).
+-define(SHA_MAC, 11).
+-define(SHA_MAC_96, 12).
+-define(DES_CBC_ENCRYPT, 13).
+-define(DES_CBC_DECRYPT, 14).
+-define(DES_EDE3_CBC_ENCRYPT, 15).
+-define(DES_EDE3_CBC_DECRYPT, 16).
+-define(AES_CFB_128_ENCRYPT, 17).
+-define(AES_CFB_128_DECRYPT, 18).
+-define(RAND_BYTES, 19).
+-define(RAND_UNIFORM, 20).
+-define(MOD_EXP, 21).
+-define(DSS_VERIFY, 22).
+-define(RSA_VERIFY_SHA, 23).
+%-define(RSA_VERIFY_MD5, 35).
+-define(AES_CBC_128_ENCRYPT, 24).
+-define(AES_CBC_128_DECRYPT, 25).
+-define(XOR, 26).
+-define(RC4_ENCRYPT, 27).
+-define(RC4_SET_KEY, 28).
+-define(RC4_ENCRYPT_WITH_STATE, 29).
+-define(RC2_40_CBC_ENCRYPT, 30).
+-define(RC2_40_CBC_DECRYPT, 31).
+-define(AES_CBC_256_ENCRYPT, 32).
+-define(AES_CBC_256_DECRYPT, 33).
+-define(INFO_LIB,34).
+%-define(RSA_VERIFY_SHA, 23).
+-define(RSA_VERIFY_MD5, 35).
+-define(RSA_SIGN_SHA, 36).
+-define(RSA_SIGN_MD5, 37).
+-define(DSS_SIGN, 38).
+-define(RSA_PUBLIC_ENCRYPT, 39).
+-define(RSA_PRIVATE_DECRYPT, 40).
+-define(RSA_PRIVATE_ENCRYPT, 41).
+-define(RSA_PUBLIC_DECRYPT, 42).
+-define(DH_GENERATE_PARAMS, 43).
+-define(DH_CHECK, 44).
+-define(DH_GENERATE_KEY, 45).
+-define(DH_COMPUTE_KEY, 46).
+-define(MD4, 47).
+-define(MD4_INIT, 48).
+-define(MD4_UPDATE, 49).
+-define(MD4_FINAL, 50).
+
+%% -define(SHA256, 51).
+%% -define(SHA256_INIT, 52).
+%% -define(SHA256_UPDATE, 53).
+%% -define(SHA256_FINAL, 54).
+%% -define(SHA512, 55).
+%% -define(SHA512_INIT, 56).
+%% -define(SHA512_UPDATE, 57).
+%% -define(SHA512_FINAL, 58).
+
+-define(BF_CFB64_ENCRYPT, 59).
+-define(BF_CFB64_DECRYPT, 60).
+
+%% -define(IDEA_CBC_ENCRYPT, 34).
+%% -define(IDEA_CBC_DECRYPT, 35).
+
+-define(FUNC_LIST, [md4, md4_init, md4_update, md4_final,
+ md5, md5_init, md5_update, md5_final,
+ sha, sha_init, sha_update, sha_final,
+%% sha256, sha256_init, sha256_update, sha256_final,
+%% sha512, sha512_init, sha512_update, sha512_final,
+ md5_mac, md5_mac_96,
+ sha_mac, sha_mac_96,
+ des_cbc_encrypt, des_cbc_decrypt,
+ des_ede3_cbc_encrypt, des_ede3_cbc_decrypt,
+ aes_cfb_128_encrypt, aes_cfb_128_decrypt,
+ rand_bytes,
+ rand_uniform,
+ mod_exp,
+ dss_verify,dss_sign,
+ rsa_verify,rsa_sign,
+ rsa_public_encrypt,rsa_private_decrypt,
+ rsa_private_encrypt,rsa_public_decrypt,
+ dh_generate_key, dh_compute_key,
+ aes_cbc_128_encrypt, aes_cbc_128_decrypt,
+ exor,
+ rc4_encrypt, rc4_set_key, rc4_encrypt_with_state,
+ rc2_40_cbc_encrypt, rc2_40_cbc_decrypt,
+ %% idea_cbc_encrypt, idea_cbc_decrypt,
+ aes_cbc_256_encrypt, aes_cbc_256_decrypt,
+ info_lib]).
+
+start() ->
+ application:start(crypto).
+
+stop() ->
+ application:stop(crypto).
+
+info() ->
+ lists:map(fun(I) ->
+ lists:nth(I, ?FUNC_LIST)
+ end, binary_to_list(control(?INFO, []))).
+
+info_lib() ->
+ <<_DrvVer:8, NameSize:8, Name:NameSize/binary,
+ VerNum:32, VerStr/binary>> = control(?INFO_LIB,[]),
+ [{Name,VerNum,VerStr}].
+
+%% Below Key and Data are binaries or IO-lists. IVec is a binary.
+%% Output is always a binary. Context is a binary.
+
+%%
+%% MESSAGE DIGESTS
+%%
+
+%%
+%% MD5
+%%
+md5(Data) ->
+ control(?MD5, Data).
+
+md5_init() ->
+ control(?MD5_INIT, []).
+
+md5_update(Context, Data) ->
+ control(?MD5_UPDATE, [Context, Data]).
+
+md5_final(Context) ->
+ control(?MD5_FINAL, Context).
+
+%%
+%% MD4
+%%
+md4(Data) ->
+ control(?MD4, Data).
+
+md4_init() ->
+ control(?MD4_INIT, []).
+
+md4_update(Context, Data) ->
+ control(?MD4_UPDATE, [Context, Data]).
+
+md4_final(Context) ->
+ control(?MD4_FINAL, Context).
+
+%%
+%% SHA
+%%
+sha(Data) ->
+ control(?SHA, Data).
+
+sha_init() ->
+ control(?SHA_INIT, []).
+
+sha_update(Context, Data) ->
+ control(?SHA_UPDATE, [Context, Data]).
+
+sha_final(Context) ->
+ control(?SHA_FINAL, Context).
+
+%% sha256 and sha512 requires openssl-0.9.8 removed for now
+
+%% sha256(Data) ->
+%% control(?SHA256, Data).
+
+%% sha256_init() ->
+%% control(?SHA256_INIT, []).
+
+%% sha256_update(Context, Data) ->
+%% control(?SHA256_UPDATE, [Context, Data]).
+
+%% sha256_final(Context) ->
+%% control(?SHA256_FINAL, Context).
+
+%% sha512(Data) ->
+%% control(?SHA512, Data).
+
+%% sha512_init() ->
+%% control(?SHA512_INIT, []).
+
+%% sha512_update(Context, Data) ->
+%% control(?SHA512_UPDATE, [Context, Data]).
+
+%% sha512_final(Context) ->
+%% control(?SHA512_FINAL, Context).
+
+%%
+%% MESSAGE AUTHENTICATION CODES
+%%
+
+%%
+%% MD5_MAC
+%%
+md5_mac(Key, Data) ->
+ control_bin(?MD5_MAC, Key, Data).
+
+md5_mac_96(Key, Data) ->
+ control_bin(?MD5_MAC_96, Key, Data).
+
+%%
+%% SHA_MAC
+%%
+sha_mac(Key, Data) ->
+ control_bin(?SHA_MAC, Key, Data).
+
+sha_mac_96(Key, Data) ->
+ control_bin(?SHA_MAC_96, Key, Data).
+
+%%
+%% CRYPTO FUNCTIONS
+%%
+
+%%
+%% DES - in cipher block chaining mode (CBC)
+%%
+des_cbc_encrypt(Key, IVec, Data) ->
+ control(?DES_CBC_ENCRYPT, [Key, IVec, Data]).
+
+des_cbc_decrypt(Key, IVec, Data) ->
+ control(?DES_CBC_DECRYPT, [Key, IVec, Data]).
+
+%%
+%% dec_cbc_ivec(Data) -> binary()
+%%
+%% Returns the IVec to be used in the next iteration of
+%% des_cbc_[encrypt|decrypt].
+%%
+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)).
+
+%%
+%% DES3 - in cipher block chaining mode (CBC)
+%%
+des3_cbc_encrypt(Key1, Key2, Key3, IVec, Data) ->
+ des_ede3_cbc_encrypt(Key1, Key2, Key3, IVec, Data).
+des_ede3_cbc_encrypt(Key1, Key2, Key3, IVec, Data) ->
+ %%io:format("des_ede3_cbc_encrypt: size(Data)=~p\n", [size(list_to_binary([Data]))]),
+ control(?DES_EDE3_CBC_ENCRYPT, [Key1, Key2, Key3, IVec, Data]).
+
+des3_cbc_decrypt(Key1, Key2, Key3, IVec, Data) ->
+ des_ede3_cbc_decrypt(Key1, Key2, Key3, IVec, Data).
+des_ede3_cbc_decrypt(Key1, Key2, Key3, IVec, Data) ->
+ control(?DES_EDE3_CBC_DECRYPT, [Key1, Key2, Key3, IVec, Data]).
+
+%%
+%% Blowfish
+%%
+blowfish_cfb64_encrypt(Key, IVec, Data) when byte_size(IVec) =:= 8 ->
+ control_bin(?BF_CFB64_ENCRYPT, Key, list_to_binary([IVec, Data])).
+
+blowfish_cfb64_decrypt(Key, IVec, Data) when byte_size(IVec) =:= 8 ->
+ control_bin(?BF_CFB64_DECRYPT, Key, list_to_binary([IVec, Data])).
+
+%%
+%% AES in cipher feedback mode (CFB)
+%%
+aes_cfb_128_encrypt(Key, IVec, Data) ->
+ control(?AES_CFB_128_ENCRYPT, [Key, IVec, Data]).
+
+aes_cfb_128_decrypt(Key, IVec, Data) ->
+ control(?AES_CFB_128_DECRYPT, [Key, IVec, Data]).
+
+
+%% %%
+%% %% IDEA - in cipher block chaining mode (CBC)
+%% %%
+%% idea_cbc_encrypt(Key, IVec, Data) ->
+%% control(?IDEA_CBC_ENCRYPT, [Key, IVec, Data]).
+
+%% idea_cbc_decrypt(Key, IVec, Data) ->
+%% control(?IDEA_CBC_DECRYPT, [Key, IVec, Data]).
+
+
+%%
+%% RAND - pseudo random numbers using RN_ functions in crypto lib
+%%
+
+rand_bytes(Bytes) ->
+ rand_bytes(Bytes, 0, 0).
+rand_bytes(Bytes, Topmask, Bottommask) ->
+ control(?RAND_BYTES,[<<Bytes:32/integer,
+ Topmask:8/integer,
+ Bottommask:8/integer>>]).
+
+rand_uniform(From,To) when is_binary(From), is_binary(To) ->
+ case control(?RAND_UNIFORM,[From,To]) of
+ <<Len:32/integer, MSB, Rest/binary>> when MSB > 127 ->
+ <<(Len + 1):32/integer, 0, MSB, Rest/binary>>;
+ Whatever ->
+ Whatever
+ end;
+rand_uniform(From,To) when is_integer(From),is_integer(To) ->
+ BinFrom = mpint(From),
+ BinTo = mpint(To),
+ case rand_uniform(BinFrom, BinTo) of
+ Result when is_binary(Result) ->
+ erlint(Result);
+ Other ->
+ Other
+ end.
+
+%%
+%% mod_exp - utility for rsa generation
+%%
+mod_exp(Base, Exponent, Modulo)
+ when is_integer(Base), is_integer(Exponent), is_integer(Modulo) ->
+ erlint(mod_exp(mpint(Base), mpint(Exponent), mpint(Modulo)));
+
+mod_exp(Base, Exponent, Modulo) ->
+ case control(?MOD_EXP,[Base,Exponent,Modulo]) of
+ <<Len:32/integer, MSB, Rest/binary>> when MSB > 127 ->
+ <<(Len + 1):32/integer, 0, MSB, Rest/binary>>;
+ Whatever ->
+ Whatever
+ end.
+
+%%
+%% DSS, RSA - verify
+%%
+
+%% Key = [P,Q,G,Y] P,Q,G=DSSParams Y=PublicKey
+dss_verify(Data,Signature,Key) ->
+ control(?DSS_VERIFY, [Data,Signature,Key]) == <<1>>.
+
+% Key = [E,N] E=PublicExponent N=PublicModulus
+rsa_verify(Data,Signature,Key) ->
+ rsa_verify(sha, Data,Signature,Key).
+rsa_verify(Type,Data,Signature,Key) ->
+ control(rsa_verify_digest_type(Type), [Data,Signature,Key]) == <<1>>.
+
+rsa_verify_digest_type(md5) -> ?RSA_VERIFY_MD5;
+rsa_verify_digest_type(sha) -> ?RSA_VERIFY_SHA;
+rsa_verify_digest_type(Bad) -> erlang:error(badarg, [Bad]).
+
+%%
+%% DSS, RSA - sign
+%%
+%% Key = [P,Q,G,X] P,Q,G=DSSParams X=PrivateKey
+dss_sign(Data, Key) ->
+ <<Ret:8, Signature/binary>> = control(?DSS_SIGN, [Data,Key]),
+ case Ret of
+ 1 -> Signature;
+ 0 -> erlang:error(badkey, [Data, Key])
+ end.
+
+%% Key = [E,N,D] E=PublicExponent N=PublicModulus D=PrivateExponent
+rsa_sign(Data,Key) ->
+ rsa_sign(sha, Data, Key).
+rsa_sign(Type, Data, Key) ->
+ <<Ret:8, Signature/binary>> = control(rsa_sign_digest_type(Type), [Data,Key]),
+ case Ret of
+ 1 -> Signature;
+ 0 -> erlang:error(badkey, [Type,Data,Key])
+ end.
+
+rsa_sign_digest_type(md5) -> ?RSA_SIGN_MD5;
+rsa_sign_digest_type(sha) -> ?RSA_SIGN_SHA;
+rsa_sign_digest_type(Bad) -> erlang:error(badarg, [Bad]).
+
+%%
+%% rsa_public_encrypt
+%% rsa_private_decrypt
+
+%% Binary, Key = [E,N]
+rsa_public_encrypt(BinMesg, Key, Padding) ->
+ Size = iolist_size(BinMesg),
+ <<Ret:8, Signature/binary>> =
+ control(?RSA_PUBLIC_ENCRYPT, [<<Size:32>>,BinMesg,Key,rsa_pad(Padding)]),
+ case Ret of
+ 1 -> Signature;
+ 0 -> erlang:error(encrypt_failed, [BinMesg,Key, Padding])
+ end.
+
+%% Binary, Key = [E,N,D]
+rsa_private_decrypt(BinMesg, Key, Padding) ->
+ Size = iolist_size(BinMesg),
+ <<Ret:8, Signature/binary>> =
+ control(?RSA_PRIVATE_DECRYPT, [<<Size:32>>,BinMesg,Key,rsa_pad(Padding)]),
+ case Ret of
+ 1 -> Signature;
+ 0 -> erlang:error(decrypt_failed, [BinMesg,Key, Padding])
+ end.
+
+rsa_pad(rsa_pkcs1_padding) -> 1;
+rsa_pad(rsa_pkcs1_oaep_padding) -> 2;
+%% rsa_pad(rsa_sslv23_padding) -> 3;
+rsa_pad(rsa_no_padding) -> 0;
+rsa_pad(Bad) -> erlang:error(badarg, [Bad]).
+
+%% Binary, Key = [E,N,D]
+rsa_private_encrypt(BinMesg, Key, Padding) ->
+ Size = iolist_size(BinMesg),
+ <<Ret:8, Signature/binary>> =
+ control(?RSA_PRIVATE_ENCRYPT, [<<Size:32>>,BinMesg,Key,rsa_pad(Padding)]),
+ case Ret of
+ 1 -> Signature;
+ 0 -> erlang:error(encrypt_failed, [BinMesg,Key, Padding])
+ end.
+
+%% Binary, Key = [E,N]
+rsa_public_decrypt(BinMesg, Key, Padding) ->
+ Size = iolist_size(BinMesg),
+ <<Ret:8, Signature/binary>> =
+ control(?RSA_PUBLIC_DECRYPT, [<<Size:32>>,BinMesg,Key,rsa_pad(Padding)]),
+ case Ret of
+ 1 -> Signature;
+ 0 -> erlang:error(decrypt_failed, [BinMesg,Key, Padding])
+ end.
+
+%%
+%% AES - with 128 or 256 bit key in cipher block chaining mode (CBC)
+%%
+
+aes_cbc_128_encrypt(Key, IVec, Data) ->
+ control(?AES_CBC_128_ENCRYPT, [Key, IVec, Data]).
+
+aes_cbc_128_decrypt(Key, IVec, Data) ->
+ control(?AES_CBC_128_DECRYPT, [Key, IVec, Data]).
+
+aes_cbc_256_encrypt(Key, IVec, Data) ->
+ control(?AES_CBC_256_ENCRYPT, [Key, IVec, Data]).
+
+aes_cbc_256_decrypt(Key, IVec, Data) ->
+ control(?AES_CBC_256_DECRYPT, [Key, IVec, Data]).
+
+%%
+%% aes_cbc_ivec(Data) -> binary()
+%%
+%% Returns the IVec to be used in the next iteration of
+%% 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)).
+
+
+%%
+%% XOR - xor to iolists and return a binary
+%% NB doesn't check that they are the same size, just concatenates
+%% them and sends them to the driver
+%%
+exor(A, B) ->
+ control(?XOR, [A, B]).
+
+%%
+%% RC4 - symmetric stream cipher
+%%
+rc4_encrypt(Key, Data) ->
+ control_bin(?RC4_ENCRYPT, Key, Data).
+
+rc4_set_key(Key) ->
+ control(?RC4_SET_KEY, Key).
+
+rc4_encrypt_with_state(State, Data) ->
+ <<Sz:32/integer-big-unsigned, S:Sz/binary, D/binary>> =
+ control_bin(?RC4_ENCRYPT_WITH_STATE, State, Data),
+ {S, D}.
+
+%%
+%% RC2 - 40 bits block cipher
+%%
+rc2_40_cbc_encrypt(Key, IVec, Data) ->
+ control(?RC2_40_CBC_ENCRYPT, [Key, IVec, Data]).
+
+rc2_40_cbc_decrypt(Key, IVec, Data) ->
+ control(?RC2_40_CBC_DECRYPT, [Key, IVec, Data]).
+
+%%
+%% DH Diffie-Hellman functions
+%%
+
+%% Generate (and check) Parameters is not documented because they are implemented
+%% for testing (and offline parameter generation) only.
+%% From the openssl doc:
+%% DH_generate_parameters() may run for several hours before finding a suitable prime.
+%% Thus dh_generate_parameters may in this implementation block
+%% the emulator for several hours.
+%%
+%% usage: dh_generate_parameters(1024, 2 or 5) ->
+%% [Prime=mpint(), SharedGenerator=mpint()]
+dh_generate_parameters(PrimeLen, Generator)
+ when is_integer(PrimeLen), is_integer(Generator) ->
+ case control(?DH_GENERATE_PARAMS, <<PrimeLen:32, Generator:32>>) of
+ <<0:8, _/binary>> ->
+ erlang:error(generation_failed, [PrimeLen,Generator]);
+ <<1:8, PLen0:32, _:PLen0/binary, GLen0:32,_:GLen0/binary>> = Bin ->
+ PLen = PLen0+4,
+ GLen = GLen0+4,
+ <<_:8, PBin:PLen/binary,GBin:GLen/binary>> = Bin,
+ [PBin, GBin]
+ end.
+
+%% Checks that the DHParameters are ok.
+%% DHParameters = [P (Prime)= mpint(), G(Generator) = mpint()]
+dh_check(DHParameters) ->
+ case control(?DH_CHECK, DHParameters) of
+ <<0:32>> -> ok;
+ <<_:24,_:1,_:1,_:1,1:1>> -> not_prime;
+ <<_:24,_:1,_:1,1:1,0:1>> -> not_strong_prime;
+ <<_:24,_:1,1:1,0:1,0:1>> -> unable_to_check_generator;
+ <<_:24,1:1,0:1,0:1,0:1>> -> not_suitable_generator;
+ <<16#FFFF:32>> -> {error, check_failed};
+ <<X:32>> -> {unknown, X}
+ end.
+
+%% DHParameters = [P (Prime)= mpint(), G(Generator) = mpint()]
+%% PrivKey = mpint()
+dh_generate_key(DHParameters) ->
+ dh_generate_key(<<0:32>>, DHParameters).
+dh_generate_key(PrivateKey, DHParameters) ->
+ case control(?DH_GENERATE_KEY, [PrivateKey, DHParameters]) of
+ <<0:8, _/binary>> ->
+ erlang:error(generation_failed, [PrivateKey,DHParameters]);
+ Bin = <<1:8, PubLen0:32, _:PubLen0/binary, PrivLen0:32, _:PrivLen0/binary>> ->
+ PubLen = PubLen0+4,
+ PrivLen = PrivLen0+4,
+ <<_:8, PubBin:PubLen/binary,PrivBin:PrivLen/binary>> = Bin,
+ {PubBin, PrivBin}
+ end.
+
+%% DHParameters = [P (Prime)= mpint(), G(Generator) = mpint()]
+%% MyPrivKey, OthersPublicKey = mpint()
+dh_compute_key(OthersPublicKey, MyPrivateKey, DHParameters) ->
+ case control(?DH_COMPUTE_KEY, [OthersPublicKey, MyPrivateKey, DHParameters]) of
+ <<0:8, _/binary>> ->
+ erlang:error(computation_failed, [OthersPublicKey,MyPrivateKey,DHParameters]);
+ <<1:8, Binary/binary>> -> Binary
+ end.
+
+%%
+%% LOCAL FUNCTIONS
+%%
+control_bin(Cmd, Key, Data) ->
+ Sz = iolist_size(Key),
+ control(Cmd, [<<Sz:32/integer-unsigned>>, Key, Data]).
+
+control(Cmd, Data) ->
+ Port = crypto_server:client_port(),
+ erlang:port_control(Port, Cmd, Data).
+
+
+%% sizehdr(N) ->
+%% [(N bsr 24) band 255,
+%% (N bsr 16) band 255,
+%% (N bsr 8) band 255,
+%% N band 255].
+
+%% Flat length of IOlist (or binary)
+%% flen(L) when binary(L) ->
+%% size(L);
+%% flen(L) ->
+%% flen(L, 0).
+
+%% flen([H| T], N) when list(H) ->
+%% flen(H, flen(T, N));
+%% flen([H| T], N) when binary(H) ->
+%% flen(T, N + size(H));
+%% flen([H| T], N) when integer(H), 0 =< H, H =< 255 ->
+%% flen(T, N + 1);
+%% flen([], N) ->
+%% N.
+
+%% large integer in a binary with 32bit length
+%% MP representaion (SSH2)
+mpint(X) when X < 0 ->
+ case X of
+ -1 ->
+ <<0,0,0,1,16#ff>>;
+ _ ->
+ mpint_neg(X,0,[])
+ end;
+mpint(X) ->
+ case X of
+ 0 ->
+ <<0,0,0,0>>;
+ _ ->
+ mpint_pos(X,0,[])
+ end.
+
+-define(UINT32(X), X:32/unsigned-big-integer).
+
+mpint_neg(-1,I,Ds=[MSB|_]) ->
+ if MSB band 16#80 =/= 16#80 ->
+ <<?UINT32((I+1)), (list_to_binary([255|Ds]))/binary>>;
+ true ->
+ (<<?UINT32(I), (list_to_binary(Ds))/binary>>)
+ end;
+mpint_neg(X,I,Ds) ->
+ mpint_neg(X bsr 8,I+1,[(X band 255)|Ds]).
+
+mpint_pos(0,I,Ds=[MSB|_]) ->
+ if MSB band 16#80 == 16#80 ->
+ <<?UINT32((I+1)), (list_to_binary([0|Ds]))/binary>>;
+ true ->
+ (<<?UINT32(I), (list_to_binary(Ds))/binary>>)
+ end;
+mpint_pos(X,I,Ds) ->
+ mpint_pos(X bsr 8,I+1,[(X band 255)|Ds]).
+
+%% int from integer in a binary with 32bit length
+erlint(<<MPIntSize:32/integer,MPIntValue/binary>>) ->
+ Bits= MPIntSize * 8,
+ <<Integer:Bits/integer>> = MPIntValue,
+ Integer.
diff --git a/lib/crypto/src/crypto_app.erl b/lib/crypto/src/crypto_app.erl
new file mode 100644
index 0000000000..f1ea1406e4
--- /dev/null
+++ b/lib/crypto/src/crypto_app.erl
@@ -0,0 +1,39 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%% Purpose : Application master for CRYPTO.
+
+-module(crypto_app).
+
+-behaviour(application).
+
+-export([start/2, stop/1]).
+
+%% start/2(Type, StartArgs) -> {ok, Pid} | {ok, Pid, State} |
+%% {error, Reason}
+%%
+start(_Type, _StartArgs) ->
+ crypto_sup:start_link().
+
+%% stop(State) -> void()
+%%
+stop(_State) ->
+ ok.
+
+
diff --git a/lib/crypto/src/crypto_server.erl b/lib/crypto/src/crypto_server.erl
new file mode 100644
index 0000000000..0b1e5c9b02
--- /dev/null
+++ b/lib/crypto/src/crypto_server.erl
@@ -0,0 +1,138 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%% Purpose: Provide cryptographic algorithms.
+
+-module(crypto_server).
+
+-behaviour(gen_server).
+
+-export([start_link/0,client_port/0]).
+
+%% Internal exports, call-back functions.
+-export([init/1,handle_call/3,handle_cast/2,handle_info/2,code_change/3,
+ terminate/2]).
+
+%% Measurements shows that inlining port_names/0 is worth doing.
+-compile({inline,[{port_names,0}]}).
+
+%%% --------------------------------------------------------
+%%% Interface Functions.
+%%% --------------------------------------------------------
+
+start_link() ->
+ gen_server:start_link({local, crypto_server}, crypto_server, [], []).
+
+init([]) ->
+ process_flag(trap_exit, true),
+ erl_ddll:start(),
+ PrivDir = code:priv_dir(crypto),
+ LibDir1 = filename:join([PrivDir, "lib"]),
+ {Status, LibDir} =
+ case erl_ddll:load_driver(LibDir1, crypto_drv) of
+ ok -> {ok,LibDir1};
+ {error,Error1} ->
+ LibDir2 =
+ filename:join(LibDir1,
+ erlang:system_info(system_architecture)),
+ Candidate =
+ filelib:wildcard(filename:join([LibDir2,"crypto_drv*"])),
+ case Candidate of
+ [] ->
+ {{error,Error1},LibDir1};
+ _ ->
+ case erl_ddll:load_driver(LibDir2, crypto_drv) of
+ ok ->
+ {ok,LibDir2};
+ {error, Error2} ->
+ {{error,Error2},LibDir2}
+ end
+ end
+ end,
+ case Status of
+ ok ->
+ Cmd = "crypto_drv elibcrypto " ++
+ filename:join([LibDir, "elibcrypto"]),
+ open_ports(Cmd,size(port_names()));
+ {error, E} ->
+ Str = erl_ddll:format_error(E),
+ error_logger:error_msg("Unable to load crypto_drv. Failed with error:~n\"~s\"~nOpenSSL might not be installed on this system.~n",[Str]),
+ {stop,nodriver}
+ end.
+
+open_ports(_,0) ->
+ {ok, []};
+open_ports(Cmd,N) ->
+ Port = open_port({spawn, Cmd}, []),
+ %% check that driver is loaded, linked and working
+ %% since crypto_drv links towards libcrypto, this is a good thing
+ %% since libcrypto is known to be bad with backwards compatibility
+ case catch port_control(Port, 0, []) of
+ {'EXIT', _} ->
+ {stop, nodriver};
+ _ ->
+ register(element(N,port_names()), Port),
+ open_ports(Cmd,N-1)
+ end.
+
+port_names() ->
+ { crypto_drv01, crypto_drv02, crypto_drv03, crypto_drv04,
+ crypto_drv05, crypto_drv06, crypto_drv07, crypto_drv08,
+ crypto_drv09, crypto_drv10, crypto_drv11, crypto_drv12,
+ crypto_drv13, crypto_drv14, crypto_drv15, crypto_drv16 }.
+
+client_port() ->
+ element(erlang:system_info(scheduler_id) rem size(port_names()) + 1,
+ port_names()).
+
+
+%%% --------------------------------------------------------
+%%% The call-back functions.
+%%% --------------------------------------------------------
+
+handle_call(_, _, State) ->
+ {noreply, State}.
+
+handle_cast(_, State) ->
+ {noreply, State}.
+
+handle_info({'EXIT', Pid, _Reason}, State) when is_pid(Pid) ->
+ {noreply, State};
+
+handle_info({'EXIT', Port, Reason}, State) when is_port(Port) ->
+ {stop, {port_died, Reason}, State};
+handle_info(_, State) ->
+ {noreply, State}.
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+terminate(_Reason, _State) ->
+ close_ports(size(port_names())).
+
+close_ports(0) ->
+ ok;
+close_ports(N) ->
+ element(N,port_names()) ! {self(), close},
+ close_ports(N-1).
+
+
+
+
+
diff --git a/lib/crypto/src/crypto_sup.erl b/lib/crypto/src/crypto_sup.erl
new file mode 100644
index 0000000000..8ef58777ab
--- /dev/null
+++ b/lib/crypto/src/crypto_sup.erl
@@ -0,0 +1,39 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%% Purpose: Main supervisor in CRYPTO application.
+
+-module(crypto_sup).
+
+-behaviour(supervisor).
+
+-export([start_link/0, init/1]).
+
+start_link() ->
+ supervisor:start_link({local, crypto_sup}, crypto_sup, []).
+
+
+%% init([])
+%% Returns: {ok, {SupFlags, [ChildSpec]}}
+%%
+init([]) ->
+ Child = {crypto_server, {crypto_server, start_link, []},
+ permanent, 2000, worker, [crypto_server]},
+ {ok, {{one_for_all, 10, 3600}, [Child]}}.
+
diff --git a/lib/crypto/vsn.mk b/lib/crypto/vsn.mk
new file mode 100644
index 0000000000..f2a9b4fe24
--- /dev/null
+++ b/lib/crypto/vsn.mk
@@ -0,0 +1 @@
+CRYPTO_VSN = 1.6.3