diff options
Diffstat (limited to 'lib/crypto/src')
-rw-r--r-- | lib/crypto/src/Makefile | 12 | ||||
-rw-r--r-- | lib/crypto/src/crypto.app.src | 12 | ||||
-rw-r--r-- | lib/crypto/src/crypto.erl | 628 | ||||
-rw-r--r-- | lib/crypto/src/crypto_server.erl | 88 |
4 files changed, 334 insertions, 406 deletions
diff --git a/lib/crypto/src/Makefile b/lib/crypto/src/Makefile index 51092d16a5..0e886ce8bf 100644 --- a/lib/crypto/src/Makefile +++ b/lib/crypto/src/Makefile @@ -1,19 +1,19 @@ # # %CopyrightBegin% -# -# Copyright Ericsson AB 1999-2009. All Rights Reserved. -# +# +# Copyright Ericsson AB 1999-2010. 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 @@ -57,7 +57,7 @@ APPUP_TARGET= $(EBIN)/$(APPUP_FILE) # ---------------------------------------------------- # FLAGS # ---------------------------------------------------- -ERL_COMPILE_FLAGS += +warn_obsolete_guard +ERL_COMPILE_FLAGS += +warn_obsolete_guard -DCRYPTO_VSN=\"$(VSN)\" # ---------------------------------------------------- # Targets diff --git a/lib/crypto/src/crypto.app.src b/lib/crypto/src/crypto.app.src index a24760a781..5548b6a1b5 100644 --- a/lib/crypto/src/crypto.app.src +++ b/lib/crypto/src/crypto.app.src @@ -1,23 +1,23 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1999-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 1999-2010. 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"}, + [{description, "CRYPTO version 2"}, {vsn, "%VSN%"}, {modules, [crypto, crypto_app, diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index fa33bad2e0..d6e2e033c0 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1999-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 1999-2010. 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% %% @@ -21,7 +21,7 @@ -module(crypto). --export([start/0, stop/0, info/0, info_lib/0]). +-export([start/0, stop/0, info/0, info_lib/0, version/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]). @@ -29,6 +29,7 @@ %-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([des_ecb_encrypt/2, des_ecb_decrypt/2]). -export([des3_cbc_encrypt/5, des3_cbc_decrypt/5]). -export([blowfish_ecb_encrypt/2, blowfish_ecb_decrypt/2]). -export([blowfish_cbc_encrypt/3, blowfish_cbc_decrypt/3]). @@ -39,8 +40,8 @@ -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([dss_verify/3, dss_verify/4, rsa_verify/3, rsa_verify/4]). +-export([dss_sign/2, dss_sign/3, 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]). @@ -50,82 +51,10 @@ -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([aes_ctr_encrypt/3, aes_ctr_decrypt/3]). -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(BF_ECB_ENCRYPT, 61). --define(BF_ECB_DECRYPT, 62). --define(BF_OFB64_ENCRYPT, 63). --define(BF_CBC_ENCRYPT, 64). --define(BF_CBC_DECRYPT, 65). - -%% -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, @@ -135,6 +64,7 @@ md5_mac, md5_mac_96, sha_mac, sha_mac_96, des_cbc_encrypt, des_cbc_decrypt, + des_ecb_encrypt, des_ecb_decrypt, des_ede3_cbc_encrypt, des_ede3_cbc_decrypt, aes_cfb_128_encrypt, aes_cfb_128_decrypt, rand_bytes, @@ -151,8 +81,70 @@ rc2_40_cbc_encrypt, rc2_40_cbc_decrypt, %% idea_cbc_encrypt, idea_cbc_decrypt, aes_cbc_256_encrypt, aes_cbc_256_decrypt, + aes_ctr_encrypt, aes_ctr_decrypt, info_lib]). +-type rsa_digest_type() :: 'md5' | 'sha'. +-type dss_digest_type() :: 'none' | 'sha'. +-type crypto_integer() :: binary() | integer(). + +-define(nif_stub,nif_stub_error(?LINE)). + +-on_load(on_load/0). + +-define(CRYPTO_NIF_VSN,101). + +on_load() -> + LibBaseName = "crypto", + PrivDir = code:priv_dir(crypto), + LibName = case erlang:system_info(build_type) of + opt -> + LibBaseName; + Type -> + LibTypeName = LibBaseName ++ "." ++ atom_to_list(Type), + case (filelib:wildcard( + filename:join( + [PrivDir, + "lib", + LibTypeName ++ "*"])) /= []) orelse + (filelib:wildcard( + filename:join( + [PrivDir, + "lib", + erlang:system_info(system_architecture), + LibTypeName ++ "*"])) /= []) of + true -> LibTypeName; + false -> LibBaseName + end + end, + Lib = filename:join([PrivDir, "lib", LibName]), + Status = case erlang:load_nif(Lib, ?CRYPTO_NIF_VSN) of + ok -> ok; + {error, {load_failed, _}}=Error1 -> + ArchLibDir = + filename:join([PrivDir, "lib", + erlang:system_info(system_architecture)]), + Candidate = + filelib:wildcard(filename:join([ArchLibDir,LibName ++ "*" ])), + case Candidate of + [] -> Error1; + _ -> + ArchLib = filename:join([ArchLibDir, LibName]), + erlang:load_nif(ArchLib, ?CRYPTO_NIF_VSN) + end; + Error1 -> Error1 + end, + case Status of + ok -> ok; + {error, {E, Str}} -> + error_logger:error_msg("Unable to load crypto library. Failed with error:~n\"~p, ~s\"~n" + "OpenSSL might not be installed on this system.~n",[E,Str]), + Status + end. + +nif_stub_error(Line) -> + erlang:nif_error({nif_not_loaded,module,?MODULE,line,Line}). + start() -> application:start(crypto). @@ -160,15 +152,15 @@ stop() -> application:stop(crypto). info() -> - lists:map(fun(I) -> - lists:nth(I, ?FUNC_LIST) - end, binary_to_list(control(?INFO, []))). + ?FUNC_LIST. -info_lib() -> - <<_DrvVer:8, NameSize:8, Name:NameSize/binary, - VerNum:32, VerStr/binary>> = control(?INFO_LIB,[]), - [{Name,VerNum,VerStr}]. +info_lib() -> ?nif_stub. +%% Crypto app version history: +%% (no version): Driver implementation +%% 2.0 : NIF implementation, requires OTP R14 +version() -> ?CRYPTO_VSN. + %% Below Key and Data are binaries or IO-lists. IVec is a binary. %% Output is always a binary. Context is a binary. @@ -179,73 +171,43 @@ info_lib() -> %% %% MD5 %% -md5(Data) -> - control(?MD5, Data). - -md5_init() -> - control(?MD5_INIT, []). -md5_update(Context, Data) -> - control(?MD5_UPDATE, [Context, Data]). +-spec md5(iodata()) -> binary(). +-spec md5_init() -> binary(). +-spec md5_update(binary(), iodata()) -> binary(). +-spec md5_final(binary()) -> binary(). -md5_final(Context) -> - control(?MD5_FINAL, Context). +md5(_Data) -> ?nif_stub. +md5_init() -> ?nif_stub. +md5_update(_Context, _Data) -> ?nif_stub. +md5_final(_Context) -> ?nif_stub. %% %% MD4 %% -md4(Data) -> - control(?MD4, Data). - -md4_init() -> - control(?MD4_INIT, []). - -md4_update(Context, Data) -> - control(?MD4_UPDATE, [Context, Data]). +-spec md4(iodata()) -> binary(). +-spec md4_init() -> binary(). +-spec md4_update(binary(), iodata()) -> binary(). +-spec md4_final(binary()) -> binary(). -md4_final(Context) -> - control(?MD4_FINAL, Context). +md4(_Data) -> ?nif_stub. +md4_init() -> ?nif_stub. +md4_update(_Context, _Data) -> ?nif_stub. +md4_final(_Context) -> ?nif_stub. %% %% 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 +-spec sha(iodata()) -> binary(). +-spec sha_init() -> binary(). +-spec sha_update(binary(), iodata()) -> binary(). +-spec sha_final(binary()) -> binary(). -%% sha256(Data) -> -%% control(?SHA256, Data). +sha(_Data) -> ?nif_stub. +sha_init() -> ?nif_stub. +sha_update(_Context, _Data) -> ?nif_stub. +sha_final(_Context) -> ?nif_stub. -%% 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 @@ -254,21 +216,31 @@ sha_final(Context) -> %% %% MD5_MAC %% +-spec md5_mac(iodata(), iodata()) -> binary(). +-spec md5_mac_96(iodata(), iodata()) -> binary(). + md5_mac(Key, Data) -> - control_bin(?MD5_MAC, Key, Data). + md5_mac_n(Key,Data,16). md5_mac_96(Key, Data) -> - control_bin(?MD5_MAC_96, Key, Data). + md5_mac_n(Key,Data,12). +md5_mac_n(_Key,_Data,_MacSz) -> ?nif_stub. + %% %% SHA_MAC %% +-spec sha_mac(iodata(), iodata()) -> binary(). +-spec sha_mac_96(iodata(), iodata()) -> binary(). + sha_mac(Key, Data) -> - control_bin(?SHA_MAC, Key, Data). + sha_mac_n(Key,Data,20). sha_mac_96(Key, Data) -> - control_bin(?SHA_MAC_96, Key, Data). + sha_mac_n(Key,Data,12). +sha_mac_n(_Key,_Data,_MacSz) -> ?nif_stub. + %% %% CRYPTO FUNCTIONS %% @@ -276,11 +248,16 @@ sha_mac_96(Key, Data) -> %% %% DES - in cipher block chaining mode (CBC) %% +-spec des_cbc_encrypt(iodata(), binary(), iodata()) -> binary(). +-spec des_cbc_decrypt(iodata(), binary(), iodata()) -> binary(). + des_cbc_encrypt(Key, IVec, Data) -> - control(?DES_CBC_ENCRYPT, [Key, IVec, Data]). + des_cbc_crypt(Key, IVec, Data, true). des_cbc_decrypt(Key, IVec, Data) -> - control(?DES_CBC_DECRYPT, [Key, IVec, Data]). + des_cbc_crypt(Key, IVec, Data, false). + +des_cbc_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub. %% %% dec_cbc_ivec(Data) -> binary() @@ -288,6 +265,8 @@ des_cbc_decrypt(Key, IVec, Data) -> %% Returns the IVec to be used in the next iteration of %% des_cbc_[encrypt|decrypt]. %% +-spec des_cbc_ivec(iodata()) -> binary(). + des_cbc_ivec(Data) when is_binary(Data) -> {_, IVec} = split_binary(Data, size(Data) - 8), IVec; @@ -295,76 +274,101 @@ des_cbc_ivec(Data) when is_list(Data) -> des_cbc_ivec(list_to_binary(Data)). %% +%% DES - in electronic codebook mode (ECB) +%% +-spec des_ecb_encrypt(iodata(), iodata()) -> binary(). +-spec des_ecb_decrypt(iodata(), iodata()) -> binary(). + +des_ecb_encrypt(Key, Data) -> + des_ecb_crypt(Key, Data, true). +des_ecb_decrypt(Key, Data) -> + des_ecb_crypt(Key, Data, false). +des_ecb_crypt(_Key, _Data, _IsEncrypt) -> ?nif_stub. + +%% %% DES3 - in cipher block chaining mode (CBC) %% +-spec des3_cbc_encrypt(iodata(), iodata(), iodata(), binary(), iodata()) -> + binary(). +-spec des3_cbc_decrypt(iodata(), iodata(), iodata(), binary(), iodata()) -> + binary(). + 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]). + des_ede3_cbc_crypt(Key1, Key2, Key3, IVec, Data, true). 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]). + des_ede3_cbc_crypt(Key1, Key2, Key3, IVec, Data, false). + +des_ede3_cbc_crypt(_Key1, _Key2, _Key3, _IVec, _Data, _IsEncrypt) -> ?nif_stub. %% %% Blowfish %% -blowfish_ecb_encrypt(Key, Data) when byte_size(Data) >= 8 -> - control_bin(?BF_ECB_ENCRYPT, Key, list_to_binary([Data])). +-spec blowfish_ecb_encrypt(iodata(), iodata()) -> binary(). +-spec blowfish_ecb_decrypt(iodata(), iodata()) -> binary(). +-spec blowfish_cbc_encrypt(iodata(), binary(), iodata()) -> binary(). +-spec blowfish_cbc_decrypt(iodata(), binary(), iodata()) -> binary(). +-spec blowfish_cfb64_encrypt(iodata(), binary(), iodata()) -> binary(). +-spec blowfish_cfb64_decrypt(iodata(), binary(), iodata()) -> binary(). +-spec blowfish_ofb64_encrypt(iodata(), binary(), iodata()) -> binary(). + +blowfish_ecb_encrypt(Key, Data) -> + bf_ecb_crypt(Key,Data, true). + +blowfish_ecb_decrypt(Key, Data) -> + bf_ecb_crypt(Key,Data, false). + +bf_ecb_crypt(_Key,_Data,_IsEncrypt) -> ?nif_stub. -blowfish_ecb_decrypt(Key, Data) when byte_size(Data) >= 8 -> - control_bin(?BF_ECB_DECRYPT, Key, list_to_binary([Data])). +blowfish_cbc_encrypt(Key, IVec, Data) -> + bf_cbc_crypt(Key,IVec,Data,true). -blowfish_cbc_encrypt(Key, IVec, Data) when byte_size(Data) rem 8 =:= 0 -> - control_bin(?BF_CBC_ENCRYPT, Key, list_to_binary([IVec, Data])). +blowfish_cbc_decrypt(Key, IVec, Data) -> + bf_cbc_crypt(Key,IVec,Data,false). -blowfish_cbc_decrypt(Key, IVec, Data) when byte_size(Data) rem 8 =:= 0 -> - control_bin(?BF_CBC_DECRYPT, Key, list_to_binary([IVec, Data])). +bf_cbc_crypt(_Key,_IVec,_Data,_IsEncrypt) -> ?nif_stub. -blowfish_cfb64_encrypt(Key, IVec, Data) when byte_size(IVec) =:= 8 -> - control_bin(?BF_CFB64_ENCRYPT, Key, list_to_binary([IVec, Data])). +blowfish_cfb64_encrypt(Key, IVec, Data) -> + bf_cfb64_crypt(Key, IVec, Data, true). -blowfish_cfb64_decrypt(Key, IVec, Data) when byte_size(IVec) =:= 8 -> - control_bin(?BF_CFB64_DECRYPT, Key, list_to_binary([IVec, Data])). +blowfish_cfb64_decrypt(Key, IVec, Data) -> + bf_cfb64_crypt(Key, IVec, Data, false). -blowfish_ofb64_encrypt(Key, IVec, Data) when byte_size(IVec) =:= 8 -> - control_bin(?BF_OFB64_ENCRYPT, Key, list_to_binary([IVec, Data])). +bf_cfb64_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub. + +blowfish_ofb64_encrypt(_Key, _IVec, _Data) -> ?nif_stub. %% %% AES in cipher feedback mode (CFB) %% +-spec aes_cfb_128_encrypt(iodata(), binary(), iodata()) -> binary(). +-spec aes_cfb_128_decrypt(iodata(), binary(), iodata()) -> binary(). + aes_cfb_128_encrypt(Key, IVec, Data) -> - control(?AES_CFB_128_ENCRYPT, [Key, IVec, Data]). + aes_cfb_128_crypt(Key, IVec, Data, true). 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]). + aes_cfb_128_crypt(Key, IVec, Data, false). -%% idea_cbc_decrypt(Key, IVec, Data) -> -%% control(?IDEA_CBC_DECRYPT, [Key, IVec, Data]). +aes_cfb_128_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub. %% %% RAND - pseudo random numbers using RN_ functions in crypto lib %% +-spec rand_bytes(non_neg_integer()) -> binary(). +-spec rand_uniform(crypto_integer(), crypto_integer()) -> + crypto_integer(). -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_bytes(_Bytes) -> ?nif_stub. +rand_bytes(_Bytes, _Topmask, _Bottommask) -> ?nif_stub. rand_uniform(From,To) when is_binary(From), is_binary(To) -> - case control(?RAND_UNIFORM,[From,To]) of + case rand_uniform_nif(From,To) of <<Len:32/integer, MSB, Rest/binary>> when MSB > 127 -> <<(Len + 1):32/integer, 0, MSB, Rest/binary>>; Whatever -> @@ -380,6 +384,8 @@ rand_uniform(From,To) when is_integer(From),is_integer(To) -> Other end. +rand_uniform_nif(_From,_To) -> ?nif_stub. + %% %% mod_exp - utility for rsa generation %% @@ -388,121 +394,142 @@ mod_exp(Base, Exponent, Modulo) erlint(mod_exp(mpint(Base), mpint(Exponent), mpint(Modulo))); mod_exp(Base, Exponent, Modulo) -> - case control(?MOD_EXP,[Base,Exponent,Modulo]) of + case mod_exp_nif(Base,Exponent,Modulo) of <<Len:32/integer, MSB, Rest/binary>> when MSB > 127 -> <<(Len + 1):32/integer, 0, MSB, Rest/binary>>; Whatever -> Whatever end. +mod_exp_nif(_Base,_Exp,_Mod) -> ?nif_stub. + %% %% DSS, RSA - verify %% +-spec dss_verify(binary(), binary(), [binary()]) -> boolean(). +-spec dss_verify(dss_digest_type(), binary(), binary(), [binary()]) -> boolean(). +-spec rsa_verify(binary(), binary(), [binary()]) -> boolean(). +-spec rsa_verify(rsa_digest_type(), binary(), binary(), [binary()]) -> + boolean(). %% Key = [P,Q,G,Y] P,Q,G=DSSParams Y=PublicKey dss_verify(Data,Signature,Key) -> - control(?DSS_VERIFY, [Data,Signature,Key]) == <<1>>. + dss_verify(sha, Data, Signature, Key). +dss_verify(_Type,_Data,_Signature,_Key) -> ?nif_stub. % 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(_Type,_Data,_Signature,_Key) -> ?nif_stub. -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]) +-spec dss_sign(binary(), [binary()]) -> binary(). +-spec dss_sign(dss_digest_type(), binary(), [binary()]) -> binary(). +-spec rsa_sign(binary(), [binary()]) -> binary(). +-spec rsa_sign(rsa_digest_type(), binary(), [binary()]) -> binary(). + +dss_sign(Data,Key) -> + dss_sign(sha,Data,Key). +dss_sign(Type, Data, Key) -> + case dss_sign_nif(Type,Data,Key) of + error -> erlang:error(badkey, [Data, Key]); + Sign -> Sign end. +dss_sign_nif(_Type,_Data,_Key) -> ?nif_stub. + %% 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]) + case rsa_sign_nif(Type,Data,Key) of + error -> erlang:error(badkey, [Type,Data,Key]); + Sign -> Sign 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_sign_nif(_Type,_Data,_Key) -> ?nif_stub. + %% %% rsa_public_encrypt %% rsa_private_decrypt +-type rsa_padding() :: 'rsa_pkcs1_padding' | 'rsa_pkcs1_oaep_padding' | 'rsa_no_padding'. + +-spec rsa_public_encrypt(binary(), [binary()], rsa_padding()) -> + binary(). +-spec rsa_public_decrypt(binary(), [binary()], rsa_padding()) -> + binary(). +-spec rsa_private_encrypt(binary(), [binary()], rsa_padding()) -> + binary(). +-spec rsa_private_decrypt(binary(), [binary()], rsa_padding()) -> + binary(). %% 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. + case rsa_public_crypt(BinMesg, Key, Padding, true) of + error -> + erlang:error(encrypt_failed, [BinMesg,Key, Padding]); + Sign -> Sign + end. + +rsa_public_crypt(_BinMsg, _Key, _Padding, _IsEncrypt) -> ?nif_stub. %% 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]). + case rsa_private_crypt(BinMesg, Key, Padding, false) of + error -> + erlang:error(decrypt_failed, [BinMesg,Key, Padding]); + Sign -> Sign + end. + +rsa_private_crypt(_BinMsg, _Key, _Padding, _IsEncrypt) -> ?nif_stub. + %% 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. + case rsa_private_crypt(BinMesg, Key, Padding, true) of + error -> + erlang:error(encrypt_failed, [BinMesg,Key, Padding]); + Sign -> Sign + 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]) + case rsa_public_crypt(BinMesg, Key, Padding, false) of + error -> + erlang:error(decrypt_failed, [BinMesg,Key, Padding]); + Sign -> Sign end. %% %% AES - with 128 or 256 bit key in cipher block chaining mode (CBC) %% +-spec aes_cbc_128_encrypt(iodata(), binary(), iodata()) -> + binary(). +-spec aes_cbc_128_decrypt(iodata(), binary(), iodata()) -> + binary(). +-spec aes_cbc_256_encrypt(iodata(), binary(), iodata()) -> + binary(). +-spec aes_cbc_256_decrypt(iodata(), binary(), iodata()) -> + binary(). aes_cbc_128_encrypt(Key, IVec, Data) -> - control(?AES_CBC_128_ENCRYPT, [Key, IVec, Data]). + aes_cbc_crypt(Key, IVec, Data, true). aes_cbc_128_decrypt(Key, IVec, Data) -> - control(?AES_CBC_128_DECRYPT, [Key, IVec, Data]). + aes_cbc_crypt(Key, IVec, Data, false). aes_cbc_256_encrypt(Key, IVec, Data) -> - control(?AES_CBC_256_ENCRYPT, [Key, IVec, Data]). + aes_cbc_crypt(Key, IVec, Data, true). aes_cbc_256_decrypt(Key, IVec, Data) -> - control(?AES_CBC_256_DECRYPT, [Key, IVec, Data]). + aes_cbc_crypt(Key, IVec, Data, false). + +aes_cbc_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub. %% %% aes_cbc_ivec(Data) -> binary() @@ -517,37 +544,45 @@ aes_cbc_ivec(Data) when is_binary(Data) -> aes_cbc_ivec(Data) when is_list(Data) -> aes_cbc_ivec(list_to_binary(Data)). +%% +%% AES - in counter mode (CTR) +%% +-spec aes_ctr_encrypt(iodata(), binary(), iodata()) -> + binary(). +-spec aes_ctr_decrypt(iodata(), binary(), iodata()) -> + binary(). + +aes_ctr_encrypt(_Key, _IVec, _Data) -> ?nif_stub. +aes_ctr_decrypt(_Key, _IVec, _Cipher) -> ?nif_stub. %% %% 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]). +-spec exor(iodata(), iodata()) -> binary(). + +exor(_A, _B) -> ?nif_stub. %% %% RC4 - symmetric stream cipher %% -rc4_encrypt(Key, Data) -> - control_bin(?RC4_ENCRYPT, Key, Data). +-spec rc4_encrypt(iodata(), iodata()) -> binary(). -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}. +rc4_encrypt(_Key, _Data) -> ?nif_stub. +rc4_set_key(_Key) -> ?nif_stub. +rc4_encrypt_with_state(_State, _Data) -> ?nif_stub. %% %% RC2 - 40 bits block cipher %% rc2_40_cbc_encrypt(Key, IVec, Data) -> - control(?RC2_40_CBC_ENCRYPT, [Key, IVec, Data]). + rc2_40_cbc_crypt(Key,IVec,Data,true). rc2_40_cbc_decrypt(Key, IVec, Data) -> - control(?RC2_40_CBC_DECRYPT, [Key, IVec, Data]). + rc2_40_cbc_crypt(Key,IVec,Data,false). + +rc2_40_cbc_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub. %% %% DH Diffie-Hellman functions @@ -562,87 +597,50 @@ rc2_40_cbc_decrypt(Key, IVec, Data) -> %% %% 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. +dh_generate_parameters(PrimeLen, Generator) -> + case dh_generate_parameters_nif(PrimeLen, Generator) of + error -> erlang:error(generation_failed, [PrimeLen,Generator]); + Ret -> Ret + end. + +dh_generate_parameters_nif(_PrimeLen, _Generator) -> ?nif_stub. %% 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. +dh_check([_Prime,_Gen]) -> ?nif_stub. %% DHParameters = [P (Prime)= mpint(), G(Generator) = mpint()] %% PrivKey = mpint() +-spec dh_generate_key([binary()]) -> {binary(),binary()}. +-spec dh_generate_key(binary()|undefined, [binary()]) -> + {binary(),binary()}. + dh_generate_key(DHParameters) -> - dh_generate_key(<<0:32>>, DHParameters). + dh_generate_key(undefined, 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} + case dh_generate_key_nif(PrivateKey, DHParameters) of + error -> erlang:error(generation_failed, [PrivateKey,DHParameters]); + Res -> Res end. +dh_generate_key_nif(_PrivateKey, _DHParameters) -> ?nif_stub. + %% DHParameters = [P (Prime)= mpint(), G(Generator) = mpint()] %% MyPrivKey, OthersPublicKey = mpint() +-spec dh_compute_key(binary(), binary(), [binary()]) -> binary(). + 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 + case dh_compute_key_nif(OthersPublicKey,MyPrivateKey,DHParameters) of + error -> erlang:error(computation_failed, [OthersPublicKey,MyPrivateKey,DHParameters]); + Ret -> Ret end. +dh_compute_key_nif(_OthersPublicKey, _MyPrivateKey, _DHParameters) -> ?nif_stub. + %% %% 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) diff --git a/lib/crypto/src/crypto_server.erl b/lib/crypto/src/crypto_server.erl index 0b1e5c9b02..89650a9f06 100644 --- a/lib/crypto/src/crypto_server.erl +++ b/lib/crypto/src/crypto_server.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1999-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 1999-2010. 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% %% @@ -23,14 +23,12 @@ -behaviour(gen_server). --export([start_link/0,client_port/0]). +-export([start_link/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. @@ -40,66 +38,8 @@ 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()). + {ok,[]}. + %%% -------------------------------------------------------- @@ -112,11 +52,6 @@ handle_call(_, _, 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}. @@ -124,13 +59,8 @@ 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). |