aboutsummaryrefslogtreecommitdiffstats
path: root/lib/crypto/src
diff options
context:
space:
mode:
Diffstat (limited to 'lib/crypto/src')
-rw-r--r--lib/crypto/src/Makefile99
-rw-r--r--lib/crypto/src/crypto.app.src31
-rw-r--r--lib/crypto/src/crypto.appup.src22
-rw-r--r--lib/crypto/src/crypto.erl665
-rw-r--r--lib/crypto/src/crypto_app.erl39
-rw-r--r--lib/crypto/src/crypto_server.erl138
-rw-r--r--lib/crypto/src/crypto_sup.erl39
7 files changed, 1033 insertions, 0 deletions
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]}}.
+