diff options
Diffstat (limited to 'lib/crypto')
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ö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ö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> +[{<<"OpenSSL">>,9469983,<<"OpenSSL 0.9.8a 11 Oct 2005">>}] + </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ögfeldt</prepared> + <responsible>Peter Högfeldt</responsible> + <docno></docno> + <approved>Peter Högfeldt</approved> + <checked>Peter Hö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ö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 + * [email protected]. + * + * 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 Binary files differnew file mode 100644 index 0000000000..6fffe30419 --- /dev/null +++ b/lib/crypto/doc/src/note.gif 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ö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ö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ö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 + ([email protected]). + </p> + <p>This product includes software written by Tim Hudson + ([email protected]). + </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ö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 + ([email protected]). + </p> + <p>This product includes software written by Tim Hudson + ([email protected]). + </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 + Young ([email protected]). + </p> + <p>This product includes software written by Tim Hudson + ([email protected]). + </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 Binary files differnew file mode 100644 index 0000000000..96af52360e --- /dev/null +++ b/lib/crypto/doc/src/warning.gif 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 |