1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 1999-2020. All Rights Reserved. 5%% 6%% Licensed under the Apache License, Version 2.0 (the "License"); 7%% you may not use this file except in compliance with the License. 8%% You may obtain a copy of the License at 9%% 10%% http://www.apache.org/licenses/LICENSE-2.0 11%% 12%% Unless required by applicable law or agreed to in writing, software 13%% distributed under the License is distributed on an "AS IS" BASIS, 14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15%% See the License for the specific language governing permissions and 16%% limitations under the License. 17%% 18%% %CopyrightEnd% 19%% 20 21%% Purpose : Main Crypto API module. 22 23-module(crypto). 24 25-export([start/0, stop/0, info/0, info_lib/0, info_fips/0, supports/0, enable_fips_mode/1, 26 version/0, bytes_to_integer/1]). 27-export([cipher_info/1, hash_info/1]). 28-export([hash/2, hash_init/1, hash_update/2, hash_final/1]). 29-export([sign/4, sign/5, verify/5, verify/6]). 30-export([generate_key/2, generate_key/3, compute_key/4]). 31-export([exor/2, strong_rand_bytes/1, mod_pow/3]). 32-export([rand_seed/0, rand_seed_alg/1, rand_seed_alg/2]). 33-export([rand_seed_s/0, rand_seed_alg_s/1, rand_seed_alg_s/2]). 34-export([rand_plugin_next/1]). 35-export([rand_plugin_aes_next/1, rand_plugin_aes_jump/1]). 36-export([rand_plugin_uniform/1]). 37-export([rand_plugin_uniform/2]). 38-export([rand_cache_plugin_next/1]). 39-export([rand_uniform/2]). 40-export([public_encrypt/4, private_decrypt/4]). 41-export([private_encrypt/4, public_decrypt/4]). 42-export([privkey_to_pubkey/2]). 43-export([ec_curve/1, ec_curves/0]). 44-export([rand_seed/1]). 45 46%%%---------------------------------------------------------------- 47%% Removed functions. 48%% 49%% Old interface. Now implemented with the New interface. 50%% Removed in OTP-24.0 See OTP-16232 (deprecation) and OTP-16656 (removal) 51 52-removed([{next_iv, '_', "see the 'New and Old API' chapter of the CRYPTO User's guide"}, 53 {hmac, 3, "use crypto:mac/4 instead"}, 54 {hmac, 4, "use crypto:macN/5 instead"}, 55 {hmac_init, 2, "use crypto:mac_init/3 instead"}, 56 {hmac_update, 2, "use crypto:mac_update/2 instead"}, 57 {hmac_final, 1, "use crypto:mac_final/1 instead"}, 58 {hmac_final_n, 2, "use crypto:mac_finalN/2 instead"}, 59 {cmac, 3, "use crypto:mac/4 instead"}, 60 {cmac, 4, "use crypto:macN/5 instead"}, 61 {poly1305, 2, "use crypto:mac/3 instead"}, 62 {stream_init, '_', "use crypto:crypto_init/3 + crypto:crypto_update/2 + " 63 "crypto:crypto_final/1 or crypto:crypto_one_time/4 instead"}, 64 {stream_encrypt, 2, "use crypto:crypto_update/2 instead"}, 65 {stream_decrypt, 2, "use crypto:crypto_update/2 instead"}, 66 {block_encrypt, 3, "use crypto:crypto_one_time/4 or crypto:crypto_init/3 + " 67 "crypto:crypto_update/2 + crypto:crypto_final/1 instead"}, 68 {block_encrypt, 4, "use crypto:crypto_one_time/5, crypto:crypto_one_time_aead/6,7 " 69 "or crypto:crypto_(dyn_iv)?_init + " 70 "crypto:crypto_(dyn_iv)?_update + crypto:crypto_final instead"}, 71 {block_decrypt, 3, "use crypto:crypto_one_time/4 or crypto:crypto_init/3 + " 72 "crypto:crypto_update/2 + crypto:crypto_final/1 instead"}, 73 {block_decrypt, 4, "use crypto:crypto_one_time/5, crypto:crypto_one_time_aead/6,7 " 74 "or crypto:crypto_(dyn_iv)?_init + " 75 "crypto:crypto_(dyn_iv)?_update + crypto:crypto_final instead"} 76 ]). 77 78-removed_type([{retired_cbc_cipher_aliases, 0, "Use aes_*_cbc or des_ede3_cbc"}, 79 {retired_cfb_cipher_aliases, 0, "Use aes_*_cfb8, aes_*_cfb128 or des_ede3_cfb"}, 80 {retired_ctr_cipher_aliases, 0, "Use aes_*_ctr"}, 81 {retired_ecb_cipher_aliases, 0, "Use aes_*_ecb"}, 82 {stream_state, 0, "see the 'New and Old API' chapter of the CRYPTO User's guide"}, 83 {hmac_state, 0, "see the 'New and Old API' chapter of the CRYPTO User's guide"} 84 ]). 85 86%%%---------------------------------------------------------------- 87%% New interface 88-export([crypto_init/4, crypto_init/3, 89 crypto_update/2, 90 91 crypto_one_time/4, crypto_one_time/5, 92 crypto_one_time_aead/6, crypto_one_time_aead/7, 93 94 crypto_dyn_iv_init/3, 95 crypto_dyn_iv_update/3, 96 crypto_final/1, 97 crypto_get_data/1, 98 99 supports/1, 100 mac/3, mac/4, macN/4, macN/5, 101 mac_init/2, mac_init/3, mac_update/2, mac_final/1, mac_finalN/2 102 ]). 103 104%%%---------------------------------------------------------------- 105%% Engine 106-export([ 107 engine_get_all_methods/0, 108 engine_load/3, 109 engine_load/4, 110 engine_unload/1, 111 engine_by_id/1, 112 engine_list/0, 113 engine_ctrl_cmd_string/3, 114 engine_ctrl_cmd_string/4, 115 engine_add/1, 116 engine_remove/1, 117 engine_get_id/1, 118 engine_get_name/1, 119 ensure_engine_loaded/2, 120 ensure_engine_loaded/3, 121 ensure_engine_unloaded/1, 122 ensure_engine_unloaded/2 123 ]). 124 125-export_type([ %% A minimum exported: only what public_key needs. 126 dh_private/0, 127 dh_public/0, 128 dss_digest_type/0, 129 ec_named_curve/0, 130 ecdsa_digest_type/0, 131 pk_encrypt_decrypt_opts/0, 132 pk_sign_verify_opts/0, 133 rsa_digest_type/0, 134 sha1/0, 135 sha2/0 136 ]). 137 138-export_type([engine_ref/0, 139 key_id/0, 140 password/0 141 ]). 142 143%%% Opaque types must be exported :( 144-export_type([ 145 hash_state/0, 146 crypto_state/0, 147 mac_state/0 148 ]). 149 150%% Private. For tests. 151-export([packed_openssl_version/4, engine_methods_convert_to_bitmask/2, 152 get_test_engine/0]). 153-export([rand_plugin_aes_jump_2pow20/1]). 154 155-deprecated({rand_uniform, 2, "use rand:uniform/1 instead"}). 156 157%% This should correspond to the similar macro in crypto.c 158-define(MAX_BYTES_TO_NIF, 20000). %% Current value is: erlang:system_info(context_reductions) * 10 159 160%% Used by strong_rand_float/0 161-define(HALF_DBL_EPSILON, 1.1102230246251565e-16). % math:pow(2, -53) 162 163 164%%% ===== BEGIN NEW TYPING ==== 165 166%%% Basic 167-type key_integer() :: integer() | binary(). % Always binary() when used as return value 168 169%%% Keys 170-type rsa_public() :: [key_integer()] . % [E, N] 171-type rsa_private() :: [key_integer()] . % [E, N, D] | [E, N, D, P1, P2, E1, E2, C] 172-type rsa_params() :: {ModulusSizeInBits::integer(), PublicExponent::key_integer()} . 173 174-type dss_public() :: [key_integer()] . % [P, Q, G, Y] 175-type dss_private() :: [key_integer()] . % [P, Q, G, X] 176 177-type ecdsa_public() :: key_integer() . 178-type ecdsa_private() :: key_integer() . 179-type ecdsa_params() :: ec_named_curve() | ec_explicit_curve() . 180 181-type eddsa_public() :: key_integer() . 182-type eddsa_private() :: key_integer() . 183-type eddsa_params() :: edwards_curve_ed() . 184 185-type srp_public() :: key_integer() . 186-type srp_private() :: key_integer() . 187-type srp_gen_params() :: {user,srp_user_gen_params()} | {host,srp_host_gen_params()}. 188-type srp_comp_params() :: {user,srp_user_comp_params()} | {host,srp_host_comp_params()}. 189-type srp_user_gen_params() :: list(binary() | atom() | list()) . 190-type srp_host_gen_params() :: list(binary() | atom() | list()) . 191-type srp_user_comp_params() :: list(binary() | atom()) . 192-type srp_host_comp_params() :: list(binary() | atom()) . 193 194-type dh_public() :: key_integer() . 195-type dh_private() :: key_integer() . 196-type dh_params() :: [key_integer()] . % [P, G] | [P, G, PrivateKeyBitLength] 197 198-type ecdh_public() :: key_integer() . 199-type ecdh_private() :: key_integer() . 200-type ecdh_params() :: ec_named_curve() | edwards_curve_dh() | ec_explicit_curve() . 201 202 203%%% Curves 204 205-type ec_explicit_curve() :: {Field :: ec_field(), 206 Curve :: ec_curve(), 207 BasePoint :: binary(), 208 Order :: binary(), 209 CoFactor :: none | % FIXME: Really? 210 binary() 211 } . 212 213-type ec_curve() :: {A :: binary(), 214 B :: binary(), 215 Seed :: none | binary() 216 } . 217 218-type ec_field() :: ec_prime_field() | ec_characteristic_two_field() . 219 220-type ec_prime_field() :: {prime_field, Prime :: integer()} . 221-type ec_characteristic_two_field() :: {characteristic_two_field, M :: integer(), Basis :: ec_basis()} . 222 223-type ec_basis() :: {tpbasis, K :: non_neg_integer()} 224 | {ppbasis, K1 :: non_neg_integer(), K2 :: non_neg_integer(), K3 :: non_neg_integer()} 225 | onbasis . 226 227-type ec_named_curve() :: brainpoolP160r1 228 | brainpoolP160t1 229 | brainpoolP192r1 230 | brainpoolP192t1 231 | brainpoolP224r1 232 | brainpoolP224t1 233 | brainpoolP256r1 234 | brainpoolP256t1 235 | brainpoolP320r1 236 | brainpoolP320t1 237 | brainpoolP384r1 238 | brainpoolP384t1 239 | brainpoolP512r1 240 | brainpoolP512t1 241 | c2pnb163v1 242 | c2pnb163v2 243 | c2pnb163v3 244 | c2pnb176v1 245 | c2pnb208w1 246 | c2pnb272w1 247 | c2pnb304w1 248 | c2pnb368w1 249 | c2tnb191v1 250 | c2tnb191v2 251 | c2tnb191v3 252 | c2tnb239v1 253 | c2tnb239v2 254 | c2tnb239v3 255 | c2tnb359v1 256 | c2tnb431r1 257 | ipsec3 258 | ipsec4 259 | prime192v1 260 | prime192v2 261 | prime192v3 262 | prime239v1 263 | prime239v2 264 | prime239v3 265 | prime256v1 266 | secp112r1 267 | secp112r2 268 | secp128r1 269 | secp128r2 270 | secp160k1 271 | secp160r1 272 | secp160r2 273 | secp192k1 274 | secp192r1 275 | secp224k1 276 | secp224r1 277 | secp256k1 278 | secp256r1 279 | secp384r1 280 | secp521r1 281 | sect113r1 282 | sect113r2 283 | sect131r1 284 | sect131r2 285 | sect163k1 286 | sect163r1 287 | sect163r2 288 | sect193r1 289 | sect193r2 290 | sect233k1 291 | sect233r1 292 | sect239k1 293 | sect283k1 294 | sect283r1 295 | sect409k1 296 | sect409r1 297 | sect571k1 298 | sect571r1 299 | wtls1 300 | wtls10 301 | wtls11 302 | wtls12 303 | wtls3 304 | wtls4 305 | wtls5 306 | wtls6 307 | wtls7 308 | wtls8 309 | wtls9 310 . 311 312-type edwards_curve_dh() :: x25519 | x448 . 313 314-type edwards_curve_ed() :: ed25519 | ed448 . 315 316%%%---------------------------------------------------------------- 317%%% New cipher schema 318%%% 319-type cipher() :: cipher_no_iv() 320 | cipher_iv() 321 | cipher_aead() . 322 323-type cipher_no_iv() :: aes_128_ecb 324 | aes_192_ecb 325 | aes_256_ecb 326 | aes_ecb 327 328 | blowfish_ecb 329 | des_ecb 330 | rc4 . 331 332-type cipher_iv() :: aes_128_cbc 333 | aes_192_cbc 334 | aes_256_cbc 335 | aes_cbc 336 337 | aes_128_cfb128 338 | aes_192_cfb128 339 | aes_256_cfb128 340 | aes_cfb128 341 342 | aes_128_cfb8 343 | aes_192_cfb8 344 | aes_256_cfb8 345 | aes_cfb8 346 347 | aes_128_ctr 348 | aes_192_ctr 349 | aes_256_ctr 350 | aes_ctr 351 352 | blowfish_cbc 353 | blowfish_cfb64 354 | blowfish_ofb64 355 | chacha20 356 | des_ede3_cbc 357 | des_ede3_cfb 358 359 | des_cbc 360 | des_cfb 361 | rc2_cbc . 362 363 364-type cipher_aead() :: aes_128_ccm 365 | aes_192_ccm 366 | aes_256_ccm 367 | aes_ccm 368 369 | aes_128_gcm 370 | aes_192_gcm 371 | aes_256_gcm 372 | aes_gcm 373 374 | chacha20_poly1305 . 375 376 377%%%---------------------------------------------------------------- 378 379-type rsa_digest_type() :: sha1() | sha2() | md5 | ripemd160 . 380-type dss_digest_type() :: sha1() | sha2() . 381-type ecdsa_digest_type() :: sha1() | sha2() . 382 383-type sha1() :: sha . 384-type sha2() :: sha224 | sha256 | sha384 | sha512 . 385-type sha3() :: sha3_224 | sha3_256 | sha3_384 | sha3_512 . 386-type blake2() :: blake2b | blake2s . 387 388-type compatibility_only_hash() :: md5 | md4 . 389 390-type crypto_integer() :: binary() | integer(). 391 392%%% 393%% Exceptions 394%% error:badarg 395%% error:notsup 396-type run_time_error() :: any(). 397 398%% Exceptions 399%% error:{badarg,Reason::term()} 400%% error:{notsup,Reason::term()} 401%% error:{error,Reason::term()} 402-type descriptive_error() :: any() . 403 404 405%%-------------------------------------------------------------------- 406%% 407%% Make the new descriptive_error() look like the old run_time_error() 408%% 409-define(COMPAT(CALL), 410 try begin CALL end 411 catch 412 error:{error, {_File,_Line}, _Reason} -> 413 error(badarg); 414 error:{E, {_File,_Line}, _Reason} when E==notsup ; E==badarg -> 415 error(E) 416 end). 417 418%%-------------------------------------------------------------------- 419-compile(no_native). 420-on_load(on_load/0). 421-define(CRYPTO_NIF_VSN,302). 422 423-define(nif_stub,nif_stub_error(?LINE)). 424nif_stub_error(Line) -> 425 erlang:nif_error({nif_not_loaded,module,?MODULE,line,Line}). 426 427%%-------------------------------------------------------------------- 428%%% API 429%%-------------------------------------------------------------------- 430%% Crypto app version history: 431%% (no version): Driver implementation 432%% 2.0 : NIF implementation, requires OTP R14 433 434%% When generating documentation from crypto.erl, the macro ?CRYPTO_VSN is not defined. 435%% That causes the doc generation to stop... 436-ifndef(CRYPTO_VSN). 437-define(CRYPTO_VSN, "??"). 438-endif. 439version() -> ?CRYPTO_VSN. 440 441-spec start() -> ok | {error, Reason::term()}. 442start() -> 443 application:start(crypto). 444 445-spec stop() -> ok | {error, Reason::term()}. 446stop() -> 447 application:stop(crypto). 448 449-spec supports() -> [Support] 450 when Support :: {hashs, Hashs} 451 | {ciphers, Ciphers} 452 | {public_keys, PKs} 453 | {macs, Macs} 454 | {curves, Curves} 455 | {rsa_opts, RSAopts}, 456 Hashs :: [sha1() | sha2() | sha3() | blake2() | ripemd160 | compatibility_only_hash()], 457 Ciphers :: [cipher()], 458 PKs :: [rsa | dss | ecdsa | dh | ecdh | eddh | ec_gf2m], 459 Macs :: [hmac | cmac | poly1305], 460 Curves :: [ec_named_curve() | edwards_curve_dh() | edwards_curve_ed()], 461 RSAopts :: [rsa_sign_verify_opt() | rsa_opt()] . 462supports() -> 463 [{hashs, supports(hashs)}, 464 {ciphers, supports(ciphers)} 465 | [{T,supports(T)} || T <- [public_keys, 466 macs, 467 curves, 468 rsa_opts] 469 ] 470 ]. 471 472 473-spec supports(Type) -> Support 474 when Type :: hashs 475 | ciphers 476 | public_keys 477 | macs 478 | curves 479 | rsa_opts, 480 Support :: Hashs 481 | Ciphers 482 | PKs 483 | Macs 484 | Curves 485 | RSAopts, 486 Hashs :: [sha1() | sha2() | sha3() | blake2() | ripemd160 | compatibility_only_hash()], 487 Ciphers :: [cipher()], 488 PKs :: [rsa | dss | ecdsa | dh | ecdh | eddh | ec_gf2m], 489 Macs :: [hmac | cmac | poly1305], 490 Curves :: [ec_named_curve() | edwards_curve_dh() | edwards_curve_ed()], 491 RSAopts :: [rsa_sign_verify_opt() | rsa_opt()] . 492 493-define(CURVES, '$curves$'). 494 495supports(hashs) -> hash_algorithms(); 496supports(public_keys) -> pubkey_algorithms(); 497supports(ciphers) -> cipher_algorithms(); 498supports(macs) -> mac_algorithms(); 499supports(curves) -> curve_algorithms(); 500supports(rsa_opts) -> rsa_opts_algorithms(). 501 502 503-spec info_lib() -> [{Name,VerNum,VerStr}] when Name :: binary(), 504 VerNum :: integer(), 505 VerStr :: binary() . 506info_lib() -> ?nif_stub. 507 508%% info/0 and info_nif/0 are experimental. May disapear or change without warning. 509info() -> info_nif(). 510info_nif() -> ?nif_stub. 511 512 513-spec info_fips() -> not_supported | not_enabled | enabled. 514 515info_fips() -> ?nif_stub. 516 517-spec enable_fips_mode(Enable) -> Result when Enable :: boolean(), 518 Result :: boolean(). 519enable_fips_mode(Enable) -> 520 enable_fips_mode_nif(Enable). 521 522enable_fips_mode_nif(_) -> ?nif_stub. 523 524%%%================================================================ 525%%% 526%%% Hashing 527%%% 528%%%================================================================ 529 530-type hash_algorithm() :: sha1() | sha2() | sha3() | blake2() | ripemd160 | compatibility_only_hash() . 531 532-spec hash_info(Type) -> Result | run_time_error() 533 when Type :: hash_algorithm(), 534 Result :: #{size := integer(), 535 block_size := integer(), 536 type := integer() 537 } . 538hash_info(Type) -> 539 notsup_to_error(hash_info_nif(Type)). 540 541-spec hash(Type, Data) -> Digest when Type :: hash_algorithm(), 542 Data :: iodata(), 543 Digest :: binary(). 544hash(Type, Data) -> 545 Data1 = iolist_to_binary(Data), 546 MaxBytes = max_bytes(), 547 hash(Type, Data1, erlang:byte_size(Data1), MaxBytes). 548 549-opaque hash_state() :: reference(). 550 551-spec hash_init(Type) -> State when Type :: hash_algorithm(), 552 State :: hash_state(). 553hash_init(Type) -> 554 notsup_to_error(hash_init_nif(Type)). 555 556-spec hash_update(State, Data) -> NewState when State :: hash_state(), 557 NewState :: hash_state(), 558 Data :: iodata() . 559hash_update(Context, Data) -> 560 Data1 = iolist_to_binary(Data), 561 MaxBytes = max_bytes(), 562 hash_update(Context, Data1, erlang:byte_size(Data1), MaxBytes). 563 564-spec hash_final(State) -> Digest when State :: hash_state(), 565 Digest :: binary(). 566hash_final(Context) -> 567 notsup_to_error(hash_final_nif(Context)). 568 569%%%================================================================ 570%%% 571%%% MACs (Message Authentication Codes) 572%%% 573%%%================================================================ 574 575-type hmac_hash_algorithm() :: sha1() | sha2() | sha3() | compatibility_only_hash(). 576 577-type cmac_cipher_algorithm() :: aes_128_cbc | aes_192_cbc | aes_256_cbc | aes_cbc 578 | aes_128_cfb128 | aes_192_cfb128 | aes_256_cfb128 | aes_cfb128 579 | aes_128_cfb8 | aes_192_cfb8 | aes_256_cfb8 | aes_cfb8 580 | blowfish_cbc 581 | des_cbc | des_ede3_cbc 582 | rc2_cbc 583 . 584 585%%%---------------------------------------------------------------- 586%%% Calculate MAC for the whole text at once 587 588-spec mac(Type :: poly1305, Key, Data) -> Mac | descriptive_error() 589 when Key :: iodata(), 590 Data :: iodata(), 591 Mac :: binary(). 592 593mac(poly1305, Key, Data) -> mac(poly1305, undefined, Key, Data). 594 595 596-spec mac(Type, SubType, Key, Data) -> Mac | descriptive_error() 597 when Type :: hmac | cmac | poly1305, 598 SubType :: hmac_hash_algorithm() | cmac_cipher_algorithm() | undefined, 599 Key :: iodata(), 600 Data :: iodata(), 601 Mac :: binary(). 602 603mac(Type, SubType, Key0, Data) -> 604 Key = iolist_to_binary(Key0), 605 mac_nif(Type, alias(SubType,Key), Key, Data). 606 607 608 609-spec macN(Type :: poly1305, Key, Data, MacLength) -> Mac | descriptive_error() 610 when Key :: iodata(), 611 Data :: iodata(), 612 Mac :: binary(), 613 MacLength :: pos_integer(). 614 615macN(Type, Key, Data, MacLength) -> 616 macN(Type, undefined, Key, Data, MacLength). 617 618 619-spec macN(Type, SubType, Key, Data, MacLength) -> Mac | descriptive_error() 620 when Type :: hmac | cmac | poly1305, 621 SubType :: hmac_hash_algorithm() | cmac_cipher_algorithm() | undefined, 622 Key :: iodata(), 623 Data :: iodata(), 624 Mac :: binary(), 625 MacLength :: pos_integer(). 626 627macN(Type, SubType, Key, Data, MacLength) -> 628 erlang:binary_part(mac(Type,SubType,Key,Data), 0, MacLength). 629 630 631%%%---------------------------------------------------------------- 632%%% Calculate the MAC by uppdating by pieces of the text 633 634-opaque mac_state() :: reference() . 635 636-spec mac_init(Type :: poly1305, Key) -> State | descriptive_error() 637 when Key :: iodata(), 638 State :: mac_state() . 639mac_init(poly1305, Key) -> 640 mac_init_nif(poly1305, undefined, Key). 641 642 643-spec mac_init(Type, SubType, Key) -> State | descriptive_error() 644 when Type :: hmac | cmac | poly1305, 645 SubType :: hmac_hash_algorithm() | cmac_cipher_algorithm() | undefined, 646 Key :: iodata(), 647 State :: mac_state() . 648mac_init(Type, SubType, Key0) -> 649 Key = iolist_to_binary(Key0), 650 mac_init_nif(Type, alias(SubType,Key), Key). 651 652 653-spec mac_update(State0, Data) -> State | descriptive_error() 654 when Data :: iodata(), 655 State0 :: mac_state(), 656 State :: mac_state(). 657mac_update(Ref, Data) -> 658 mac_update_nif(Ref, Data). 659 660 661 662-spec mac_final(State) -> Mac | descriptive_error() 663 when State :: mac_state(), 664 Mac :: binary(). 665mac_final(Ref) -> 666 mac_final_nif(Ref). 667 668 669-spec mac_finalN(State, MacLength) -> Mac | descriptive_error() 670 when State :: mac_state(), 671 MacLength :: pos_integer(), 672 Mac :: binary(). 673mac_finalN(Ref, MacLength) -> 674 erlang:binary_part(mac_final(Ref), 0, MacLength). 675 676 677%%%---------------------------------------------------------------- 678%%% NIFs for the functions above 679 680mac_nif(_Type, _SubType, _Key, _Data) -> ?nif_stub. 681 682mac_init_nif(_Type, _SubType, _Key) -> ?nif_stub. 683mac_update_nif(_Ref, _Data) -> ?nif_stub. 684mac_final_nif(_Ref) -> ?nif_stub. 685 686%%%================================================================ 687%%% 688%%% The "Old API", kept for compatibility 689%%% 690%%%================================================================ 691 692%%%---------------------------------------------------------------- 693%%% Ciphers 694 695 696%%%---- Cipher info 697-spec cipher_info(Type) -> Result | run_time_error() 698 when Type :: cipher(), 699 Result :: #{key_length := integer(), 700 iv_length := integer(), 701 block_size := integer(), 702 mode := CipherModes, 703 type := undefined | integer(), 704 prop_aead := boolean() 705 }, 706 CipherModes :: undefined 707 | cbc_mode 708 | ccm_mode 709 | cfb_mode 710 | ctr_mode 711 | ecb_mode 712 | gcm_mode 713 | ige_mode 714 | ocb_mode 715 | ofb_mode 716 | wrap_mode 717 | xts_mode 718 . 719 720cipher_info(Type) -> 721 try cipher_info_nif(Type) 722 catch 723 %% These ciphers are not available via the EVP interface on older cryptolibs. 724 error:notsup when Type == aes_128_ctr -> 725 #{block_size => 1,iv_length => 16,key_length => 16,mode => ctr_mode,type => undefined}; 726 727 error:notsup when Type == aes_192_ctr -> 728 #{block_size => 1,iv_length => 16,key_length => 24,mode => ctr_mode,type => undefined}; 729 730 error:notsup when Type == aes_256_ctr -> 731 #{block_size => 1,iv_length => 16,key_length => 32,mode => ctr_mode,type => undefined}; 732 733 error:badarg -> 734 %% Maybe an alias: we don't know the key length.. 735 case alias1(Type, 16) of 736 Type -> 737 %% Not found, propagate 738 error(badarg); 739 NewType -> 740 cipher_info(NewType) 741 end 742 end. 743 744%%%================================================================ 745%%% 746%%% Encrypt/decrypt, The "New API" 747%%% 748%%%================================================================ 749 750-opaque crypto_state() :: reference() . 751 752-type crypto_opts() :: boolean() 753 | [ crypto_opt() ] . 754-type crypto_opt() :: {encrypt,boolean()} 755 | {padding, padding()} . 756-type padding() :: cryptolib_padding() | otp_padding(). 757-type cryptolib_padding() :: none | pkcs_padding . 758-type otp_padding() :: zero | random . 759 760 761%%%---------------------------------------------------------------- 762%%% 763%%% Create and initialize a new state for encryption or decryption 764%%% 765 766-spec crypto_init(Cipher, Key, FlagOrOptions) -> State | descriptive_error() 767 when Cipher :: cipher_no_iv(), 768 Key :: iodata(), 769 FlagOrOptions :: crypto_opts() | boolean(), 770 State :: crypto_state() . 771crypto_init(Cipher, Key, FlagOrOptions) -> 772 ng_crypto_init_nif(Cipher, 773 iolist_to_binary(Key), 774 <<>>, 775 get_crypto_opts(FlagOrOptions)). 776 777 778-spec crypto_init(Cipher, Key, IV, FlagOrOptions) -> State | descriptive_error() 779 when Cipher :: cipher_iv(), 780 Key :: iodata(), 781 IV :: iodata(), 782 FlagOrOptions :: crypto_opts(), 783 State :: crypto_state() . 784crypto_init(Cipher, Key, IV, FlagOrOptions) -> 785 ng_crypto_init_nif(Cipher, 786 iolist_to_binary(Key), 787 iolist_to_binary(IV), 788 get_crypto_opts(FlagOrOptions)). 789 790%%%---------------------------------------------------------------- 791get_crypto_opts(Options) when is_list(Options) -> 792 lists:foldl(fun chk_opt/2, 793 #{encrypt => true, 794 padding => undefined 795 }, 796 Options); 797get_crypto_opts(Flag) when is_boolean(Flag) -> 798 #{encrypt => Flag, 799 padding => undefined 800 }; 801get_crypto_opts(X) -> 802 error({badarg,{bad_option,X}}). 803 804 805chk_opt({Tag,Val}, A) -> 806 case ok_opt(Tag,Val) of 807 true -> 808 A#{Tag => Val}; 809 false -> 810 error({badarg,{bad_option,{Tag,Val}}}) 811 end; 812chk_opt(X, _) -> 813 error({badarg,{bad_option,X}}). 814 815 816ok_opt(encrypt, V) -> lists:member(V, [true, false, undefined]); 817ok_opt(padding, V) -> lists:member(V, [none, pkcs_padding, zero, random, undefined]); 818ok_opt(_, _) -> false. 819 820%%%---------------------------------------------------------------- 821-spec crypto_dyn_iv_init(Cipher, Key, FlagOrOptions) -> State | descriptive_error() 822 when Cipher :: cipher_iv(), 823 Key :: iodata(), 824 FlagOrOptions :: crypto_opts() | boolean(), 825 State :: crypto_state() . 826crypto_dyn_iv_init(Cipher, Key, FlagOrOptions) -> 827 %% The IV is supposed to be supplied by calling crypto_update/3 828 ng_crypto_init_nif(Cipher, 829 iolist_to_binary(Key), 830 undefined, 831 get_crypto_opts(FlagOrOptions)). 832 833%%%---------------------------------------------------------------- 834%%% 835%%% Encrypt/decrypt a sequence of bytes. The sum of the sizes 836%%% of all blocks must be an integer multiple of the crypto's 837%%% blocksize. 838%%% 839 840-spec crypto_update(State, Data) -> Result | descriptive_error() 841 when State :: crypto_state(), 842 Data :: iodata(), 843 Result :: binary() . 844crypto_update(State, Data) -> 845 ng_crypto_update_nif(State, iolist_to_binary(Data)). 846 847%%%---------------------------------------------------------------- 848-spec crypto_dyn_iv_update(State, Data, IV) -> Result | descriptive_error() 849 when State :: crypto_state(), 850 Data :: iodata(), 851 IV :: iodata(), 852 Result :: binary() . 853crypto_dyn_iv_update(State, Data, IV) -> 854 ng_crypto_update_nif(State, iolist_to_binary(Data), iolist_to_binary(IV)). 855 856%%%---------------------------------------------------------------- 857%%% 858%%% Finalize encrypt/decrypt bytes. If the size of the bytes in 859%%% to crypto_uptate was not an integer number of blocks, the rest 860%%% is returned from this function. 861 862-spec crypto_final(State) -> FinalResult | descriptive_error() 863 when State :: crypto_state(), 864 FinalResult :: binary() . 865crypto_final(State) -> 866 ng_crypto_final_nif(State). 867 868%%%---------------------------------------------------------------- 869%%% 870%%% Get result of padding etc 871 872-spec crypto_get_data(State) -> Result 873 when State :: crypto_state(), 874 Result :: map() . 875crypto_get_data(State) -> 876 ng_crypto_get_data_nif(State). 877 878%%%---------------------------------------------------------------- 879%%% 880%%% Encrypt/decrypt one set bytes. 881%%% The size must be an integer multiple of the crypto's blocksize. 882%%% 883 884-spec crypto_one_time(Cipher, Key, Data, FlagOrOptions) -> 885 Result | descriptive_error() 886 when Cipher :: cipher_no_iv(), 887 Key :: iodata(), 888 Data :: iodata(), 889 FlagOrOptions :: crypto_opts() | boolean(), 890 Result :: binary() . 891 892crypto_one_time(Cipher, Key, Data, FlagOrOptions) -> 893 ng_crypto_one_time_nif(Cipher, 894 iolist_to_binary(Key), 895 <<>>, 896 iolist_to_binary(Data), 897 get_crypto_opts(FlagOrOptions)). 898 899 900-spec crypto_one_time(Cipher, Key, IV, Data, FlagOrOptions) -> 901 Result | descriptive_error() 902 when Cipher :: cipher_iv(), 903 Key :: iodata(), 904 IV :: iodata(), 905 Data :: iodata(), 906 FlagOrOptions :: crypto_opts() | boolean(), 907 Result :: binary() . 908 909crypto_one_time(Cipher, Key, IV, Data, FlagOrOptions) -> 910 ng_crypto_one_time_nif(Cipher, 911 iolist_to_binary(Key), 912 iolist_to_binary(IV), 913 iolist_to_binary(Data), 914 get_crypto_opts(FlagOrOptions)). 915 916%%%---------------------------------------------------------------- 917-spec crypto_one_time_aead(Cipher, Key, IV, InText, AAD, EncFlag::true) -> 918 Result | descriptive_error() 919 when Cipher :: cipher_aead(), 920 Key :: iodata(), 921 IV :: iodata(), 922 InText :: iodata(), 923 AAD :: iodata(), 924 Result :: EncryptResult, 925 EncryptResult :: {OutCryptoText, OutTag}, 926 OutCryptoText :: binary(), 927 OutTag :: binary(). 928 929crypto_one_time_aead(Cipher, Key, IV, PlainText, AAD, true) -> 930 crypto_one_time_aead(Cipher, Key, IV, PlainText, AAD, aead_tag_len(Cipher), true). 931 932 933-spec crypto_one_time_aead(Cipher, Key, IV, InText, AAD, TagOrTagLength, EncFlag) -> 934 Result | descriptive_error() 935 when Cipher :: cipher_aead(), 936 Key :: iodata(), 937 IV :: iodata(), 938 InText :: iodata(), 939 AAD :: iodata(), 940 TagOrTagLength :: EncryptTagLength | DecryptTag, 941 EncryptTagLength :: non_neg_integer(), % or pos_integer() 1.. 942 DecryptTag :: iodata(), 943 EncFlag :: boolean(), 944 Result :: EncryptResult | DecryptResult, 945 EncryptResult :: {OutCryptoText, OutTag}, 946 DecryptResult :: OutPlainText | error, 947 OutCryptoText :: binary(), 948 OutTag :: binary(), 949 OutPlainText :: binary(). 950 951crypto_one_time_aead(Cipher, Key, IV, TextIn, AAD, TagOrTagLength, EncFlg) -> 952 aead_cipher(Cipher, iolist_to_binary(Key), IV, 953 TextIn, AAD, TagOrTagLength, EncFlg). 954 955 956aead_tag_len(aes_ccm ) -> 12; 957aead_tag_len(aes_128_ccm) -> 12; 958aead_tag_len(aes_192_ccm) -> 12; 959aead_tag_len(aes_256_ccm) -> 12; 960aead_tag_len(aes_gcm ) -> 16; 961aead_tag_len(aes_128_gcm) -> 16; 962aead_tag_len(aes_192_gcm) -> 16; 963aead_tag_len(aes_256_gcm) -> 16; 964aead_tag_len(chacha20_poly1305) -> 16; 965aead_tag_len(_) -> 966 error({badarg, "Not an AEAD cipher"}). 967 968%%%---------------------------------------------------------------- 969%%% Cipher NIFs 970 971ng_crypto_init_nif(Cipher, Key, IVec, #{encrypt := EncryptFlag, 972 padding := Padding}) -> 973 ng_crypto_init_nif(alias(Cipher,Key), Key, IVec, EncryptFlag, Padding). 974 975ng_crypto_init_nif(_Cipher, _Key, _IVec, _EncryptFlag, _Padding) -> ?nif_stub. 976 977 978ng_crypto_update_nif(_State, _Data) -> ?nif_stub. 979ng_crypto_update_nif(_State, _Data, _IV) -> ?nif_stub. 980 981ng_crypto_final_nif(_State) -> ?nif_stub. 982 983ng_crypto_get_data_nif(_State) -> ?nif_stub. 984 985ng_crypto_one_time_nif(Cipher, Key, IVec, Data, #{encrypt := EncryptFlag, 986 padding := Padding}) -> 987 ng_crypto_one_time_nif(alias(Cipher,Key), Key, IVec, Data, EncryptFlag, Padding). 988 989ng_crypto_one_time_nif(_Cipher, _Key, _IVec, _Data, _EncryptFlag, _Padding) -> ?nif_stub. 990 991%% The default tag length is EVP_GCM_TLS_TAG_LEN(16), 992aead_cipher(Cipher, Key, IVec, AAD, In, TagOrLength, EncFlg) -> 993 aead_cipher_nif(alias(Cipher,Key), Key, IVec, AAD, In, TagOrLength, EncFlg). 994 995aead_cipher_nif(_Type, _Key, _Ivec, _AAD, _In, _TagOrTagLength, _EncFlg) -> ?nif_stub. 996 997cipher_info_nif(_Type) -> ?nif_stub. 998 999%%%---------------------------------------------------------------- 1000%%% Cipher aliases 1001%%% 1002 1003alias(aes_cbc, Key) -> alias1(aes_cbc, size(Key)); 1004alias(aes_cfb8, Key) -> alias1(aes_cfb8, size(Key)); 1005alias(aes_cfb128, Key) -> alias1(aes_cfb128, size(Key)); 1006alias(aes_ctr, Key) -> alias1(aes_ctr, size(Key)); 1007alias(aes_ecb, Key) -> alias1(aes_ecb, size(Key)); 1008alias(aes_gcm, Key) -> alias1(aes_gcm, size(Key)); 1009alias(aes_ccm, Key) -> alias1(aes_ccm, size(Key)); 1010alias(Alg, _) -> Alg. 1011 1012 1013alias1(aes_cbc, 16) -> aes_128_cbc; 1014alias1(aes_cbc, 24) -> aes_192_cbc; 1015alias1(aes_cbc, 32) -> aes_256_cbc; 1016 1017alias1(aes_cfb8, 16) -> aes_128_cfb8; 1018alias1(aes_cfb8, 24) -> aes_192_cfb8; 1019alias1(aes_cfb8, 32) -> aes_256_cfb8; 1020 1021alias1(aes_cfb128, 16) -> aes_128_cfb128; 1022alias1(aes_cfb128, 24) -> aes_192_cfb128; 1023alias1(aes_cfb128, 32) -> aes_256_cfb128; 1024 1025alias1(aes_ctr, 16) -> aes_128_ctr; 1026alias1(aes_ctr, 24) -> aes_192_ctr; 1027alias1(aes_ctr, 32) -> aes_256_ctr; 1028 1029alias1(aes_ecb, 16) -> aes_128_ecb; 1030alias1(aes_ecb, 24) -> aes_192_ecb; 1031alias1(aes_ecb, 32) -> aes_256_ecb; 1032 1033alias1(aes_gcm, 16) -> aes_128_gcm; 1034alias1(aes_gcm, 24) -> aes_192_gcm; 1035alias1(aes_gcm, 32) -> aes_256_gcm; 1036 1037alias1(aes_ccm, 16) -> aes_128_ccm; 1038alias1(aes_ccm, 24) -> aes_192_ccm; 1039alias1(aes_ccm, 32) -> aes_256_ccm; 1040 1041alias1(Alg, _) -> Alg. 1042 1043%%%================================================================ 1044%%% 1045%%% RAND - pseudo random numbers using RN_ and BN_ functions in crypto lib 1046%%% 1047%%%================================================================ 1048-type rand_cache_seed() :: 1049 nonempty_improper_list(non_neg_integer(), binary()). 1050 1051-spec strong_rand_bytes(N::non_neg_integer()) -> binary(). 1052strong_rand_bytes(Bytes) -> 1053 case strong_rand_bytes_nif(Bytes) of 1054 false -> erlang:error(low_entropy); 1055 Bin -> Bin 1056 end. 1057strong_rand_bytes_nif(_Bytes) -> ?nif_stub. 1058 1059 1060-spec rand_seed() -> rand:state(). 1061rand_seed() -> 1062 rand:seed(rand_seed_s()). 1063 1064-spec rand_seed_s() -> rand:state(). 1065rand_seed_s() -> 1066 rand_seed_alg_s(?MODULE). 1067 1068-spec rand_seed_alg(Alg :: atom()) -> 1069 {rand:alg_handler(), 1070 atom() | rand_cache_seed()}. 1071rand_seed_alg(Alg) -> 1072 rand:seed(rand_seed_alg_s(Alg)). 1073 1074-spec rand_seed_alg(Alg :: atom(), Seed :: term()) -> 1075 {rand:alg_handler(), 1076 atom() | rand_cache_seed()}. 1077rand_seed_alg(Alg, Seed) -> 1078 rand:seed(rand_seed_alg_s(Alg, Seed)). 1079 1080-define(CRYPTO_CACHE_BITS, 56). 1081-define(CRYPTO_AES_BITS, 58). 1082 1083-spec rand_seed_alg_s(Alg :: atom()) -> 1084 {rand:alg_handler(), 1085 atom() | rand_cache_seed()}. 1086rand_seed_alg_s({AlgHandler, _AlgState} = State) when is_map(AlgHandler) -> 1087 State; 1088rand_seed_alg_s({Alg, AlgState}) when is_atom(Alg) -> 1089 {mk_alg_handler(Alg),AlgState}; 1090 rand_seed_alg_s(Alg) when is_atom(Alg) -> 1091 {mk_alg_handler(Alg),mk_alg_state(Alg)}. 1092%% 1093-spec rand_seed_alg_s(Alg :: atom(), Seed :: term()) -> 1094 {rand:alg_handler(), 1095 atom() | rand_cache_seed()}. 1096rand_seed_alg_s(Alg, Seed) when is_atom(Alg) -> 1097 {mk_alg_handler(Alg),mk_alg_state({Alg,Seed})}. 1098 1099mk_alg_handler(?MODULE = Alg) -> 1100 #{ type => Alg, 1101 bits => 64, 1102 next => fun ?MODULE:rand_plugin_next/1, 1103 uniform => fun ?MODULE:rand_plugin_uniform/1, 1104 uniform_n => fun ?MODULE:rand_plugin_uniform/2}; 1105mk_alg_handler(crypto_cache = Alg) -> 1106 #{ type => Alg, 1107 bits => ?CRYPTO_CACHE_BITS, 1108 next => fun ?MODULE:rand_cache_plugin_next/1}; 1109mk_alg_handler(crypto_aes = Alg) -> 1110 #{ type => Alg, 1111 bits => ?CRYPTO_AES_BITS, 1112 next => fun ?MODULE:rand_plugin_aes_next/1, 1113 jump => fun ?MODULE:rand_plugin_aes_jump/1}. 1114 1115mk_alg_state(?MODULE) -> 1116 no_seed; 1117mk_alg_state(crypto_cache) -> 1118 CacheBits = ?CRYPTO_CACHE_BITS, 1119 BytesPerWord = (CacheBits + 7) div 8, 1120 GenBytes = 1121 ((rand_cache_size() + (2*BytesPerWord - 1)) div BytesPerWord) 1122 * BytesPerWord, 1123 {CacheBits, GenBytes, <<>>}; 1124mk_alg_state({crypto_aes,Seed}) -> 1125 %% 16 byte words (128 bit crypto blocks) 1126 GenWords = (rand_cache_size() + 31) div 16, 1127 Key = crypto:hash(sha256, Seed), 1128 {F,Count} = longcount_seed(Seed), 1129 {Key,GenWords,F,Count}. 1130 1131rand_cache_size() -> 1132 DefaultCacheSize = 1024, 1133 CacheSize = 1134 application:get_env(crypto, rand_cache_size, DefaultCacheSize), 1135 if 1136 is_integer(CacheSize), 0 =< CacheSize -> 1137 CacheSize; 1138 true -> 1139 DefaultCacheSize 1140 end. 1141 1142rand_plugin_next(Seed) -> 1143 {bytes_to_integer(strong_rand_range(1 bsl 64)), Seed}. 1144 1145rand_plugin_uniform(State) -> 1146 {strong_rand_float(), State}. 1147 1148rand_plugin_uniform(Max, State) -> 1149 {bytes_to_integer(strong_rand_range(Max)) + 1, State}. 1150 1151 1152rand_cache_plugin_next({CacheBits, GenBytes, <<>>}) -> 1153 rand_cache_plugin_next( 1154 {CacheBits, GenBytes, strong_rand_bytes(GenBytes)}); 1155rand_cache_plugin_next({CacheBits, GenBytes, Cache}) -> 1156 <<I:CacheBits, NewCache/binary>> = Cache, 1157 {I, {CacheBits, GenBytes, NewCache}}. 1158 1159 1160%% Encrypt 128 bit counter values and use the 58 lowest 1161%% encrypted bits as random numbers. 1162%% 1163%% The 128 bit counter is handled as 4 32 bit words 1164%% to avoid bignums. Generate a bunch of numbers 1165%% at the time and cache them. 1166%% 1167-dialyzer({no_improper_lists, rand_plugin_aes_next/1}). 1168rand_plugin_aes_next([V|Cache]) -> 1169 {V,Cache}; 1170rand_plugin_aes_next({Key,GenWords,F,Count}) -> 1171 rand_plugin_aes_next(Key, GenWords, F, Count); 1172rand_plugin_aes_next({Key,GenWords,F,_JumpBase,Count}) -> 1173 rand_plugin_aes_next(Key, GenWords, F, Count). 1174%% 1175rand_plugin_aes_next(Key, GenWords, F, Count) -> 1176 {Cleartext,NewCount} = aes_cleartext(<<>>, F, Count, GenWords), 1177 Encrypted = block_encrypt(Key, Cleartext), 1178 [V|Cache] = aes_cache(Encrypted, {Key,GenWords,F,Count,NewCount}), 1179 {V,Cache}. 1180 1181block_encrypt(Key, Data) -> 1182 Cipher = case size(Key) of 1183 16 -> aes_128_ecb; 1184 24 -> aes_192_ecb; 1185 32 -> aes_256_ecb; 1186 _ -> error(badarg) 1187 end, 1188 try 1189 crypto_one_time(Cipher, Key, Data, true) 1190 catch 1191 error:{error, {_File,_Line}, _Reason} -> 1192 error(badarg); 1193 error:{E, {_File,_Line}, _Reason} when E==notsup ; E==badarg -> 1194 error(E) 1195 end. 1196 1197 1198%% A jump advances the counter 2^512 steps; the jump function 1199%% is applied to the jump base and then the number of used 1200%% numbers from the cache has to be wasted for the jump to be correct 1201%% 1202rand_plugin_aes_jump({#{type := crypto_aes} = Alg, Cache}) -> 1203 {Alg,rand_plugin_aes_jump(fun longcount_jump/1, 0, Cache)}. 1204%% Count cached words and subtract their number from jump 1205-dialyzer({no_improper_lists, rand_plugin_aes_jump/3}). 1206rand_plugin_aes_jump(Jump, J, [_|Cache]) -> 1207 rand_plugin_aes_jump(Jump, J + 1, Cache); 1208rand_plugin_aes_jump(Jump, J, {Key,GenWords,F,JumpBase, _Count}) -> 1209 rand_plugin_aes_jump(Jump, GenWords - J, Key, GenWords, F, JumpBase); 1210rand_plugin_aes_jump(Jump, 0, {Key,GenWords,F,JumpBase}) -> 1211 rand_plugin_aes_jump(Jump, 0, Key, GenWords, F, JumpBase). 1212%% 1213rand_plugin_aes_jump(Jump, Skip, Key, GenWords, F, JumpBase) -> 1214 Count = longcount_next_count(Skip, Jump(JumpBase)), 1215 {Key,GenWords,F,Count}. 1216 1217rand_plugin_aes_jump_2pow20(Cache) -> 1218 rand_plugin_aes_jump(fun longcount_jump_2pow20/1, 0, Cache). 1219 1220 1221longcount_seed(Seed) -> 1222 <<X:64, _:6, F:12, S2:58, S1:58, S0:58>> = 1223 crypto:hash(sha256, [Seed,<<"Xoroshiro928">>]), 1224 {F,rand:exro928_seed([S0,S1,S2|rand:seed58(13, X)])}. 1225 1226longcount_next_count(0, Count) -> 1227 Count; 1228longcount_next_count(N, Count) -> 1229 longcount_next_count(N - 1, rand:exro928_next_state(Count)). 1230 1231longcount_next(Count) -> 1232 rand:exro928_next(Count). 1233 1234longcount_jump(Count) -> 1235 rand:exro928_jump_2pow512(Count). 1236 1237longcount_jump_2pow20(Count) -> 1238 rand:exro928_jump_2pow20(Count). 1239 1240 1241%% Build binary with counter values to cache 1242aes_cleartext(Cleartext, _F, Count, 0) -> 1243 {Cleartext,Count}; 1244aes_cleartext(Cleartext, F, Count, GenWords) -> 1245 {{S0,S1}, NewCount} = longcount_next(Count), 1246 aes_cleartext( 1247 <<Cleartext/binary, F:12, S1:58, S0:58>>, 1248 F, NewCount, GenWords - 1). 1249 1250%% Parse and cache encrypted counter values aka random numbers 1251-dialyzer({no_improper_lists, aes_cache/2}). 1252aes_cache(<<>>, Cache) -> 1253 Cache; 1254aes_cache( 1255 <<_:(128 - ?CRYPTO_AES_BITS), V:?CRYPTO_AES_BITS, Encrypted/binary>>, 1256 Cache) -> 1257 [V|aes_cache(Encrypted, Cache)]. 1258 1259 1260strong_rand_range(Range) when is_integer(Range), Range > 0 -> 1261 BinRange = int_to_bin(Range), 1262 strong_rand_range(BinRange); 1263strong_rand_range(BinRange) when is_binary(BinRange) -> 1264 case strong_rand_range_nif(BinRange) of 1265 false -> 1266 erlang:error(low_entropy); 1267 <<BinResult/binary>> -> 1268 BinResult 1269 end. 1270strong_rand_range_nif(_BinRange) -> ?nif_stub. 1271 1272strong_rand_float() -> 1273 WholeRange = strong_rand_range(1 bsl 53), 1274 ?HALF_DBL_EPSILON * bytes_to_integer(WholeRange). 1275 1276-spec rand_uniform(crypto_integer(), crypto_integer()) -> 1277 crypto_integer(). 1278rand_uniform(From, To) when is_binary(From), is_binary(To) -> 1279 case rand_uniform_nif(From,To) of 1280 <<Len:32/integer, MSB, Rest/binary>> when MSB > 127 -> 1281 <<(Len + 1):32/integer, 0, MSB, Rest/binary>>; 1282 Whatever -> 1283 Whatever 1284 end; 1285rand_uniform(From,To) when is_integer(From),is_integer(To) -> 1286 if From < 0 -> 1287 rand_uniform_pos(0, To - From) + From; 1288 true -> 1289 rand_uniform_pos(From, To) 1290 end. 1291 1292rand_uniform_pos(From,To) when From < To -> 1293 BinFrom = mpint(From), 1294 BinTo = mpint(To), 1295 case rand_uniform(BinFrom, BinTo) of 1296 Result when is_binary(Result) -> 1297 erlint(Result); 1298 Other -> 1299 Other 1300 end; 1301rand_uniform_pos(_,_) -> 1302 error(badarg). 1303 1304rand_uniform_nif(_From,_To) -> ?nif_stub. 1305 1306 1307-spec rand_seed(binary()) -> ok. 1308rand_seed(Seed) when is_binary(Seed) -> 1309 rand_seed_nif(Seed). 1310 1311rand_seed_nif(_Seed) -> ?nif_stub. 1312 1313%%%================================================================ 1314%%% 1315%%% Sign/verify 1316%%% 1317%%%================================================================ 1318-type pk_sign_verify_algs() :: rsa | dss | ecdsa | eddsa . 1319 1320-type pk_sign_verify_opts() :: [ rsa_sign_verify_opt() ] . 1321 1322-type rsa_sign_verify_opt() :: {rsa_padding, rsa_sign_verify_padding()} 1323 | {rsa_pss_saltlen, integer()} 1324 | {rsa_mgf1_md, sha2()}. 1325 1326-type rsa_sign_verify_padding() :: rsa_pkcs1_padding | rsa_pkcs1_pss_padding 1327 | rsa_x931_padding | rsa_no_padding 1328 . 1329 1330 1331%%%---------------------------------------------------------------- 1332%%% Sign 1333 1334-spec sign(Algorithm, DigestType, Msg, Key) 1335 -> Signature 1336 when Algorithm :: pk_sign_verify_algs(), 1337 DigestType :: rsa_digest_type() 1338 | dss_digest_type() 1339 | ecdsa_digest_type() 1340 | none, 1341 Msg :: iodata() | {digest,iodata()}, 1342 Key :: rsa_private() 1343 | dss_private() 1344 | [ecdsa_private() | ecdsa_params()] 1345 | [eddsa_private() | eddsa_params()] 1346 | engine_key_ref(), 1347 Signature :: binary() . 1348 1349sign(Algorithm, Type, Data, Key) -> 1350 sign(Algorithm, Type, Data, Key, []). 1351 1352 1353-spec sign(Algorithm, DigestType, Msg, Key, Options) 1354 -> Signature 1355 when Algorithm :: pk_sign_verify_algs(), 1356 DigestType :: rsa_digest_type() 1357 | dss_digest_type() 1358 | ecdsa_digest_type() 1359 | none, 1360 Msg :: iodata() | {digest,iodata()}, 1361 Key :: rsa_private() 1362 | dss_private() 1363 | [ecdsa_private() | ecdsa_params()] 1364 | [eddsa_private() | eddsa_params()] 1365 | engine_key_ref(), 1366 Options :: pk_sign_verify_opts(), 1367 Signature :: binary() . 1368 1369sign(Algorithm0, Type0, Data, Key, Options) -> 1370 {Algorithm, Type} = sign_verify_compatibility(Algorithm0, Type0, Data), 1371 case pkey_sign_nif(Algorithm, Type, Data, format_pkey(Algorithm, Key), Options) of 1372 error -> erlang:error(badkey, [Algorithm, Type, Data, Key, Options]); 1373 notsup -> erlang:error(notsup); 1374 Signature -> Signature 1375 end. 1376 1377pkey_sign_nif(_Algorithm, _Type, _Digest, _Key, _Options) -> ?nif_stub. 1378 1379%%%---------------------------------------------------------------- 1380%%% Verify 1381 1382-spec verify(Algorithm, DigestType, Msg, Signature, Key) 1383 -> Result 1384 when Algorithm :: pk_sign_verify_algs(), 1385 DigestType :: rsa_digest_type() 1386 | dss_digest_type() 1387 | ecdsa_digest_type() 1388 | none, 1389 Msg :: iodata() | {digest,iodata()}, 1390 Signature :: binary(), 1391 Key :: rsa_public() 1392 | dss_public() 1393 | [ecdsa_public() | ecdsa_params()] 1394 | [eddsa_public() | eddsa_params()] 1395 | engine_key_ref(), 1396 Result :: boolean(). 1397 1398verify(Algorithm, Type, Data, Signature, Key) -> 1399 verify(Algorithm, Type, Data, Signature, Key, []). 1400 1401-spec verify(Algorithm, DigestType, Msg, Signature, Key, Options) 1402 -> Result 1403 when Algorithm :: pk_sign_verify_algs(), 1404 DigestType :: rsa_digest_type() 1405 | dss_digest_type() 1406 | ecdsa_digest_type() 1407 | none, 1408 Msg :: iodata() | {digest,iodata()}, 1409 Signature :: binary(), 1410 Key :: rsa_public() 1411 | dss_public() 1412 | [ecdsa_public() | ecdsa_params()] 1413 | [eddsa_public() | eddsa_params()] 1414 | engine_key_ref(), 1415 Options :: pk_sign_verify_opts(), 1416 Result :: boolean(). 1417 1418verify(Algorithm0, Type0, Data, Signature, Key, Options) -> 1419 {Algorithm, Type} = sign_verify_compatibility(Algorithm0, Type0, Data), 1420 case pkey_verify_nif(Algorithm, Type, Data, Signature, format_pkey(Algorithm, Key), Options) of 1421 notsup -> erlang:error(notsup); 1422 Boolean -> Boolean 1423 end. 1424 1425pkey_verify_nif(_Algorithm, _Type, _Data, _Signature, _Key, _Options) -> ?nif_stub. 1426 1427%% Backwards compatible: 1428sign_verify_compatibility(dss, none, Digest) -> 1429 {sha, {digest, Digest}}; 1430sign_verify_compatibility(Algorithm0, Type0, _Digest) -> 1431 {Algorithm0, Type0}. 1432 1433%%%================================================================ 1434%%% 1435%%% Public/private encrypt/decrypt 1436%%% 1437%%% Only rsa works so far (although ecdsa | dss should do it) 1438%%%================================================================ 1439-type pk_encrypt_decrypt_algs() :: rsa . 1440 1441-type pk_encrypt_decrypt_opts() :: [rsa_opt()] | rsa_compat_opts(). 1442 1443-type rsa_compat_opts() :: [{rsa_pad, rsa_padding()}] 1444 | rsa_padding() . 1445 1446-type rsa_padding() :: rsa_pkcs1_padding 1447 | rsa_pkcs1_oaep_padding 1448 | rsa_sslv23_padding 1449 | rsa_x931_padding 1450 | rsa_no_padding. 1451 1452-type rsa_opt() :: {rsa_padding, rsa_padding()} 1453 | {signature_md, atom()} 1454 | {rsa_mgf1_md, sha} 1455 | {rsa_oaep_label, binary()} 1456 | {rsa_oaep_md, sha} . 1457 1458%%%---- Encrypt with public key 1459 1460-spec public_encrypt(Algorithm, PlainText, PublicKey, Options) -> 1461 CipherText when Algorithm :: pk_encrypt_decrypt_algs(), 1462 PlainText :: binary(), 1463 PublicKey :: rsa_public() | engine_key_ref(), 1464 Options :: pk_encrypt_decrypt_opts(), 1465 CipherText :: binary(). 1466public_encrypt(Algorithm, PlainText, PublicKey, Options) -> 1467 pkey_crypt(Algorithm, PlainText, PublicKey, Options, false, true). 1468 1469%%%---- Decrypt with private key 1470 1471-spec private_decrypt(Algorithm, CipherText, PrivateKey, Options) -> 1472 PlainText when Algorithm :: pk_encrypt_decrypt_algs(), 1473 CipherText :: binary(), 1474 PrivateKey :: rsa_private() | engine_key_ref(), 1475 Options :: pk_encrypt_decrypt_opts(), 1476 PlainText :: binary() . 1477private_decrypt(Algorithm, CipherText, PrivateKey, Options) -> 1478 pkey_crypt(Algorithm, CipherText, PrivateKey, Options, true, false). 1479 1480%%%---- Encrypt with private key 1481 1482-spec private_encrypt(Algorithm, PlainText, PrivateKey, Options) -> 1483 CipherText when Algorithm :: pk_encrypt_decrypt_algs(), 1484 PlainText :: binary(), 1485 PrivateKey :: rsa_private() | engine_key_ref(), 1486 Options :: pk_encrypt_decrypt_opts(), 1487 CipherText :: binary(). 1488private_encrypt(Algorithm, PlainText, PrivateKey, Options) -> 1489 pkey_crypt(Algorithm, PlainText, PrivateKey, Options, true, true). 1490 1491%%%---- Decrypt with public key 1492 1493-spec public_decrypt(Algorithm, CipherText, PublicKey, Options) -> 1494 PlainText when Algorithm :: pk_encrypt_decrypt_algs(), 1495 CipherText :: binary(), 1496 PublicKey :: rsa_public() | engine_key_ref(), 1497 Options :: pk_encrypt_decrypt_opts(), 1498 PlainText :: binary() . 1499public_decrypt(Algorithm, CipherText, PublicKey, Options) -> 1500 pkey_crypt(Algorithm, CipherText, PublicKey, Options, false, false). 1501 1502%%%---- Call the nif, but fix a compatibility issue first 1503 1504%% Backwards compatible (rsa_pad -> rsa_padding is handled by the pkey_crypt_nif): 1505pkey_crypt(rsa, Text, Key, Padding, PubPriv, EncDec) when is_atom(Padding) -> 1506 pkey_crypt(rsa, Text, Key, [{rsa_padding, Padding}], PubPriv, EncDec); 1507 1508pkey_crypt(Alg, Text, Key, Options, PubPriv, EncDec) -> 1509 case pkey_crypt_nif(Alg, Text, format_pkey(Alg,Key), Options, PubPriv, EncDec) of 1510 error when EncDec==true -> erlang:error(encrypt_failed, [Alg, Text, Key, Options]); 1511 error when EncDec==false -> erlang:error(decrypt_failed, [Alg, Text, Key, Options]); 1512 notsup -> erlang:error(notsup); 1513 Out -> Out 1514 end. 1515 1516pkey_crypt_nif(_Algorithm, _In, _Key, _Options, _IsPrivate, _IsEncrypt) -> ?nif_stub. 1517 1518%%%================================================================ 1519%%% 1520%%% 1521%%% 1522%%%================================================================ 1523 1524-spec generate_key(Type, Params) 1525 -> {PublicKey, PrivKeyOut} 1526 when Type :: dh | ecdh | eddh | eddsa | rsa | srp, 1527 PublicKey :: dh_public() | ecdh_public() | rsa_public() | srp_public(), 1528 PrivKeyOut :: dh_private() | ecdh_private() | rsa_private() | {srp_public(),srp_private()}, 1529 Params :: dh_params() | ecdh_params() | eddsa_params() | rsa_params() | srp_gen_params() 1530 . 1531generate_key(Type, Params) -> 1532 generate_key(Type, Params, undefined). 1533 1534-spec generate_key(Type, Params, PrivKeyIn) 1535 -> {PublicKey, PrivKeyOut} 1536 when Type :: dh | ecdh | eddh | eddsa | rsa | srp, 1537 PublicKey :: dh_public() | ecdh_public() | rsa_public() | srp_public(), 1538 PrivKeyIn :: undefined | dh_private() | ecdh_private() | rsa_private() | {srp_public(),srp_private()}, 1539 PrivKeyOut :: dh_private() | ecdh_private() | rsa_private() | {srp_public(),srp_private()}, 1540 Params :: dh_params() | ecdh_params() | eddsa_params() | rsa_params() | srp_comp_params() 1541 . 1542 1543generate_key(dh, DHParameters0, PrivateKey) -> 1544 {DHParameters, Len} = 1545 case DHParameters0 of 1546 [P,G,L] -> {[P,G], L}; 1547 [P,G] -> {[P,G], 0} 1548 end, 1549 dh_generate_key_nif(ensure_int_as_bin(PrivateKey), 1550 map_ensure_int_as_bin(DHParameters), 1551 0, Len); 1552 1553generate_key(srp, {host, [Verifier, Generator, Prime, Version]}, PrivArg) 1554 when is_binary(Verifier), is_binary(Generator), is_binary(Prime), is_atom(Version) -> 1555 Private = case PrivArg of 1556 undefined -> strong_rand_bytes(32); 1557 _ -> ensure_int_as_bin(PrivArg) 1558 end, 1559 host_srp_gen_key(Private, Verifier, Generator, Prime, Version); 1560 1561generate_key(srp, {user, [Generator, Prime, Version]}, PrivateArg) 1562 when is_binary(Generator), is_binary(Prime), is_atom(Version) -> 1563 Private = case PrivateArg of 1564 undefined -> strong_rand_bytes(32); 1565 _ -> PrivateArg 1566 end, 1567 user_srp_gen_key(Private, Generator, Prime); 1568 1569generate_key(rsa, {ModulusSize, PublicExponent}, undefined) -> 1570 case rsa_generate_key_nif(ModulusSize, ensure_int_as_bin(PublicExponent)) of 1571 error -> 1572 erlang:error(computation_failed, 1573 [rsa,{ModulusSize,PublicExponent}]); 1574 Private -> 1575 {lists:sublist(Private, 2), Private} 1576 end; 1577 1578generate_key(eddh, Curve, PrivKey) when Curve == x448 ; 1579 Curve == x25519 -> 1580 evp_generate_key_nif(Curve, ensure_int_as_bin(PrivKey)); 1581generate_key(ecdh, Curve, PrivKey) when Curve == x448 ; 1582 Curve == x25519 -> 1583 %% This was here before the eddh was added as an own Type 1584 evp_generate_key_nif(Curve, ensure_int_as_bin(PrivKey)); 1585generate_key(ecdh, Curve, PrivKey) -> 1586 ec_key_generate(nif_curve_params(Curve), ensure_int_as_bin(PrivKey)); 1587 1588generate_key(eddsa, Curve, PrivKey) when Curve == ed448 ; 1589 Curve == ed25519 -> 1590 evp_generate_key_nif(Curve, ensure_int_as_bin(PrivKey)). 1591 1592evp_generate_key_nif(_Curve, _PrivKey) -> ?nif_stub. 1593 1594 1595-spec compute_key(Type, OthersPublicKey, MyPrivateKey, Params) 1596 -> SharedSecret 1597 when Type :: dh | ecdh | eddh | srp, 1598 SharedSecret :: binary(), 1599 OthersPublicKey :: dh_public() | ecdh_public() | srp_public(), 1600 MyPrivateKey :: dh_private() | ecdh_private() | {srp_public(),srp_private()}, 1601 Params :: dh_params() | ecdh_params() | srp_comp_params() 1602 . 1603 1604compute_key(dh, OthersPublicKey, MyPrivateKey, DHParameters) -> 1605 case dh_compute_key_nif(ensure_int_as_bin(OthersPublicKey), 1606 ensure_int_as_bin(MyPrivateKey), 1607 map_ensure_int_as_bin(DHParameters)) of 1608 error -> erlang:error(computation_failed, 1609 [dh,OthersPublicKey,MyPrivateKey,DHParameters]); 1610 Ret -> Ret 1611 end; 1612 1613compute_key(srp, HostPublic, {UserPublic, UserPrivate}, 1614 {user, [DerivedKey, Prime, Generator, Version | ScramblerArg]}) when 1615 is_binary(Prime), 1616 is_binary(Generator), 1617 is_atom(Version) -> 1618 HostPubBin = ensure_int_as_bin(HostPublic), 1619 Multiplier = srp_multiplier(Version, Generator, Prime), 1620 Scrambler = case ScramblerArg of 1621 [] -> srp_scrambler(Version, ensure_int_as_bin(UserPublic), 1622 HostPubBin, Prime); 1623 [S] -> S 1624 end, 1625 notsup_to_error( 1626 srp_user_secret_nif(ensure_int_as_bin(UserPrivate), Scrambler, HostPubBin, 1627 Multiplier, Generator, DerivedKey, Prime)); 1628 1629compute_key(srp, UserPublic, {HostPublic, HostPrivate}, 1630 {host,[Verifier, Prime, Version | ScramblerArg]}) when 1631 is_binary(Verifier), 1632 is_binary(Prime), 1633 is_atom(Version) -> 1634 UserPubBin = ensure_int_as_bin(UserPublic), 1635 Scrambler = case ScramblerArg of 1636 [] -> srp_scrambler(Version, UserPubBin, ensure_int_as_bin(HostPublic), Prime); 1637 [S] -> S 1638 end, 1639 notsup_to_error( 1640 srp_host_secret_nif(Verifier, ensure_int_as_bin(HostPrivate), Scrambler, 1641 UserPubBin, Prime)); 1642 1643compute_key(ecdh, Others, My, Curve) when Curve == x448 ; 1644 Curve == x25519 -> 1645 evp_compute_key_nif(Curve, ensure_int_as_bin(Others), ensure_int_as_bin(My)); 1646 1647compute_key(eddh, Others, My, Curve) when Curve == x448 ; 1648 Curve == x25519 -> 1649 evp_compute_key_nif(Curve, ensure_int_as_bin(Others), ensure_int_as_bin(My)); 1650 1651compute_key(ecdh, Others, My, Curve) -> 1652 ecdh_compute_key_nif(ensure_int_as_bin(Others), 1653 nif_curve_params(Curve), 1654 ensure_int_as_bin(My)). 1655 1656 1657evp_compute_key_nif(_Curve, _OthersBin, _MyBin) -> ?nif_stub. 1658 1659 1660%%%================================================================ 1661%%% 1662%%% XOR - xor to iolists and return a binary 1663%%% NB doesn't check that they are the same size, just concatenates 1664%%% them and sends them to the driver 1665%%% 1666%%%================================================================ 1667 1668-spec exor(iodata(), iodata()) -> binary(). 1669 1670exor(Bin1, Bin2) -> 1671 Data1 = iolist_to_binary(Bin1), 1672 Data2 = iolist_to_binary(Bin2), 1673 MaxBytes = max_bytes(), 1674 exor(Data1, Data2, erlang:byte_size(Data1), MaxBytes, []). 1675 1676 1677%%%================================================================ 1678%%% 1679%%% Exponentiation modulo 1680%%% 1681%%%================================================================ 1682 1683-spec mod_pow(N, P, M) -> Result when N :: binary() | integer(), 1684 P :: binary() | integer(), 1685 M :: binary() | integer(), 1686 Result :: binary() | error . 1687mod_pow(Base, Exponent, Prime) -> 1688 case mod_exp_nif(ensure_int_as_bin(Base), ensure_int_as_bin(Exponent), ensure_int_as_bin(Prime), 0) of 1689 <<0>> -> error; 1690 R -> R 1691 end. 1692 1693%%%====================================================================== 1694%%% 1695%%% Engine functions 1696%%% 1697%%%====================================================================== 1698 1699%%%---- Refering to keys stored in an engine: 1700-type key_id() :: string() | binary() . 1701-type password() :: string() | binary() . 1702 1703-type engine_key_ref() :: #{engine := engine_ref(), 1704 key_id := key_id(), 1705 password => password(), 1706 term() => term() 1707 }. 1708 1709%%%---- Commands: 1710-type engine_cmnd() :: {unicode:chardata(), unicode:chardata()}. 1711 1712%%---------------------------------------------------------------------- 1713%% Function: engine_get_all_methods/0 1714%%---------------------------------------------------------------------- 1715-type engine_method_type() :: engine_method_rsa | engine_method_dsa | engine_method_dh | 1716 engine_method_rand | engine_method_ecdh | engine_method_ecdsa | 1717 engine_method_ciphers | engine_method_digests | engine_method_store | 1718 engine_method_pkey_meths | engine_method_pkey_asn1_meths | 1719 engine_method_ec. 1720 1721-type engine_ref() :: term(). 1722 1723-spec engine_get_all_methods() -> Result when Result :: [engine_method_type()]. 1724engine_get_all_methods() -> 1725 notsup_to_error(engine_get_all_methods_nif()). 1726 1727%%---------------------------------------------------------------------- 1728%% Function: engine_load/3 1729%%---------------------------------------------------------------------- 1730-spec engine_load(EngineId, PreCmds, PostCmds) -> 1731 Result when EngineId::unicode:chardata(), 1732 PreCmds::[engine_cmnd()], 1733 PostCmds::[engine_cmnd()], 1734 Result :: {ok, Engine::engine_ref()} | {error, Reason::term()}. 1735engine_load(EngineId, PreCmds, PostCmds) when is_list(PreCmds), 1736 is_list(PostCmds) -> 1737 engine_load(EngineId, PreCmds, PostCmds, engine_get_all_methods()). 1738 1739%%---------------------------------------------------------------------- 1740%% Function: engine_load/4 1741%%---------------------------------------------------------------------- 1742-spec engine_load(EngineId, PreCmds, PostCmds, EngineMethods) -> 1743 Result when EngineId::unicode:chardata(), 1744 PreCmds::[engine_cmnd()], 1745 PostCmds::[engine_cmnd()], 1746 EngineMethods::[engine_method_type()], 1747 Result :: {ok, Engine::engine_ref()} | {error, Reason::term()}. 1748engine_load(EngineId, PreCmds, PostCmds, EngineMethods) when is_list(PreCmds), 1749 is_list(PostCmds) -> 1750 try 1751 ok = notsup_to_error(engine_load_dynamic_nif()), 1752 case notsup_to_error(engine_by_id_nif(ensure_bin_chardata(EngineId))) of 1753 {ok, Engine} -> 1754 engine_load_1(Engine, PreCmds, PostCmds, EngineMethods); 1755 {error, Error1} -> 1756 {error, Error1} 1757 end 1758 catch 1759 throw:Error2 -> 1760 Error2 1761 end. 1762 1763engine_load_1(Engine, PreCmds, PostCmds, EngineMethods) -> 1764 try 1765 ok = engine_nif_wrapper(engine_ctrl_cmd_strings_nif(Engine, ensure_bin_cmds(PreCmds), 0)), 1766 ok = engine_nif_wrapper(engine_init_nif(Engine)), 1767 engine_load_2(Engine, PostCmds, EngineMethods), 1768 {ok, Engine} 1769 catch 1770 throw:Error -> 1771 %% The engine couldn't initialise, release the structural reference 1772 ok = engine_free_nif(Engine), 1773 throw(Error); 1774 error:badarg -> 1775 %% For example bad argument list, release the structural reference 1776 ok = engine_free_nif(Engine), 1777 error(badarg) 1778 end. 1779 1780engine_load_2(Engine, PostCmds, EngineMethods) -> 1781 try 1782 ok = engine_nif_wrapper(engine_ctrl_cmd_strings_nif(Engine, ensure_bin_cmds(PostCmds), 0)), 1783 [ok = engine_nif_wrapper(engine_register_nif(Engine, engine_method_atom_to_int(Method))) || 1784 Method <- EngineMethods], 1785 ok 1786 catch 1787 throw:Error -> 1788 %% The engine registration failed, release the functional reference 1789 ok = engine_free_nif(Engine), 1790 throw(Error) 1791 end. 1792 1793%%---------------------------------------------------------------------- 1794%% Function: engine_unload/1 1795%%---------------------------------------------------------------------- 1796-spec engine_unload(Engine) -> Result when Engine :: engine_ref(), 1797 Result :: ok | {error, Reason::term()}. 1798engine_unload(Engine) -> 1799 engine_unload(Engine, engine_get_all_methods()). 1800 1801-spec engine_unload(Engine, EngineMethods) -> Result when Engine :: engine_ref(), 1802 EngineMethods :: [engine_method_type()], 1803 Result :: ok | {error, Reason::term()}. 1804engine_unload(Engine, EngineMethods) -> 1805 try 1806 [ok = engine_nif_wrapper(engine_unregister_nif(Engine, engine_method_atom_to_int(Method))) || 1807 Method <- EngineMethods], 1808 %% Release the reference from engine_by_id_nif 1809 ok = engine_nif_wrapper(engine_free_nif(Engine)) 1810 catch 1811 throw:Error -> 1812 Error 1813 end. 1814 1815%%---------------------------------------------------------------------- 1816%% Function: engine_by_id/1 1817%%---------------------------------------------------------------------- 1818-spec engine_by_id(EngineId) -> Result when EngineId :: unicode:chardata(), 1819 Result :: {ok, Engine::engine_ref()} | {error, Reason::term()} . 1820engine_by_id(EngineId) -> 1821 try 1822 notsup_to_error(engine_by_id_nif(ensure_bin_chardata(EngineId))) 1823 catch 1824 throw:Error -> 1825 Error 1826 end. 1827 1828%%---------------------------------------------------------------------- 1829%% Function: engine_add/1 1830%%---------------------------------------------------------------------- 1831-spec engine_add(Engine) -> Result when Engine :: engine_ref(), 1832 Result :: ok | {error, Reason::term()} . 1833engine_add(Engine) -> 1834 notsup_to_error(engine_add_nif(Engine)). 1835 1836%%---------------------------------------------------------------------- 1837%% Function: engine_remove/1 1838%%---------------------------------------------------------------------- 1839-spec engine_remove(Engine) -> Result when Engine :: engine_ref(), 1840 Result :: ok | {error, Reason::term()} . 1841engine_remove(Engine) -> 1842 notsup_to_error(engine_remove_nif(Engine)). 1843 1844%%---------------------------------------------------------------------- 1845%% Function: engine_get_id/1 1846%%---------------------------------------------------------------------- 1847-spec engine_get_id(Engine) -> EngineId when Engine :: engine_ref(), 1848 EngineId :: unicode:chardata(). 1849engine_get_id(Engine) -> 1850 notsup_to_error(engine_get_id_nif(Engine)). 1851 1852%%---------------------------------------------------------------------- 1853%% Function: engine_get_name/1 1854%%---------------------------------------------------------------------- 1855-spec engine_get_name(Engine) -> EngineName when Engine :: engine_ref(), 1856 EngineName :: unicode:chardata(). 1857engine_get_name(Engine) -> 1858 notsup_to_error(engine_get_name_nif(Engine)). 1859 1860%%---------------------------------------------------------------------- 1861%% Function: engine_list/0 1862%%---------------------------------------------------------------------- 1863-spec engine_list() -> Result when Result :: [EngineId::unicode:chardata()]. 1864engine_list() -> 1865 case notsup_to_error(engine_get_first_nif()) of 1866 {ok, <<>>} -> 1867 []; 1868 {ok, Engine} -> 1869 case notsup_to_error(engine_get_id_nif(Engine)) of 1870 <<>> -> 1871 engine_list(Engine, []); 1872 EngineId -> 1873 engine_list(Engine, [EngineId]) 1874 end 1875 end. 1876 1877engine_list(Engine0, IdList) -> 1878 case notsup_to_error(engine_get_next_nif(Engine0)) of 1879 {ok, <<>>} -> 1880 lists:reverse(IdList); 1881 {ok, Engine1} -> 1882 case notsup_to_error(engine_get_id_nif(Engine1)) of 1883 <<>> -> 1884 engine_list(Engine1, IdList); 1885 EngineId -> 1886 engine_list(Engine1, [EngineId |IdList]) 1887 end 1888 end. 1889 1890%%---------------------------------------------------------------------- 1891%% Function: engine_ctrl_cmd_string/3 1892%%---------------------------------------------------------------------- 1893-spec engine_ctrl_cmd_string(Engine, CmdName, CmdArg) -> 1894 Result when Engine::term(), 1895 CmdName::unicode:chardata(), 1896 CmdArg::unicode:chardata(), 1897 Result :: ok | {error, Reason::term()}. 1898engine_ctrl_cmd_string(Engine, CmdName, CmdArg) -> 1899 engine_ctrl_cmd_string(Engine, CmdName, CmdArg, false). 1900 1901%%---------------------------------------------------------------------- 1902%% Function: engine_ctrl_cmd_string/4 1903%%---------------------------------------------------------------------- 1904-spec engine_ctrl_cmd_string(Engine, CmdName, CmdArg, Optional) -> 1905 Result when Engine::term(), 1906 CmdName::unicode:chardata(), 1907 CmdArg::unicode:chardata(), 1908 Optional::boolean(), 1909 Result :: ok | {error, Reason::term()}. 1910engine_ctrl_cmd_string(Engine, CmdName, CmdArg, Optional) -> 1911 case engine_ctrl_cmd_strings_nif(Engine, 1912 ensure_bin_cmds([{CmdName, CmdArg}]), 1913 bool_to_int(Optional)) of 1914 ok -> 1915 ok; 1916 notsup -> 1917 erlang:error(notsup); 1918 {error, Error} -> 1919 {error, Error} 1920 end. 1921 1922%%---------------------------------------------------------------------- 1923%% Function: ensure_engine_loaded/2 1924%% Special version of load that only uses dynamic engine to load 1925%%---------------------------------------------------------------------- 1926-spec ensure_engine_loaded(EngineId, LibPath) -> 1927 Result when EngineId :: unicode:chardata(), 1928 LibPath :: unicode:chardata(), 1929 Result :: {ok, Engine::engine_ref()} | {error, Reason::term()}. 1930ensure_engine_loaded(EngineId, LibPath) -> 1931 ensure_engine_loaded(EngineId, LibPath, engine_get_all_methods()). 1932 1933%%---------------------------------------------------------------------- 1934%% Function: ensure_engine_loaded/3 1935%% Special version of load that only uses dynamic engine to load 1936%%---------------------------------------------------------------------- 1937-spec ensure_engine_loaded(EngineId, LibPath, EngineMethods) -> 1938 Result when EngineId :: unicode:chardata(), 1939 LibPath :: unicode:chardata(), 1940 EngineMethods :: [engine_method_type()], 1941 Result :: {ok, Engine::engine_ref()} | {error, Reason::term()}. 1942ensure_engine_loaded(EngineId, LibPath, EngineMethods) -> 1943 try 1944 List = crypto:engine_list(), 1945 case lists:member(EngineId, List) of 1946 true -> 1947 notsup_to_error(engine_by_id_nif(ensure_bin_chardata(EngineId))); 1948 false -> 1949 ok = notsup_to_error(engine_load_dynamic_nif()), 1950 case notsup_to_error(engine_by_id_nif(ensure_bin_chardata(<<"dynamic">>))) of 1951 {ok, Engine} -> 1952 PreCommands = [{<<"SO_PATH">>, ensure_bin_chardata(LibPath)}, 1953 {<<"ID">>, ensure_bin_chardata(EngineId)}, 1954 <<"LOAD">>], 1955 ensure_engine_loaded_1(Engine, PreCommands, EngineMethods); 1956 {error, Error1} -> 1957 {error, Error1} 1958 end 1959 end 1960 catch 1961 throw:Error2 -> 1962 Error2 1963 end. 1964 1965ensure_engine_loaded_1(Engine, PreCmds, Methods) -> 1966 try 1967 ok = engine_nif_wrapper(engine_ctrl_cmd_strings_nif(Engine, ensure_bin_cmds(PreCmds), 0)), 1968 ok = engine_nif_wrapper(engine_add_nif(Engine)), 1969 ok = engine_nif_wrapper(engine_init_nif(Engine)), 1970 ensure_engine_loaded_2(Engine, Methods), 1971 {ok, Engine} 1972 catch 1973 throw:Error -> 1974 %% The engine couldn't initialise, release the structural reference 1975 ok = engine_free_nif(Engine), 1976 throw(Error) 1977 end. 1978 1979ensure_engine_loaded_2(Engine, Methods) -> 1980 try 1981 [ok = engine_nif_wrapper(engine_register_nif(Engine, engine_method_atom_to_int(Method))) || 1982 Method <- Methods], 1983 ok 1984 catch 1985 throw:Error -> 1986 %% The engine registration failed, release the functional reference 1987 ok = engine_free_nif(Engine), 1988 throw(Error) 1989 end. 1990%%---------------------------------------------------------------------- 1991%% Function: ensure_engine_unloaded/1 1992%%---------------------------------------------------------------------- 1993-spec ensure_engine_unloaded(Engine) -> Result when Engine :: engine_ref(), 1994 Result :: ok | {error, Reason::term()}. 1995ensure_engine_unloaded(Engine) -> 1996 ensure_engine_unloaded(Engine, engine_get_all_methods()). 1997 1998%%---------------------------------------------------------------------- 1999%% Function: ensure_engine_unloaded/2 2000%%---------------------------------------------------------------------- 2001-spec ensure_engine_unloaded(Engine, EngineMethods) -> 2002 Result when Engine :: engine_ref(), 2003 EngineMethods :: [engine_method_type()], 2004 Result :: ok | {error, Reason::term()}. 2005ensure_engine_unloaded(Engine, EngineMethods) -> 2006 List = crypto:engine_list(), 2007 EngineId = crypto:engine_get_id(Engine), 2008 case lists:member(EngineId, List) of 2009 true -> 2010 case engine_remove(Engine) of 2011 ok -> 2012 engine_unload(Engine, EngineMethods); 2013 {error, Error} -> 2014 {error, Error} 2015 end; 2016 false -> 2017 engine_unload(Engine, EngineMethods) 2018 end. 2019 2020 2021%%-------------------------------------------------------------------- 2022%%% On load 2023%%-------------------------------------------------------------------- 2024on_load() -> 2025 LibBaseName = "crypto", 2026 PrivDir = code:priv_dir(crypto), 2027 LibName = case erlang:system_info(build_type) of 2028 opt -> 2029 LibBaseName; 2030 Type -> 2031 LibTypeName = LibBaseName ++ "." ++ atom_to_list(Type), 2032 case (filelib:wildcard( 2033 filename:join( 2034 [PrivDir, 2035 "lib", 2036 LibTypeName ++ "*"])) /= []) orelse 2037 (filelib:wildcard( 2038 filename:join( 2039 [PrivDir, 2040 "lib", 2041 erlang:system_info(system_architecture), 2042 LibTypeName ++ "*"])) /= []) of 2043 true -> LibTypeName; 2044 false -> LibBaseName 2045 end 2046 end, 2047 Lib = filename:join([PrivDir, "lib", LibName]), 2048 LibBin = path2bin(Lib), 2049 FipsMode = application:get_env(crypto, fips_mode, false) == true, 2050 Status = case erlang:load_nif(Lib, {?CRYPTO_NIF_VSN,LibBin,FipsMode}) of 2051 ok -> ok; 2052 {error, {load_failed, _}}=Error1 -> 2053 ArchLibDir = 2054 filename:join([PrivDir, "lib", 2055 erlang:system_info(system_architecture)]), 2056 Candidate = 2057 filelib:wildcard(filename:join([ArchLibDir,LibName ++ "*" ]),erl_prim_loader), 2058 case Candidate of 2059 [] -> Error1; 2060 _ -> 2061 ArchLib = filename:join([ArchLibDir, LibName]), 2062 ArchBin = path2bin(ArchLib), 2063 erlang:load_nif(ArchLib, {?CRYPTO_NIF_VSN,ArchBin,FipsMode}) 2064 end; 2065 Error1 -> Error1 2066 end, 2067 case Status of 2068 ok -> ok; 2069 {error, {E, Str}} -> 2070 Fmt = "Unable to load crypto library. Failed with error:~n\"~p, ~s\"~n~s", 2071 Extra = case E of 2072 load_failed -> 2073 "OpenSSL might not be installed on this system.\n"; 2074 _ -> "" 2075 end, 2076 error_logger:error_msg(Fmt, [E,Str,Extra]), 2077 Status 2078 end. 2079 2080path2bin(Path) when is_list(Path) -> 2081 Encoding = file:native_name_encoding(), 2082 case unicode:characters_to_binary(Path,Encoding,Encoding) of 2083 Bin when is_binary(Bin) -> 2084 Bin 2085 end. 2086 2087%%%================================================================ 2088%%%================================================================ 2089%%% 2090%%% Internal functions 2091%%% 2092%%%================================================================ 2093 2094max_bytes() -> 2095 ?MAX_BYTES_TO_NIF. 2096 2097notsup_to_error(notsup) -> 2098 erlang:error(notsup); 2099notsup_to_error(Other) -> 2100 Other. 2101 2102%% HASH -------------------------------------------------------------------- 2103hash(Hash, Data, Size, Max) when Size =< Max -> 2104 notsup_to_error(hash_nif(Hash, Data)); 2105hash(Hash, Data, Size, Max) -> 2106 State0 = hash_init(Hash), 2107 State1 = hash_update(State0, Data, Size, Max), 2108 hash_final(State1). 2109 2110hash_update(State, Data, Size, MaxBytes) when Size =< MaxBytes -> 2111 notsup_to_error(hash_update_nif(State, Data)); 2112hash_update(State0, Data, _, MaxBytes) -> 2113 <<Increment:MaxBytes/binary, Rest/binary>> = Data, 2114 State = notsup_to_error(hash_update_nif(State0, Increment)), 2115 hash_update(State, Rest, erlang:byte_size(Rest), MaxBytes). 2116 2117hash_info_nif(_Hash) -> ?nif_stub. 2118hash_nif(_Hash, _Data) -> ?nif_stub. 2119hash_init_nif(_Hash) -> ?nif_stub. 2120hash_update_nif(_State, _Data) -> ?nif_stub. 2121hash_final_nif(_State) -> ?nif_stub. 2122 2123%%%================================================================ 2124 2125%% Secure remote password ------------------------------------------------------------------- 2126 2127user_srp_gen_key(Private, Generator, Prime) -> 2128 %% Ensure the SRP algorithm is disabled in FIPS mode 2129 case info_fips() of 2130 enabled -> erlang:error(notsup); 2131 _ -> ok 2132 end, 2133 case mod_pow(Generator, Private, Prime) of 2134 error -> 2135 error; 2136 Public -> 2137 {Public, Private} 2138 end. 2139 2140host_srp_gen_key(Private, Verifier, Generator, Prime, Version) -> 2141 Multiplier = srp_multiplier(Version, Generator, Prime), 2142 case srp_value_B_nif(Multiplier, Verifier, Generator, Private, Prime) of 2143 error -> 2144 error; 2145 notsup -> 2146 erlang:error(notsup); 2147 Public -> 2148 {Public, Private} 2149 end. 2150 2151srp_multiplier('6a', Generator, Prime) -> 2152 %% k = SHA1(N | PAD(g)) from http://srp.stanford.edu/design.html 2153 C0 = hash_init(sha), 2154 C1 = hash_update(C0, Prime), 2155 C2 = hash_update(C1, srp_pad_to(erlang:byte_size(Prime), Generator)), 2156 hash_final(C2); 2157srp_multiplier('6', _, _) -> 2158 <<3/integer>>; 2159srp_multiplier('3', _, _) -> 2160 <<1/integer>>. 2161 2162srp_scrambler(Version, UserPublic, HostPublic, Prime) when Version == '6'; Version == '6a'-> 2163 %% SHA1(PAD(A) | PAD(B)) from http://srp.stanford.edu/design.html 2164 PadLength = erlang:byte_size(Prime), 2165 C0 = hash_init(sha), 2166 C1 = hash_update(C0, srp_pad_to(PadLength, UserPublic)), 2167 C2 = hash_update(C1, srp_pad_to(PadLength, HostPublic)), 2168 hash_final(C2); 2169srp_scrambler('3', _, HostPublic, _Prime) -> 2170 %% The parameter u is a 32-bit unsigned integer which takes its value 2171 %% from the first 32 bits of the SHA1 hash of B, MSB first. 2172 <<U:32/bits, _/binary>> = hash(sha, HostPublic), 2173 U. 2174 2175srp_pad_length(Width, Length) -> 2176 (Width - Length rem Width) rem Width. 2177 2178srp_pad_to(Width, Binary) -> 2179 case srp_pad_length(Width, size(Binary)) of 2180 0 -> Binary; 2181 N -> << 0:(N*8), Binary/binary>> 2182 end. 2183 2184srp_host_secret_nif(_Verifier, _B, _U, _A, _Prime) -> ?nif_stub. 2185 2186srp_user_secret_nif(_A, _U, _B, _Multiplier, _Generator, _Exponent, _Prime) -> ?nif_stub. 2187 2188srp_value_B_nif(_Multiplier, _Verifier, _Generator, _Exponent, _Prime) -> ?nif_stub. 2189 2190 2191%% Public Keys -------------------------------------------------------------------- 2192%% RSA Rivest-Shamir-Adleman functions 2193%% 2194 2195rsa_generate_key_nif(_Bits, _Exp) -> ?nif_stub. 2196 2197%% DH Diffie-Hellman functions 2198%% 2199 2200%% DHParameters = [P (Prime)= mpint(), G(Generator) = mpint()] 2201%% PrivKey = mpint() 2202dh_generate_key_nif(_PrivateKey, _DHParameters, _Mpint, _Length) -> ?nif_stub. 2203 2204%% DHParameters = [P (Prime)= mpint(), G(Generator) = mpint()] 2205%% MyPrivKey, OthersPublicKey = mpint() 2206dh_compute_key_nif(_OthersPublicKey, _MyPrivateKey, _DHParameters) -> ?nif_stub. 2207 2208ec_key_generate(_Curve, _Key) -> ?nif_stub. 2209 2210ecdh_compute_key_nif(_Others, _Curve, _My) -> ?nif_stub. 2211 2212-spec ec_curves() -> [EllipticCurve] when EllipticCurve :: ec_named_curve() 2213 | edwards_curve_dh() 2214 | edwards_curve_ed() . 2215 2216ec_curves() -> 2217 crypto_ec_curves:curves(). 2218 2219-spec ec_curve(CurveName) -> ExplicitCurve when CurveName :: ec_named_curve(), 2220 ExplicitCurve :: ec_explicit_curve() . 2221ec_curve(X) -> 2222 crypto_ec_curves:curve(X). 2223 2224 2225-spec privkey_to_pubkey(Type, EnginePrivateKeyRef) -> PublicKey when Type :: rsa | dss, 2226 EnginePrivateKeyRef :: engine_key_ref(), 2227 PublicKey :: rsa_public() | dss_public() . 2228privkey_to_pubkey(Alg, EngineMap) when Alg == rsa; Alg == dss; Alg == ecdsa -> 2229 try privkey_to_pubkey_nif(Alg, format_pkey(Alg,EngineMap)) 2230 of 2231 [_|_]=L -> map_ensure_bin_as_int(L); 2232 X -> X 2233 catch 2234 error:badarg when Alg==ecdsa -> 2235 {error, notsup}; 2236 error:badarg -> 2237 {error, not_found}; 2238 error:notsup -> 2239 {error, notsup} 2240 end. 2241 2242privkey_to_pubkey_nif(_Alg, _EngineMap) -> ?nif_stub. 2243 2244 2245%% 2246%% EC 2247%% 2248 2249term_to_nif_prime({prime_field, Prime}) -> 2250 {prime_field, ensure_int_as_bin(Prime)}; 2251term_to_nif_prime(PrimeField) -> 2252 PrimeField. 2253 2254term_to_nif_curve({A, B, Seed}) -> 2255 {ensure_int_as_bin(A), ensure_int_as_bin(B), Seed}. 2256 2257nif_curve_params({PrimeField, Curve, BasePoint, Order, CoFactor}) -> 2258 {term_to_nif_prime(PrimeField), 2259 term_to_nif_curve(Curve), 2260 ensure_int_as_bin(BasePoint), 2261 ensure_int_as_bin(Order), 2262 ensure_int_as_bin(CoFactor)}; 2263nif_curve_params(Curve) when is_atom(Curve) -> 2264 %% named curve 2265 case Curve of 2266 x448 -> {evp,Curve}; 2267 x25519 -> {evp,Curve}; 2268 _ -> crypto_ec_curves:curve(Curve) 2269 end. 2270 2271 2272%% MISC -------------------------------------------------------------------- 2273 2274exor(Data1, Data2, Size, MaxByts, []) when Size =< MaxByts -> 2275 do_exor(Data1, Data2); 2276exor(Data1, Data2, Size, MaxByts, Acc) when Size =< MaxByts -> 2277 Result = do_exor(Data1, Data2), 2278 list_to_binary(lists:reverse([Result | Acc])); 2279exor(Data1, Data2, _Size, MaxByts, Acc) -> 2280 <<Increment1:MaxByts/binary, Rest1/binary>> = Data1, 2281 <<Increment2:MaxByts/binary, Rest2/binary>> = Data2, 2282 Result = do_exor(Increment1, Increment2), 2283 exor(Rest1, Rest2, erlang:byte_size(Rest1), MaxByts, [Result | Acc]). 2284 2285do_exor(_A, _B) -> ?nif_stub. 2286 2287hash_algorithms() -> ?nif_stub. 2288pubkey_algorithms() -> ?nif_stub. 2289cipher_algorithms() -> ?nif_stub. 2290mac_algorithms() -> ?nif_stub. 2291curve_algorithms() -> ?nif_stub. 2292rsa_opts_algorithms() -> ?nif_stub. 2293 2294 2295int_to_bin(X) when X < 0 -> int_to_bin_neg(X, []); 2296int_to_bin(X) -> int_to_bin_pos(X, []). 2297 2298int_to_bin_pos(0,Ds=[_|_]) -> 2299 list_to_binary(Ds); 2300int_to_bin_pos(X,Ds) -> 2301 int_to_bin_pos(X bsr 8, [(X band 255)|Ds]). 2302 2303int_to_bin_neg(-1, Ds=[MSB|_]) when MSB >= 16#80 -> 2304 list_to_binary(Ds); 2305int_to_bin_neg(X,Ds) -> 2306 int_to_bin_neg(X bsr 8, [(X band 255)|Ds]). 2307 2308-spec bytes_to_integer(binary()) -> integer() . 2309bytes_to_integer(Bin) -> 2310 bin_to_int(Bin). 2311 2312bin_to_int(Bin) when is_binary(Bin) -> 2313 Bits = bit_size(Bin), 2314 <<Integer:Bits/integer>> = Bin, 2315 Integer; 2316bin_to_int(undefined) -> 2317 undefined. 2318 2319map_ensure_int_as_bin([H|_]=List) when is_integer(H) -> 2320 lists:map(fun(E) -> int_to_bin(E) end, List); 2321map_ensure_int_as_bin(List) -> 2322 List. 2323 2324ensure_int_as_bin(Int) when is_integer(Int) -> 2325 int_to_bin(Int); 2326ensure_int_as_bin(Bin) -> 2327 Bin. 2328 2329map_ensure_bin_as_int(List) when is_list(List) -> 2330 lists:map(fun ensure_bin_as_int/1, List). 2331 2332ensure_bin_as_int(Bin) when is_binary(Bin) -> 2333 bin_to_int(Bin); 2334ensure_bin_as_int(E) -> 2335 E. 2336 2337format_pkey(_Alg, #{engine:=_, key_id:=T}=M) when is_binary(T) -> format_pwd(M); 2338format_pkey(_Alg, #{engine:=_, key_id:=T}=M) when is_list(T) -> format_pwd(M#{key_id:=list_to_binary(T)}); 2339format_pkey(_Alg, #{engine:=_ }=M) -> error({bad_key_id, M}); 2340format_pkey(_Alg, #{}=M) -> error({bad_engine_map, M}); 2341%%% 2342format_pkey(rsa, Key) -> 2343 map_ensure_int_as_bin(Key); 2344format_pkey(ecdsa, [Key, Curve]) -> 2345 {nif_curve_params(Curve), ensure_int_as_bin(Key)}; 2346format_pkey(eddsa, [PubKey, Curve]) when Curve == ed25519; 2347 Curve == ed448 -> 2348 [ensure_int_as_bin(PubKey), Curve]; 2349format_pkey(dss, Key) -> 2350 map_ensure_int_as_bin(Key); 2351format_pkey(_, Key) -> 2352 Key. 2353 2354format_pwd(#{password := Pwd}=M) when is_list(Pwd) -> M#{password := list_to_binary(Pwd)}; 2355format_pwd(M) -> M. 2356 2357%%-------------------------------------------------------------------- 2358%% 2359 2360%% large integer in a binary with 32bit length 2361%% MP representaion (SSH2) 2362mpint(X) when X < 0 -> mpint_neg(X); 2363mpint(X) -> mpint_pos(X). 2364 2365-define(UINT32(X), X:32/unsigned-big-integer). 2366 2367 2368mpint_neg(X) -> 2369 Bin = int_to_bin_neg(X, []), 2370 Sz = byte_size(Bin), 2371 <<?UINT32(Sz), Bin/binary>>. 2372 2373mpint_pos(X) -> 2374 Bin = int_to_bin_pos(X, []), 2375 <<MSB,_/binary>> = Bin, 2376 Sz = byte_size(Bin), 2377 if MSB band 16#80 == 16#80 -> 2378 <<?UINT32((Sz+1)), 0, Bin/binary>>; 2379 true -> 2380 <<?UINT32(Sz), Bin/binary>> 2381 end. 2382 2383%% int from integer in a binary with 32bit length 2384erlint(<<MPIntSize:32/integer,MPIntValue/binary>>) -> 2385 Bits= MPIntSize * 8, 2386 <<Integer:Bits/integer>> = MPIntValue, 2387 Integer. 2388 2389%% 2390%% mod_exp - utility for rsa generation and SRP 2391%% 2392mod_exp_nif(_Base,_Exp,_Mod,_bin_hdr) -> ?nif_stub. 2393 2394%%%---------------------------------------------------------------- 2395%% 9470495 == V(0,9,8,zh). 2396%% 268435615 == V(1,0,0,i). 2397%% 268439663 == V(1,0,1,f). 2398 2399packed_openssl_version(MAJ, MIN, FIX, P0) -> 2400 %% crypto.c 2401 P1 = atom_to_list(P0), 2402 P = lists:sum([C-$a||C<-P1]), 2403 ((((((((MAJ bsl 8) bor MIN) bsl 8 ) bor FIX) bsl 8) bor (P+1)) bsl 4) bor 16#f). 2404 2405%%-------------------------------------------------------------------- 2406%% Engine nifs 2407engine_by_id_nif(_EngineId) -> ?nif_stub. 2408engine_init_nif(_Engine) -> ?nif_stub. 2409engine_free_nif(_Engine) -> ?nif_stub. 2410engine_load_dynamic_nif() -> ?nif_stub. 2411engine_ctrl_cmd_strings_nif(_Engine, _Cmds, _Optional) -> ?nif_stub. 2412engine_add_nif(_Engine) -> ?nif_stub. 2413engine_remove_nif(_Engine) -> ?nif_stub. 2414engine_register_nif(_Engine, _EngineMethod) -> ?nif_stub. 2415engine_unregister_nif(_Engine, _EngineMethod) -> ?nif_stub. 2416engine_get_first_nif() -> ?nif_stub. 2417engine_get_next_nif(_Engine) -> ?nif_stub. 2418engine_get_id_nif(_Engine) -> ?nif_stub. 2419engine_get_name_nif(_Engine) -> ?nif_stub. 2420engine_get_all_methods_nif() -> ?nif_stub. 2421 2422%%-------------------------------------------------------------------- 2423%% Engine internals 2424engine_nif_wrapper(ok) -> 2425 ok; 2426engine_nif_wrapper(notsup) -> 2427 erlang:error(notsup); 2428engine_nif_wrapper({error, Error}) -> 2429 throw({error, Error}). 2430 2431ensure_bin_chardata(CharData) when is_binary(CharData) -> 2432 CharData; 2433ensure_bin_chardata(CharData) -> 2434 unicode:characters_to_binary(CharData). 2435 2436ensure_bin_cmds(CMDs) -> 2437 ensure_bin_cmds(CMDs, []). 2438 2439ensure_bin_cmds([], Acc) -> 2440 lists:reverse(Acc); 2441ensure_bin_cmds([{Key, Value} |CMDs], Acc) -> 2442 ensure_bin_cmds(CMDs, [{ensure_bin_chardata(Key), ensure_bin_chardata(Value)} | Acc]); 2443ensure_bin_cmds([Key | CMDs], Acc) -> 2444 ensure_bin_cmds(CMDs, [{ensure_bin_chardata(Key), <<"">>} | Acc]). 2445 2446engine_methods_convert_to_bitmask([], BitMask) -> 2447 BitMask; 2448engine_methods_convert_to_bitmask(engine_method_all, _BitMask) -> 2449 16#FFFF; 2450engine_methods_convert_to_bitmask(engine_method_none, _BitMask) -> 2451 16#0000; 2452engine_methods_convert_to_bitmask([M |Ms], BitMask) -> 2453 engine_methods_convert_to_bitmask(Ms, BitMask bor engine_method_atom_to_int(M)). 2454 2455bool_to_int(true) -> 1; 2456bool_to_int(false) -> 0. 2457 2458engine_method_atom_to_int(engine_method_rsa) -> 16#0001; 2459engine_method_atom_to_int(engine_method_dsa) -> 16#0002; 2460engine_method_atom_to_int(engine_method_dh) -> 16#0004; 2461engine_method_atom_to_int(engine_method_rand) -> 16#0008; 2462engine_method_atom_to_int(engine_method_ecdh) -> 16#0010; 2463engine_method_atom_to_int(engine_method_ecdsa) -> 16#0020; 2464engine_method_atom_to_int(engine_method_ciphers) -> 16#0040; 2465engine_method_atom_to_int(engine_method_digests) -> 16#0080; 2466engine_method_atom_to_int(engine_method_store) -> 16#0100; 2467engine_method_atom_to_int(engine_method_pkey_meths) -> 16#0200; 2468engine_method_atom_to_int(engine_method_pkey_asn1_meths) -> 16#0400; 2469engine_method_atom_to_int(engine_method_ec) -> 16#0800; 2470engine_method_atom_to_int(X) -> 2471 erlang:error(badarg, [X]). 2472 2473get_test_engine() -> 2474 Type = erlang:system_info(system_architecture), 2475 LibDir = filename:join([code:priv_dir(crypto), "lib"]), 2476 ArchDir = filename:join([LibDir, Type]), 2477 case filelib:is_dir(ArchDir) of 2478 true -> check_otp_test_engine(ArchDir); 2479 false -> check_otp_test_engine(LibDir) 2480 end. 2481 2482check_otp_test_engine(LibDir) -> 2483 case choose_otp_test_engine(LibDir) of 2484 false -> 2485 {error, notexist}; 2486 LibName -> 2487 LibPath = filename:join(LibDir,LibName), 2488 case filelib:is_file(LibPath) of 2489 true -> 2490 {ok, unicode:characters_to_binary(LibPath)}; 2491 false -> 2492 {error, notexist} 2493 end 2494 end. 2495 2496 2497choose_otp_test_engine(LibDir) -> 2498 LibNames = filelib:wildcard("otp_test_engine.*", LibDir), 2499 Type = atom_to_list(erlang:system_info(build_type)), 2500 choose_otp_test_engine(LibNames, Type, false). 2501 2502choose_otp_test_engine([LibName | T], Type, Acc) -> 2503 case string:lexemes(LibName, ".") of 2504 [_, Type, _SO] -> 2505 LibName; %% Choose typed if exists (valgrind,asan) 2506 [_, _SO] -> 2507 %% Fallback on typeless (opt) 2508 choose_otp_test_engine(T, Type, LibName); 2509 _ -> 2510 choose_otp_test_engine(T, Type, Acc) 2511 end; 2512choose_otp_test_engine([], _, Acc) -> 2513 Acc. 2514