summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgregor herrmann <gregoa@debian.org>2018-04-09 21:21:20 +0200
committergregor herrmann <gregoa@debian.org>2018-04-09 21:21:20 +0200
commitfa5f52b7d5e821591e6c6a2f96f8abb644888b38 (patch)
tree8aa5611ba5ae98c26b4abb31d5928c82e4a194bf
parent5b7253046b660592f2e7db7afd2857c8ac517621 (diff)
parente8a8ed0e6467701e2e2737fa23c99724c8370036 (diff)
New upstream version 0.059
-rw-r--r--Changes15
-rw-r--r--CryptX.xs742
-rw-r--r--MANIFEST43
-rw-r--r--META.json2
-rw-r--r--META.yml2
-rw-r--r--Makefile.PL120
-rw-r--r--README.md11
-rw-r--r--inc/CryptX_AuthEnc_CCM.xs.inc127
-rw-r--r--inc/CryptX_AuthEnc_ChaCha20Poly1305.xs.inc100
-rw-r--r--inc/CryptX_AuthEnc_EAX.xs.inc99
-rw-r--r--inc/CryptX_AuthEnc_GCM.xs.inc104
-rw-r--r--inc/CryptX_AuthEnc_OCB.xs.inc108
-rw-r--r--inc/CryptX_BigInt_LTM.xs.inc1
-rw-r--r--inc/CryptX_Checksum_Adler32.xs.inc64
-rw-r--r--inc/CryptX_Checksum_CRC32.xs.inc64
-rw-r--r--inc/CryptX_Cipher.xs.inc170
-rw-r--r--inc/CryptX_Digest.xs.inc180
-rw-r--r--inc/CryptX_Digest_SHAKE.xs.inc25
-rw-r--r--inc/CryptX_KeyDerivation.xs.inc218
-rw-r--r--inc/CryptX_Mac_BLAKE2b.xs.inc155
-rw-r--r--inc/CryptX_Mac_BLAKE2s.xs.inc155
-rw-r--r--inc/CryptX_Mac_F9.xs.inc158
-rw-r--r--inc/CryptX_Mac_HMAC.xs.inc158
-rw-r--r--inc/CryptX_Mac_OMAC.xs.inc158
-rw-r--r--inc/CryptX_Mac_PMAC.xs.inc158
-rw-r--r--inc/CryptX_Mac_Pelican.xs.inc155
-rw-r--r--inc/CryptX_Mac_Poly1305.xs.inc154
-rw-r--r--inc/CryptX_Mac_XCBC.xs.inc158
-rw-r--r--inc/CryptX_Mode_CBC.xs.inc387
-rw-r--r--inc/CryptX_Mode_CFB.xs.inc76
-rw-r--r--inc/CryptX_Mode_CTR.xs.inc76
-rw-r--r--inc/CryptX_Mode_ECB.xs.inc387
-rw-r--r--inc/CryptX_Mode_OFB.xs.inc76
-rw-r--r--inc/CryptX_PK_DH.xs.inc6
-rw-r--r--inc/CryptX_PK_DSA.xs.inc56
-rw-r--r--inc/CryptX_PK_ECC.xs.inc237
-rw-r--r--inc/CryptX_PK_RSA.xs.inc69
-rw-r--r--inc/CryptX_PRNG.xs.inc118
-rw-r--r--inc/CryptX_Stream_ChaCha.xs.inc41
-rw-r--r--inc/CryptX_Stream_RC4.xs.inc37
-rw-r--r--inc/CryptX_Stream_Rabbit.xs.inc39
-rw-r--r--inc/CryptX_Stream_Salsa20.xs.inc39
-rw-r--r--inc/CryptX_Stream_Sober128.xs.inc39
-rw-r--r--inc/CryptX_Stream_Sosemanuk.xs.inc41
-rw-r--r--lib/Crypt/AuthEnc.pm4
-rw-r--r--lib/Crypt/AuthEnc/CCM.pm50
-rw-r--r--lib/Crypt/AuthEnc/ChaCha20Poly1305.pm38
-rw-r--r--lib/Crypt/AuthEnc/EAX.pm53
-rw-r--r--lib/Crypt/AuthEnc/GCM.pm48
-rw-r--r--lib/Crypt/AuthEnc/OCB.pm44
-rw-r--r--lib/Crypt/Checksum.pm220
-rw-r--r--lib/Crypt/Checksum/Adler32.pm129
-rw-r--r--lib/Crypt/Checksum/CRC32.pm129
-rw-r--r--lib/Crypt/Cipher.pm86
-rw-r--r--lib/Crypt/Cipher/AES.pm15
-rw-r--r--lib/Crypt/Cipher/Anubis.pm15
-rw-r--r--lib/Crypt/Cipher/Blowfish.pm15
-rw-r--r--lib/Crypt/Cipher/CAST5.pm15
-rw-r--r--lib/Crypt/Cipher/Camellia.pm15
-rw-r--r--lib/Crypt/Cipher/DES.pm15
-rw-r--r--lib/Crypt/Cipher/DES_EDE.pm15
-rw-r--r--lib/Crypt/Cipher/IDEA.pm15
-rw-r--r--lib/Crypt/Cipher/KASUMI.pm15
-rw-r--r--lib/Crypt/Cipher/Khazad.pm15
-rw-r--r--lib/Crypt/Cipher/MULTI2.pm15
-rw-r--r--lib/Crypt/Cipher/Noekeon.pm15
-rw-r--r--lib/Crypt/Cipher/RC2.pm15
-rw-r--r--lib/Crypt/Cipher/RC5.pm15
-rw-r--r--lib/Crypt/Cipher/RC6.pm15
-rw-r--r--lib/Crypt/Cipher/SAFERP.pm15
-rw-r--r--lib/Crypt/Cipher/SAFER_K128.pm15
-rw-r--r--lib/Crypt/Cipher/SAFER_K64.pm15
-rw-r--r--lib/Crypt/Cipher/SAFER_SK128.pm15
-rw-r--r--lib/Crypt/Cipher/SAFER_SK64.pm15
-rw-r--r--lib/Crypt/Cipher/SEED.pm15
-rw-r--r--lib/Crypt/Cipher/Serpent.pm15
-rw-r--r--lib/Crypt/Cipher/Skipjack.pm15
-rw-r--r--lib/Crypt/Cipher/Twofish.pm15
-rw-r--r--lib/Crypt/Cipher/XTEA.pm15
-rw-r--r--lib/Crypt/Digest.pm67
-rw-r--r--lib/Crypt/Digest/BLAKE2b_160.pm26
-rw-r--r--lib/Crypt/Digest/BLAKE2b_256.pm26
-rw-r--r--lib/Crypt/Digest/BLAKE2b_384.pm26
-rw-r--r--lib/Crypt/Digest/BLAKE2b_512.pm26
-rw-r--r--lib/Crypt/Digest/BLAKE2s_128.pm26
-rw-r--r--lib/Crypt/Digest/BLAKE2s_160.pm26
-rw-r--r--lib/Crypt/Digest/BLAKE2s_224.pm26
-rw-r--r--lib/Crypt/Digest/BLAKE2s_256.pm26
-rw-r--r--lib/Crypt/Digest/CHAES.pm26
-rw-r--r--lib/Crypt/Digest/Keccak224.pm223
-rw-r--r--lib/Crypt/Digest/Keccak256.pm223
-rw-r--r--lib/Crypt/Digest/Keccak384.pm223
-rw-r--r--lib/Crypt/Digest/Keccak512.pm223
-rw-r--r--lib/Crypt/Digest/MD2.pm26
-rw-r--r--lib/Crypt/Digest/MD4.pm26
-rw-r--r--lib/Crypt/Digest/MD5.pm26
-rw-r--r--lib/Crypt/Digest/RIPEMD128.pm26
-rw-r--r--lib/Crypt/Digest/RIPEMD160.pm26
-rw-r--r--lib/Crypt/Digest/RIPEMD256.pm26
-rw-r--r--lib/Crypt/Digest/RIPEMD320.pm26
-rw-r--r--lib/Crypt/Digest/SHA1.pm26
-rw-r--r--lib/Crypt/Digest/SHA224.pm26
-rw-r--r--lib/Crypt/Digest/SHA256.pm26
-rw-r--r--lib/Crypt/Digest/SHA384.pm26
-rw-r--r--lib/Crypt/Digest/SHA3_224.pm26
-rw-r--r--lib/Crypt/Digest/SHA3_256.pm26
-rw-r--r--lib/Crypt/Digest/SHA3_384.pm26
-rw-r--r--lib/Crypt/Digest/SHA3_512.pm26
-rw-r--r--lib/Crypt/Digest/SHA512.pm26
-rw-r--r--lib/Crypt/Digest/SHA512_224.pm26
-rw-r--r--lib/Crypt/Digest/SHA512_256.pm26
-rw-r--r--lib/Crypt/Digest/SHAKE.pm4
-rw-r--r--lib/Crypt/Digest/Tiger192.pm26
-rw-r--r--lib/Crypt/Digest/Whirlpool.pm26
-rw-r--r--lib/Crypt/KeyDerivation.pm53
-rw-r--r--lib/Crypt/Mac.pm18
-rw-r--r--lib/Crypt/Mac/BLAKE2b.pm9
-rw-r--r--lib/Crypt/Mac/BLAKE2s.pm9
-rw-r--r--lib/Crypt/Mac/F9.pm11
-rw-r--r--lib/Crypt/Mac/HMAC.pm11
-rw-r--r--lib/Crypt/Mac/OMAC.pm11
-rw-r--r--lib/Crypt/Mac/PMAC.pm11
-rw-r--r--lib/Crypt/Mac/Pelican.pm9
-rw-r--r--lib/Crypt/Mac/Poly1305.pm9
-rw-r--r--lib/Crypt/Mac/XCBC.pm11
-rw-r--r--lib/Crypt/Misc.pm46
-rw-r--r--lib/Crypt/Mode.pm59
-rw-r--r--lib/Crypt/Mode/CBC.pm17
-rw-r--r--lib/Crypt/Mode/CFB.pm17
-rw-r--r--lib/Crypt/Mode/CTR.pm17
-rw-r--r--lib/Crypt/Mode/ECB.pm17
-rw-r--r--lib/Crypt/Mode/OFB.pm17
-rw-r--r--lib/Crypt/PK.pm2
-rw-r--r--lib/Crypt/PK/DH.pm8
-rw-r--r--lib/Crypt/PK/DSA.pm60
-rw-r--r--lib/Crypt/PK/ECC.pm707
-rw-r--r--lib/Crypt/PK/RSA.pm68
-rw-r--r--lib/Crypt/PRNG.pm33
-rw-r--r--lib/Crypt/PRNG/ChaCha20.pm3
-rw-r--r--lib/Crypt/PRNG/Fortuna.pm3
-rw-r--r--lib/Crypt/PRNG/RC4.pm3
-rw-r--r--lib/Crypt/PRNG/Sober128.pm3
-rw-r--r--lib/Crypt/PRNG/Yarrow.pm2
-rw-r--r--lib/Crypt/Stream/ChaCha.pm2
-rw-r--r--lib/Crypt/Stream/RC4.pm2
-rw-r--r--lib/Crypt/Stream/Rabbit.pm2
-rw-r--r--lib/Crypt/Stream/Salsa20.pm2
-rw-r--r--lib/Crypt/Stream/Sober128.pm2
-rw-r--r--lib/Crypt/Stream/Sosemanuk.pm2
-rw-r--r--lib/CryptX.pm16
-rw-r--r--lib/Math/BigInt/LTM.pm2
-rw-r--r--src/Makefile42
-rw-r--r--src/Makefile.nmake44
-rw-r--r--src/ltc/hashes/sha3.c109
-rw-r--r--src/ltc/hashes/sha3_test.c328
-rw-r--r--src/ltc/headers/tomcrypt.h6
-rw-r--r--src/ltc/headers/tomcrypt_custom.h40
-rw-r--r--src/ltc/headers/tomcrypt_hash.h37
-rw-r--r--src/ltc/headers/tomcrypt_math.h49
-rw-r--r--src/ltc/headers/tomcrypt_pk.h272
-rw-r--r--src/ltc/mac/blake2/blake2bmac_file.c5
-rw-r--r--src/ltc/mac/blake2/blake2smac_file.c5
-rw-r--r--src/ltc/mac/f9/f9_file.c6
-rw-r--r--src/ltc/mac/hmac/hmac_file.c6
-rw-r--r--src/ltc/mac/omac/omac_file.c6
-rw-r--r--src/ltc/mac/pmac/pmac_file.c6
-rw-r--r--src/ltc/mac/poly1305/poly1305_file.c5
-rw-r--r--src/ltc/mac/xcbc/xcbc_file.c6
-rw-r--r--src/ltc/math/rand_bn.c2
-rw-r--r--src/ltc/math/tfm_desc.c113
-rw-r--r--src/ltc/misc/crypt/crypt.c3
-rw-r--r--src/ltc/misc/crypt/crypt_constants.c5
-rw-r--r--src/ltc/misc/crypt/crypt_register_all_hashes.c6
-rw-r--r--src/ltc/misc/error_to_string.c2
-rw-r--r--src/ltc/misc/pk_get_oid.c2
-rw-r--r--src/ltc/modes/ctr/ctr_encrypt.c2
-rw-r--r--src/ltc/pk/asn1/der/bit/der_decode_bit_string.c25
-rw-r--r--src/ltc/pk/asn1/der/bit/der_decode_raw_bit_string.c25
-rw-r--r--src/ltc/pk/asn1/der/bit/der_encode_bit_string.c13
-rw-r--r--src/ltc/pk/asn1/der/bit/der_encode_raw_bit_string.c13
-rw-r--r--src/ltc/pk/asn1/der/bit/der_length_bit_string.c18
-rw-r--r--src/ltc/pk/asn1/der/choice/der_decode_choice.c12
-rw-r--r--src/ltc/pk/asn1/der/custom_type/der_decode_custom_type.c420
-rw-r--r--src/ltc/pk/asn1/der/custom_type/der_encode_custom_type.c238
-rw-r--r--src/ltc/pk/asn1/der/custom_type/der_length_custom_type.c213
-rw-r--r--src/ltc/pk/asn1/der/general/der_asn1_maps.c167
-rw-r--r--src/ltc/pk/asn1/der/general/der_decode_asn1_identifier.c133
-rw-r--r--src/ltc/pk/asn1/der/general/der_decode_asn1_length.c67
-rw-r--r--src/ltc/pk/asn1/der/general/der_encode_asn1_identifier.c97
-rw-r--r--src/ltc/pk/asn1/der/general/der_encode_asn1_length.c127
-rw-r--r--src/ltc/pk/asn1/der/general/der_length_asn1_identifier.c33
-rw-r--r--src/ltc/pk/asn1/der/general/der_length_asn1_length.c32
-rw-r--r--src/ltc/pk/asn1/der/ia5/der_decode_ia5_string.c25
-rw-r--r--src/ltc/pk/asn1/der/ia5/der_encode_ia5_string.c20
-rw-r--r--src/ltc/pk/asn1/der/ia5/der_length_ia5_string.c18
-rw-r--r--src/ltc/pk/asn1/der/integer/der_decode_integer.c48
-rw-r--r--src/ltc/pk/asn1/der/integer/der_encode_integer.c23
-rw-r--r--src/ltc/pk/asn1/der/integer/der_length_integer.c26
-rw-r--r--src/ltc/pk/asn1/der/object_identifier/der_decode_object_identifier.c46
-rw-r--r--src/ltc/pk/asn1/der/object_identifier/der_encode_object_identifier.c15
-rw-r--r--src/ltc/pk/asn1/der/octet/der_decode_octet_string.c24
-rw-r--r--src/ltc/pk/asn1/der/octet/der_encode_octet_string.c20
-rw-r--r--src/ltc/pk/asn1/der/octet/der_length_octet_string.c20
-rw-r--r--src/ltc/pk/asn1/der/printable_string/der_decode_printable_string.c25
-rw-r--r--src/ltc/pk/asn1/der/printable_string/der_encode_printable_string.c20
-rw-r--r--src/ltc/pk/asn1/der/printable_string/der_length_printable_string.c18
-rw-r--r--src/ltc/pk/asn1/der/sequence/der_decode_sequence_ex.c310
-rw-r--r--src/ltc/pk/asn1/der/sequence/der_decode_sequence_flexi.c213
-rw-r--r--src/ltc/pk/asn1/der/sequence/der_decode_sequence_multi.c83
-rw-r--r--src/ltc/pk/asn1/der/sequence/der_encode_sequence_ex.c56
-rw-r--r--src/ltc/pk/asn1/der/sequence/der_encode_sequence_multi.c6
-rw-r--r--src/ltc/pk/asn1/der/sequence/der_length_sequence.c51
-rw-r--r--src/ltc/pk/asn1/der/sequence/der_sequence_shrink.c2
-rw-r--r--src/ltc/pk/asn1/der/set/der_encode_set.c25
-rw-r--r--src/ltc/pk/asn1/der/short_integer/der_length_short_integer.c24
-rw-r--r--src/ltc/pk/asn1/der/teletex_string/der_decode_teletex_string.c25
-rw-r--r--src/ltc/pk/asn1/der/teletex_string/der_length_teletex_string.c18
-rw-r--r--src/ltc/pk/asn1/der/utf8/der_decode_utf8_string.c38
-rw-r--r--src/ltc/pk/asn1/der/utf8/der_encode_utf8_string.c43
-rw-r--r--src/ltc/pk/asn1/der/utf8/der_length_utf8_string.c18
-rw-r--r--src/ltc/pk/asn1/x509/x509_decode_subject_public_key_info.c (renamed from src/ltc/pk/asn1/der/sequence/der_decode_subject_public_key_info.c)27
-rw-r--r--src/ltc/pk/asn1/x509/x509_encode_subject_public_key_info.c (renamed from src/ltc/pk/asn1/der/sequence/der_encode_subject_public_key_info.c)8
-rw-r--r--src/ltc/pk/dsa/dsa_export.c2
-rw-r--r--src/ltc/pk/dsa/dsa_import.c7
-rw-r--r--src/ltc/pk/dsa/dsa_verify_hash.c2
-rw-r--r--src/ltc/pk/ecc/ecc.c333
-rw-r--r--src/ltc/pk/ecc/ecc_ansi_x963_export.c8
-rw-r--r--src/ltc/pk/ecc/ecc_ansi_x963_import.c64
-rw-r--r--src/ltc/pk/ecc/ecc_decrypt_key.c11
-rw-r--r--src/ltc/pk/ecc/ecc_dp_clear.c36
-rw-r--r--src/ltc/pk/ecc/ecc_dp_fill_from_sets.c76
-rw-r--r--src/ltc/pk/ecc/ecc_dp_from_oid.c84
-rw-r--r--src/ltc/pk/ecc/ecc_dp_from_params.c84
-rw-r--r--src/ltc/pk/ecc/ecc_dp_init.c36
-rw-r--r--src/ltc/pk/ecc/ecc_dp_set.c100
-rw-r--r--src/ltc/pk/ecc/ecc_encrypt_key.c15
-rw-r--r--src/ltc/pk/ecc/ecc_export.c9
-rw-r--r--src/ltc/pk/ecc/ecc_export_openssl.c (renamed from src/ltc/pk/ecc/ecc_export_full.c)81
-rw-r--r--src/ltc/pk/ecc/ecc_free.c12
-rw-r--r--src/ltc/pk/ecc/ecc_get_key.c (renamed from src/ltc/pk/ecc/ecc_export_raw.c)28
-rw-r--r--src/ltc/pk/ecc/ecc_get_set.c40
-rw-r--r--src/ltc/pk/ecc/ecc_get_size.c12
-rw-r--r--src/ltc/pk/ecc/ecc_import.c42
-rw-r--r--src/ltc/pk/ecc/ecc_import_full.c152
-rw-r--r--src/ltc/pk/ecc/ecc_import_openssl.c157
-rw-r--r--src/ltc/pk/ecc/ecc_import_pkcs8.c696
-rw-r--r--src/ltc/pk/ecc/ecc_import_raw.c100
-rw-r--r--src/ltc/pk/ecc/ecc_import_x509.c59
-rw-r--r--src/ltc/pk/ecc/ecc_make_key.c99
-rw-r--r--src/ltc/pk/ecc/ecc_set_dp.c97
-rw-r--r--src/ltc/pk/ecc/ecc_set_dp_internal.c150
-rw-r--r--src/ltc/pk/ecc/ecc_set_key.c67
-rw-r--r--src/ltc/pk/ecc/ecc_shared_secret.c25
-rw-r--r--src/ltc/pk/ecc/ecc_sign_hash.c45
-rw-r--r--src/ltc/pk/ecc/ecc_sizes.c36
-rw-r--r--src/ltc/pk/ecc/ecc_verify_hash.c85
-rw-r--r--src/ltc/pk/ecc/ltc_ecc_export_point.c9
-rw-r--r--src/ltc/pk/ecc/ltc_ecc_import_point.c9
-rw-r--r--src/ltc/pk/ecc/ltc_ecc_is_point.c43
-rw-r--r--src/ltc/pk/ecc/ltc_ecc_is_point_at_infinity.c6
-rw-r--r--src/ltc/pk/ecc/ltc_ecc_is_valid_idx.c42
-rw-r--r--src/ltc/pk/ecc/ltc_ecc_map.c5
-rw-r--r--src/ltc/pk/ecc/ltc_ecc_mul2add.c25
-rw-r--r--src/ltc/pk/ecc/ltc_ecc_mulmod.c48
-rw-r--r--src/ltc/pk/ecc/ltc_ecc_mulmod_timing.c43
-rw-r--r--src/ltc/pk/ecc/ltc_ecc_points.c3
-rw-r--r--src/ltc/pk/ecc/ltc_ecc_projective_add_point.c7
-rw-r--r--src/ltc/pk/ecc/ltc_ecc_projective_dbl_point.c11
-rw-r--r--src/ltc/pk/ecc/ltc_ecc_verify_key.c (renamed from src/ltc/pk/ecc/ecc_verify_key.c)31
-rw-r--r--src/ltc/pk/rsa/rsa_export.c2
-rw-r--r--src/ltc/pk/rsa/rsa_import.c7
-rw-r--r--src/ltc/pk/rsa/rsa_import_x509.c7
-rw-r--r--src/ltc/pk/rsa/rsa_verify_hash.c4
-rw-r--r--t/001_compile.t4
-rw-r--r--t/002_all_pm.t2
-rw-r--r--t/003_all_pm_pod.t2
-rw-r--r--t/004_all_pm_pod_spelling.t3
-rw-r--r--t/005_all_pm_pod_coverage.t8
-rw-r--r--t/auth_enc_ccm.t6
-rw-r--r--t/checksum.t144
-rw-r--r--t/crypt-misc.t4
-rw-r--r--t/digest_blake2b_160.t13
-rw-r--r--t/digest_blake2b_256.t13
-rw-r--r--t/digest_blake2b_384.t13
-rw-r--r--t/digest_blake2b_512.t13
-rw-r--r--t/digest_blake2s_128.t13
-rw-r--r--t/digest_blake2s_160.t13
-rw-r--r--t/digest_blake2s_224.t13
-rw-r--r--t/digest_blake2s_256.t13
-rw-r--r--t/digest_chaes.t13
-rw-r--r--t/digest_keccak224.t116
-rw-r--r--t/digest_keccak256.t116
-rw-r--r--t/digest_keccak384.t116
-rw-r--r--t/digest_keccak512.t116
-rw-r--r--t/digest_md2.t13
-rw-r--r--t/digest_md4.t13
-rw-r--r--t/digest_md5.t13
-rw-r--r--t/digest_ripemd128.t13
-rw-r--r--t/digest_ripemd160.t13
-rw-r--r--t/digest_ripemd256.t13
-rw-r--r--t/digest_ripemd320.t13
-rw-r--r--t/digest_sha1.t13
-rw-r--r--t/digest_sha224.t13
-rw-r--r--t/digest_sha256.t13
-rw-r--r--t/digest_sha384.t13
-rw-r--r--t/digest_sha3_224.t13
-rw-r--r--t/digest_sha3_256.t13
-rw-r--r--t/digest_sha3_384.t13
-rw-r--r--t/digest_sha3_512.t13
-rw-r--r--t/digest_sha512.t13
-rw-r--r--t/digest_sha512_224.t13
-rw-r--r--t/digest_sha512_256.t13
-rw-r--r--t/digest_tiger192.t13
-rw-r--r--t/digest_whirlpool.t13
-rw-r--r--t/jwk.t12
-rw-r--r--t/mac_blake2b.t11
-rw-r--r--t/mac_blake2s.t11
-rw-r--r--t/mac_f9.t11
-rw-r--r--t/mac_hmac.t11
-rw-r--r--t/mac_omac.t11
-rw-r--r--t/mac_pelican.t11
-rw-r--r--t/mac_pmac.t11
-rw-r--r--t/mac_poly1305.t11
-rw-r--r--t/mac_xcbc.t11
-rw-r--r--t/mode_ctr.t24
-rw-r--r--t/pk_dsa.t8
-rw-r--r--t/pk_ecc.t16
-rw-r--r--t/pkcs8.t13
-rw-r--r--t/wycheproof.t36
329 files changed, 10722 insertions, 7182 deletions
diff --git a/Changes b/Changes
index 4ec28374..8f2fd32e 100644
--- a/Changes
+++ b/Changes
@@ -1,5 +1,20 @@
Changes for CryptX
+0.059 2018-03-25
+ - new Crypt::Digest::Keccak(224|256|384|512)
+ - new methods sign_hash_rfc7518 + verify_hash_rfc7518 (Crypt::PK::ECC)
+ - improved import of pkcs#8 private keys (Crypt::PK::ECC)
+ - improved export allowing "compressed" variants (Crypt::PK::ECC)
+ - fix #28 Apple's APNS pkcs8 auth key import fails (Crypt::PK::ECC)
+ - fix cpantesters failure (5.8.1 related)
+
+0.058 2018-02-27
+ - fix: decode_b58b + invalid input
+
+0.057 2018-01-31
+ - significant speed-up (more stuff handled on XS level)
+ - Crypt::Checksum is deprecated in favour of Crypt::Checksum::Adler32|CRC32
+
0.056 2017-12-22
- new Crypt::Stream::Rabbit
diff --git a/CryptX.xs b/CryptX.xs
index 91b7af81..41f21358 100644
--- a/CryptX.xs
+++ b/CryptX.xs
@@ -1,3 +1,4 @@
+#define PERL_NO_GET_CONTEXT /* we want efficiency */
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
@@ -7,22 +8,53 @@
#define NEED_newRV_noinc_GLOBAL
#include "ppport.h"
+/* assert_not_ROK is broken in 5.8.1 */
+#if PERL_VERSION == 8 && PERL_SUBVERSION == 1
+# undef assert_not_ROK
+# if defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN)
+# define assert_not_ROK(sv) ({assert(!SvROK(sv) || !SvRV(sv));}),
+# else
+# define assert_not_ROK(sv)
+# endif
+#endif
+
#undef LTC_SOURCE
#include "tomcrypt.h"
#include "tommath.h"
-typedef adler32_state *Crypt__Checksum__Adler32;
-typedef crc32_state *Crypt__Checksum__CRC32;
+typedef adler32_state *Crypt__Checksum__Adler32;
+typedef crc32_state *Crypt__Checksum__CRC32;
+
+typedef ccm_state *Crypt__AuthEnc__CCM;
+typedef eax_state *Crypt__AuthEnc__EAX;
+typedef gcm_state *Crypt__AuthEnc__GCM;
+typedef chacha20poly1305_state *Crypt__AuthEnc__ChaCha20Poly1305;
+typedef ocb3_state *Crypt__AuthEnc__OCB;
+
+typedef chacha_state *Crypt__Stream__ChaCha;
+typedef salsa20_state *Crypt__Stream__Salsa20;
+typedef sosemanuk_state *Crypt__Stream__Sosemanuk;
+typedef rabbit_state *Crypt__Stream__Rabbit;
+typedef rc4_state *Crypt__Stream__RC4;
+typedef sober128_state *Crypt__Stream__Sober128;
+
+typedef f9_state *Crypt__Mac__F9;
+typedef hmac_state *Crypt__Mac__HMAC;
+typedef omac_state *Crypt__Mac__OMAC;
+typedef pelican_state *Crypt__Mac__Pelican;
+typedef pmac_state *Crypt__Mac__PMAC;
+typedef xcbc_state *Crypt__Mac__XCBC;
+typedef poly1305_state *Crypt__Mac__Poly1305;
+typedef blake2smac_state *Crypt__Mac__BLAKE2s;
+typedef blake2bmac_state *Crypt__Mac__BLAKE2b;
typedef struct cipher_struct { /* used by Crypt::Cipher */
symmetric_key skey;
- int id;
struct ltc_cipher_descriptor *desc;
} *Crypt__Cipher;
typedef struct digest_struct { /* used by Crypt::Digest */
hash_state state;
- int id;
struct ltc_hash_descriptor *desc;
} *Crypt__Digest;
@@ -31,109 +63,6 @@ typedef struct digest_shake_struct { /* used by Crypt::Digest::SHAKE */
int num;
} *Crypt__Digest__SHAKE;
-typedef struct ccm_struct { /* used by Crypt::AuthEnc::CCM */
- ccm_state state;
- int direction;
- int tag_len;
- unsigned long pt_len;
- int id;
-} *Crypt__AuthEnc__CCM;
-
-typedef struct eax_struct { /* used by Crypt::AuthEnc::EAX */
- eax_state state;
- int id;
-} *Crypt__AuthEnc__EAX;
-
-typedef struct gcm_struct { /* used by Crypt::AuthEnc::GCM */
- gcm_state state;
- int id;
-} *Crypt__AuthEnc__GCM;
-
-typedef struct chacha20poly1305_struct {/* used by Crypt::AuthEnc::ChaCha20Poly1305 */
- chacha20poly1305_state state;
- int id;
-} *Crypt__AuthEnc__ChaCha20Poly1305;
-
-typedef struct ocb_struct { /* used by Crypt::AuthEnc::OCB */
- ocb3_state state;
- int id;
-} *Crypt__AuthEnc__OCB;
-
-typedef struct chacha_struct { /* used by Crypt::Stream::ChaCha */
- chacha_state state;
- int id;
-} *Crypt__Stream__ChaCha;
-
-typedef struct salsa20_struct { /* used by Crypt::Stream::Salsa20 */
- salsa20_state state;
- int id;
-} *Crypt__Stream__Salsa20;
-
-typedef struct sosemanuk_struct { /* used by Crypt::Stream::Sosemanuk */
- sosemanuk_state state;
- int id;
-} *Crypt__Stream__Sosemanuk;
-
-typedef struct rabbit_struct { /* used by Crypt::Stream::Rabbit */
- rabbit_state state;
- int id;
-} *Crypt__Stream__Rabbit;
-
-typedef struct rc4_struct { /* used by Crypt::Stream::RC4 */
- rc4_state state;
- int id;
-} *Crypt__Stream__RC4;
-
-typedef struct sober128_struct { /* used by Crypt::Stream::Sober128 */
- sober128_state state;
- int id;
-} *Crypt__Stream__Sober128;
-
-typedef struct f9_struct { /* used by Crypt::Mac::F9 */
- f9_state state;
- int id;
-} *Crypt__Mac__F9;
-
-typedef struct hmac_struct { /* used by Crypt::Mac::HMAC */
- hmac_state state;
- int id;
-} *Crypt__Mac__HMAC;
-
-typedef struct omac_struct { /* used by Crypt::Mac::OMAC */
- omac_state state;
- int id;
-} *Crypt__Mac__OMAC;
-
-typedef struct pelican_struct { /* used by Crypt::Mac::Pelican */
- pelican_state state;
- int id;
-} *Crypt__Mac__Pelican;
-
-typedef struct pmac_struct { /* used by Crypt::Mac::PMAC */
- pmac_state state;
- int id;
-} *Crypt__Mac__PMAC;
-
-typedef struct xcbc_struct { /* used by Crypt::Mac::XCBC */
- xcbc_state state;
- int id;
-} *Crypt__Mac__XCBC;
-
-typedef struct poly1305_struct { /* used by Crypt::Mac::Poly1305 */
- poly1305_state state;
- int id;
-} *Crypt__Mac__Poly1305;
-
-typedef struct blake2s_struct { /* used by Crypt::Mac::BLAKE2s */
- blake2smac_state state;
- int id;
-} *Crypt__Mac__BLAKE2s;
-
-typedef struct blake2b_struct { /* used by Crypt::Mac::BLAKE2b */
- blake2bmac_state state;
- int id;
-} *Crypt__Mac__BLAKE2b;
-
typedef struct cbc_struct { /* used by Crypt::Mode::CBC */
int cipher_id, cipher_rounds;
symmetric_CBC state;
@@ -141,7 +70,6 @@ typedef struct cbc_struct { /* used by Crypt::Mode::CBC */
int padlen;
int padding_mode;
int direction;
- int id;
} *Crypt__Mode__CBC;
typedef struct ecb_struct { /* used by Crypt::Mode::ECB */
@@ -151,14 +79,12 @@ typedef struct ecb_struct { /* used by Crypt::Mode::ECB */
int padlen;
int padding_mode;
int direction;
- int id;
} *Crypt__Mode__ECB;
typedef struct cfb_struct { /* used by Crypt::Mode::CFB */
int cipher_id, cipher_rounds;
symmetric_CFB state;
int direction;
- int id;
} *Crypt__Mode__CFB;
typedef struct ctr_struct { /* used by Crypt::Mode::CTR */
@@ -166,174 +92,302 @@ typedef struct ctr_struct { /* used by Crypt::Mode::CTR */
int ctr_mode_param;
symmetric_CTR state;
int direction;
- int id;
} *Crypt__Mode__CTR;
typedef struct f8_struct { /* used by Crypt::Mode::F8 */
int cipher_id, cipher_rounds;
symmetric_F8 state;
int direction;
- int id;
} *Crypt__Mode__F8;
typedef struct lrw_struct { /* used by Crypt::Mode::LRW */
int cipher_id, cipher_rounds;
symmetric_LRW state;
int direction;
- int id;
} *Crypt__Mode__LRW;
typedef struct ofb_struct { /* used by Crypt::Mode::OFB */
int cipher_id, cipher_rounds;
symmetric_OFB state;
int direction;
- int id;
} *Crypt__Mode__OFB;
typedef struct xts_struct { /* used by Crypt::Mode::XTS */
int cipher_id, cipher_rounds;
symmetric_xts state;
int direction;
- int id;
} *Crypt__Mode__XTS;
typedef struct prng_struct { /* used by Crypt::PRNG */
prng_state state;
struct ltc_prng_descriptor *desc;
IV last_pid;
- int id;
} *Crypt__PRNG;
typedef struct rsa_struct { /* used by Crypt::PK::RSA */
prng_state pstate;
int pindex;
rsa_key key;
- int id;
} *Crypt__PK__RSA;
typedef struct dsa_struct { /* used by Crypt::PK::DSA */
prng_state pstate;
int pindex;
dsa_key key;
- int id;
} *Crypt__PK__DSA;
typedef struct dh_struct { /* used by Crypt::PK::DH */
prng_state pstate;
int pindex;
dh_key key;
- int id;
} *Crypt__PK__DH;
typedef struct ecc_struct { /* used by Crypt::PK::ECC */
prng_state pstate;
int pindex;
ecc_key key;
- ltc_ecc_set_type dp;
- int id;
} *Crypt__PK__ECC;
-int str_add_leading_zero(char *str, int maxlen, int minlen) {
- int len;
+int mp_tohex_with_leading_zero(mp_int * a, char *str, int maxlen, int minlen) {
+ int len, rv;
+
+ if (mp_isneg(a) == MP_YES) {
+ *str = '\0';
+ return MP_VAL;
+ }
+
+ rv = mp_toradix_n(a, str, 16, maxlen);
+ if (rv != MP_OKAY) {
+ *str = '\0';
+ return rv;
+ }
+
len = (int)strlen(str);
if (len > 0 && len % 2 && len < maxlen-2) {
memmove(str+1, str, len+1); /* incl. NUL byte */
*str = '0'; /* add leading zero */
}
+
len = (int)strlen(str);
if (len < minlen && minlen < maxlen-1) {
memmove(str+(minlen-len), str, len+1); /* incl. NUL byte */
memset(str, '0', minlen-len); /* add leading zero */
}
+
return MP_OKAY;
}
-int mp_tohex_with_leading_zero(mp_int * a, char *str, int maxlen, int minlen) {
- int rv;
- if (mp_isneg(a) == MP_YES) {
- *str = '\0';
- return MP_VAL;
- }
- rv = mp_toradix_n(a, str, 16, maxlen);
- if (rv != MP_OKAY) {
- *str = '\0';
- return rv;
- }
- return str_add_leading_zero(str, maxlen, minlen);
+int _base16_encode(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen)
+{
+ unsigned long i;
+ const char alphabet[] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
+
+ if (*outlen < inlen * 2) {
+ *outlen = inlen * 2;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ for (i = 0; i < inlen; i++) {
+ out[i*2] = (unsigned char)alphabet[in[i] >> 4];
+ out[i*2+1] = (unsigned char)alphabet[in[i] & 0xF];
+ }
+
+ *outlen = inlen * 2;
+ return CRYPT_OK;
+}
+
+size_t _find_start(const char *name, char *ltcname, size_t ltclen)
+{
+ size_t i, start = 0;
+ if (name == NULL || strlen(name) + 1 > ltclen) croak("FATAL: invalid name") ;
+ /* normalize */
+ for (i = 0; i < ltclen && name[i] > 0; i++) {
+ if (name[i] >= 'A' && name[i] <= 'Z') {
+ ltcname[i] = name[i] + 32; /* lowecase */
+ }
+ else if (name[i] == '_') {
+ ltcname[i] = '-';
+ }
+ else {
+ ltcname[i] = name[i];
+ }
+ if (name[i] == ':') start = i + 1;
+ }
+ return start;
+}
+
+int _find_hash(const char *name)
+{
+ char ltcname[100] = { 0 };
+ size_t start = _find_start(name, ltcname, sizeof(ltcname) - 1);
+ /* special cases */
+ if (strcmp(ltcname + start, "ripemd128") == 0) return find_hash("rmd128");
+ if (strcmp(ltcname + start, "ripemd160") == 0) return find_hash("rmd160");
+ if (strcmp(ltcname + start, "ripemd256") == 0) return find_hash("rmd256");
+ if (strcmp(ltcname + start, "ripemd320") == 0) return find_hash("rmd320");
+ if (strcmp(ltcname + start, "tiger192") == 0) return find_hash("tiger");
+ if (strcmp(ltcname + start, "chaes") == 0) return find_hash("chc_hash");
+ if (strcmp(ltcname + start, "chc-hash") == 0) return find_hash("chc_hash");
+ return find_hash(ltcname + start);
+}
+
+int _find_cipher(const char *name)
+{
+ char ltcname[100] = { 0 };
+ size_t start = _find_start(name, ltcname, sizeof(ltcname) - 1);
+ /* special cases */
+ if (strcmp(ltcname + start, "des-ede") == 0) return find_cipher("3des");
+ if (strcmp(ltcname + start, "saferp") == 0) return find_cipher("safer+");
+ return find_cipher(ltcname + start);
+}
+
+int _find_prng(const char *name)
+{
+ char ltcname[100] = { 0 };
+ size_t start = _find_start(name, ltcname, sizeof(ltcname) - 1);
+ return find_prng(ltcname + start);
}
/* Math::BigInt::LTM related */
typedef mp_int * Math__BigInt__LTM;
STATIC SV * sv_from_mpi(mp_int *mpi) {
+ dTHX; /* fetch context */
SV *obj = newSV(0);
sv_setref_pv(obj, "Math::BigInt::LTM", (void*)mpi);
return obj;
}
-ltc_ecc_set_type* _ecc_set_dp_from_SV(ltc_ecc_set_type *dp, SV *curve)
+void _ecc_oid_lookup(ecc_key *key)
{
- HV *h;
- SV *param, **pref;
- SV **sv_cofactor, **sv_prime, **sv_A, **sv_B, **sv_order, **sv_Gx, **sv_Gy;
- int err;
+ int err;
+ unsigned i;
+ void *tmp;
+ const ltc_ecc_set_type *set;
+
+ key->dp.oidlen = 0;
+ if ((err = ltc_mp.init(&tmp)) != CRYPT_OK) return;
+ for (set = ltc_ecc_sets; set->name != NULL; set++) {
+ if ((err = mp_read_radix(tmp, set->prime, 16)) != CRYPT_OK) continue;
+ if ((mp_cmp(tmp, key->dp.prime) != LTC_MP_EQ)) continue;
+ if ((err = mp_read_radix(tmp, set->order, 16)) != CRYPT_OK) continue;
+ if ((mp_cmp(tmp, key->dp.order) != LTC_MP_EQ)) continue;
+ if ((err = mp_read_radix(tmp, set->A, 16)) != CRYPT_OK) continue;
+ if ((mp_cmp(tmp, key->dp.A) != LTC_MP_EQ)) continue;
+ if ((err = mp_read_radix(tmp, set->B, 16)) != CRYPT_OK) continue;
+ if ((mp_cmp(tmp, key->dp.B) != LTC_MP_EQ)) continue;
+ if ((err = mp_read_radix(tmp, set->Gx, 16)) != CRYPT_OK) continue;
+ if ((mp_cmp(tmp, key->dp.base.x) != LTC_MP_EQ)) continue;
+ if ((err = mp_read_radix(tmp, set->Gy, 16)) != CRYPT_OK) continue;
+ if ((mp_cmp(tmp, key->dp.base.y) != LTC_MP_EQ)) continue;
+ if (key->dp.cofactor != set->cofactor) continue;
+ break; /* found */
+ }
+ ltc_mp.deinit(tmp);
+ if (set->name != NULL) {
+ key->dp.oidlen = set->oidlen;
+ for(i = 0; i < set->oidlen; i++) key->dp.oid[i] = set->oid[i];
+ }
+}
+
+int _ecc_set_dp_from_SV(ecc_key *key, SV *curve)
+{
+ dTHX; /* fetch context */
+ HV *hc, *hl, *h;
+ SV *sv_crv, **pref;
+ SV **sv_cofactor, **sv_prime, **sv_A, **sv_B, **sv_order, **sv_Gx, **sv_Gy, **sv_oid;
char *ch_name;
- STRLEN l_name;
+ STRLEN l_name, i, j;
+ int err;
+
+ if (!SvOK(curve)) croak("FATAL: undefined curve");
if (SvPOK(curve)) {
+ /* string */
ch_name = SvPV(curve, l_name);
- if ((h = get_hv("Crypt::PK::ECC::curve", 0)) == NULL) croak("FATAL: generate_key_ex: no curve register");
- if ((pref = hv_fetch(h, ch_name, (U32)l_name, 0)) == NULL) croak("FATAL: generate_key_ex: unknown curve/1 '%s'", ch_name);
- if (!SvOK(*pref)) croak("FATAL: generate_key_ex: unknown curve/2 '%s'", ch_name);
- param = *pref;
+ if ((hl = get_hv("Crypt::PK::ECC::curve2ltc", 0)) == NULL) croak("FATAL: no curve2ltc register");
+ pref = hv_fetch(hl, ch_name, (U32)l_name, 0);
+ if (pref && SvOK(*pref)) {
+ sv_crv = *pref; /* found in %cutve2ltc */
+ }
+ else {
+ if ((hc = get_hv("Crypt::PK::ECC::curve", 0)) == NULL) croak("FATAL: no curve register");
+ pref = hv_fetch(hc, ch_name, (U32)l_name, 0);
+ if (pref && SvOK(*pref)) {
+ sv_crv = *pref; /* found in %curve */
+ }
+ else {
+ sv_crv = curve;
+ }
+ }
}
else if (SvROK(curve)) {
- param = curve;
+ /* hashref */
+ sv_crv = curve;
}
else {
croak("FATAL: curve has to be a string or a hashref");
}
- if ((h = (HV*)(SvRV(param))) == NULL) croak("FATAL: ecparams: param is not valid hashref");
-
- if ((sv_prime = hv_fetchs(h, "prime", 0)) == NULL) croak("FATAL: ecparams: missing param prime");
- if ((sv_A = hv_fetchs(h, "A", 0)) == NULL) croak("FATAL: ecparams: missing param A");
- if ((sv_B = hv_fetchs(h, "B", 0)) == NULL) croak("FATAL: ecparams: missing param B");
- if ((sv_order = hv_fetchs(h, "order", 0)) == NULL) croak("FATAL: ecparams: missing param order");
- if ((sv_Gx = hv_fetchs(h, "Gx", 0)) == NULL) croak("FATAL: ecparams: missing param Gx");
- if ((sv_Gy = hv_fetchs(h, "Gy", 0)) == NULL) croak("FATAL: ecparams: missing param Gy");
- if ((sv_cofactor = hv_fetchs(h, "cofactor", 0)) == NULL) croak("FATAL: ecparams: missing param cofactor");
-
- if (!SvOK(*sv_prime )) croak("FATAL: ecparams: undefined param prime");
- if (!SvOK(*sv_A )) croak("FATAL: ecparams: undefined param A");
- if (!SvOK(*sv_B )) croak("FATAL: ecparams: undefined param B");
- if (!SvOK(*sv_order )) croak("FATAL: ecparams: undefined param order");
- if (!SvOK(*sv_Gx )) croak("FATAL: ecparams: undefined param Gx");
- if (!SvOK(*sv_Gy )) croak("FATAL: ecparams: undefined param Gy");
- if (!SvOK(*sv_cofactor)) croak("FATAL: ecparams: undefined param cofactor");
-
- err = ecc_dp_set( dp,
- SvPV_nolen(*sv_prime),
- SvPV_nolen(*sv_A),
- SvPV_nolen(*sv_B),
- SvPV_nolen(*sv_order),
- SvPV_nolen(*sv_Gx),
- SvPV_nolen(*sv_Gy),
- (unsigned long)SvUV(*sv_cofactor),
- NULL, /* we intentionally don't allow setting custom names */
- NULL /* we intentionally don't allow setting custom OIDs */
- );
- return err == CRYPT_OK ? dp : NULL;
-}
-
-void _ecc_free_key(ecc_key *key, ltc_ecc_set_type *dp)
-{
- if(dp) {
- ecc_dp_clear(dp);
+ if (SvPOK(sv_crv)) {
+ /* string - curve name */
+ const ltc_ecc_set_type *dp;
+ ch_name = SvPV(sv_crv, l_name);
+ if (ecc_get_set_by_name(ch_name, &dp) != CRYPT_OK) croak("FATAL: ecparams: unknown curve '%s'", ch_name);
+ return ecc_set_dp(dp, key);
}
- if (key->type != -1) {
- ecc_free(key);
- key->type = -1;
- key->dp = NULL;
+ else {
+ /* hashref */
+ ltc_ecc_set_type set = { 0 };
+
+ if ((h = (HV*)(SvRV(sv_crv))) == NULL) croak("FATAL: ecparams: param is not valid hashref");
+
+ if ((sv_prime = hv_fetchs(h, "prime", 0)) == NULL) croak("FATAL: ecparams: missing param prime");
+ if ((sv_A = hv_fetchs(h, "A", 0)) == NULL) croak("FATAL: ecparams: missing param A");
+ if ((sv_B = hv_fetchs(h, "B", 0)) == NULL) croak("FATAL: ecparams: missing param B");
+ if ((sv_order = hv_fetchs(h, "order", 0)) == NULL) croak("FATAL: ecparams: missing param order");
+ if ((sv_Gx = hv_fetchs(h, "Gx", 0)) == NULL) croak("FATAL: ecparams: missing param Gx");
+ if ((sv_Gy = hv_fetchs(h, "Gy", 0)) == NULL) croak("FATAL: ecparams: missing param Gy");
+ if ((sv_cofactor = hv_fetchs(h, "cofactor", 0)) == NULL) croak("FATAL: ecparams: missing param cofactor");
+
+ if (!SvOK(*sv_prime )) croak("FATAL: ecparams: undefined param prime");
+ if (!SvOK(*sv_A )) croak("FATAL: ecparams: undefined param A");
+ if (!SvOK(*sv_B )) croak("FATAL: ecparams: undefined param B");
+ if (!SvOK(*sv_order )) croak("FATAL: ecparams: undefined param order");
+ if (!SvOK(*sv_Gx )) croak("FATAL: ecparams: undefined param Gx");
+ if (!SvOK(*sv_Gy )) croak("FATAL: ecparams: undefined param Gy");
+ if (!SvOK(*sv_cofactor)) croak("FATAL: ecparams: undefined param cofactor");
+
+ set.prime = SvPV_nolen(*sv_prime);
+ set.A = SvPV_nolen(*sv_A);
+ set.B = SvPV_nolen(*sv_B);
+ set.order = SvPV_nolen(*sv_order);
+ set.Gx = SvPV_nolen(*sv_Gx);
+ set.Gy = SvPV_nolen(*sv_Gy);
+ set.cofactor = (unsigned long)SvUV(*sv_cofactor),
+ set.name = NULL;
+ set.oidlen = 0;
+
+ sv_oid = hv_fetchs(h, "oid", 0);
+ if (sv_oid && SvPOK(*sv_oid)) {
+ ch_name = SvPV(*sv_oid, l_name);
+ for (i = 0, j = 0; i < l_name; i++) {
+ if (ch_name[i] == '.') {
+ if (++j >= 16) return CRYPT_ERROR;
+ }
+ else if(ch_name[i] >= '0' && ch_name[i] <= '9') {
+ set.oid[j] = set.oid[j] * 10 + (ch_name[i] - '0');
+ }
+ else {
+ return CRYPT_ERROR;
+ }
+ }
+ if (j == 0) return CRYPT_ERROR;
+ set.oidlen = j + 1;
+ }
+
+ if ((err = ecc_set_dp(&set, key)) != CRYPT_OK) return err;
+ if (key->dp.oidlen == 0) _ecc_oid_lookup(key);
+ return CRYPT_OK;
}
}
@@ -348,65 +402,115 @@ BOOT:
if(crypt_mp_init("ltm") != CRYPT_OK) { croak("FATAL: crypt_mp_init failed"); }
SV *
-CryptX__encode_base64url(SV * in)
+CryptX__ltc_build_settings()
+ CODE:
+ RETVAL = newSVpv(crypt_build_settings, 0);
+ OUTPUT:
+ RETVAL
+
+SV *
+CryptX__ltc_mp_name()
+ CODE:
+ RETVAL = newSVpv(ltc_mp.name, 0);
+ OUTPUT:
+ RETVAL
+
+int
+CryptX__ltc_mp_bits_per_digit()
+ CODE:
+ RETVAL = ltc_mp.bits_per_digit;
+ OUTPUT:
+ RETVAL
+
+MODULE = CryptX PACKAGE = Crypt::Misc
+
+PROTOTYPES: DISABLE
+
+SV *
+_radix_to_bin(char *in, int radix)
CODE:
{
- STRLEN in_len;
- unsigned long out_len;
- unsigned char *out_data, *in_data;
+ STRLEN len;
+ unsigned char *out_data;
+ mp_int mpi;
- if (!SvPOK(in)) XSRETURN_UNDEF;
- in_data = (unsigned char *) SvPVbyte(in, in_len);
- if (in_len == 0) {
+ if (in == NULL) XSRETURN_UNDEF;
+ if (mp_init(&mpi) != CRYPT_OK) XSRETURN_UNDEF;
+ if (strlen(in) == 0) {
RETVAL = newSVpvn("", 0);
}
- else {
- out_len = (unsigned long)(4 * ((in_len + 2) / 3) + 1);
- RETVAL = NEWSV(0, out_len);
- SvPOK_only(RETVAL);
- out_data = (unsigned char *)SvPVX(RETVAL);
- if (base64url_encode(in_data, (unsigned long)in_len, out_data, &out_len) != CRYPT_OK) {
- SvREFCNT_dec(RETVAL);
- XSRETURN_UNDEF;
+ else if (mp_read_radix(&mpi, in, radix) == CRYPT_OK) {
+ len = mp_unsigned_bin_size(&mpi);
+ if (len == 0) {
+ RETVAL = newSVpvn("", 0);
}
- SvCUR_set(RETVAL, out_len);
+ else {
+ RETVAL = NEWSV(0, len); /* avoid zero! */
+ SvPOK_only(RETVAL);
+ SvCUR_set(RETVAL, len);
+ out_data = (unsigned char *)SvPVX(RETVAL);
+ mp_to_unsigned_bin(&mpi, out_data);
+ }
+ }
+ else {
+ RETVAL = newSVpvn(NULL, 0); /* undef */
}
+ mp_clear(&mpi);
}
OUTPUT:
RETVAL
SV *
-CryptX__decode_base64url(SV * in)
+_bin_to_radix(SV *in, int radix)
CODE:
{
- STRLEN in_len;
- unsigned long out_len;
- unsigned char *out_data, *in_data;
+ STRLEN len;
+ unsigned char *in_data;
+ char *out_data;
+ mp_int mpi, tmp;
+ mp_digit d;
+ int digits = 0;
- if (!SvPOK(in)) XSRETURN_UNDEF;
- in_data = (unsigned char *) SvPVbyte(in, in_len);
- if (in_len == 0) {
+ if (!SvPOK(in) || radix < 2 || radix > 64) XSRETURN_UNDEF;
+ in_data = (unsigned char *) SvPVbyte(in, len);
+ mp_init_multi(&mpi, &tmp, NULL);
+ if (len == 0) {
RETVAL = newSVpvn("", 0);
}
else {
- out_len = (unsigned long)in_len;
- RETVAL = NEWSV(0, out_len);
- SvPOK_only(RETVAL);
- out_data = (unsigned char *)SvPVX(RETVAL);
- if (base64url_decode(in_data, (unsigned long)in_len, out_data, &out_len) != CRYPT_OK) {
- SvREFCNT_dec(RETVAL);
- XSRETURN_UNDEF;
+ if (mp_read_unsigned_bin(&mpi, in_data, (unsigned long)len) == CRYPT_OK) {
+ mp_copy(&mpi, &tmp);
+ while (mp_iszero(&tmp) == MP_NO) {
+ mp_div_d(&tmp, (mp_digit)radix, &tmp, &d);
+ digits++;
+ }
+ if (digits == 0) {
+ RETVAL = newSVpvn("", 0);
+ }
+ else {
+ RETVAL = NEWSV(0, digits + 2); /* +2 for sign and NUL byte */
+ SvPOK_only(RETVAL);
+ out_data = SvPVX(RETVAL);
+ mp_toradix(&mpi, out_data, radix);
+ SvCUR_set(RETVAL, strlen(out_data));
+ }
+ }
+ else {
+ RETVAL = newSVpvn(NULL, 0); /* undef */
}
- SvCUR_set(RETVAL, out_len);
}
+ mp_clear_multi(&tmp, &mpi, NULL);
}
OUTPUT:
RETVAL
SV *
-CryptX__encode_base64(SV * in)
+encode_b64(SV * in)
+ ALIAS:
+ encode_b64u = 1
CODE:
{
+ int rv;
STRLEN in_len;
unsigned long out_len;
unsigned char *out_data, *in_data;
@@ -418,10 +522,14 @@ CryptX__encode_base64(SV * in)
}
else {
out_len = (unsigned long)(4 * ((in_len + 2) / 3) + 1);
- RETVAL = NEWSV(0, out_len);
+ RETVAL = NEWSV(0, out_len); /* avoid zero! */
SvPOK_only(RETVAL);
out_data = (unsigned char *)SvPVX(RETVAL);
- if (base64_encode(in_data, (unsigned long)in_len, out_data, &out_len) != CRYPT_OK) {
+ if (ix == 1)
+ rv = base64url_encode(in_data, (unsigned long)in_len, out_data, &out_len);
+ else
+ rv = base64_encode(in_data, (unsigned long)in_len, out_data, &out_len);
+ if (rv != CRYPT_OK) {
SvREFCNT_dec(RETVAL);
XSRETURN_UNDEF;
}
@@ -432,9 +540,12 @@ CryptX__encode_base64(SV * in)
RETVAL
SV *
-CryptX__decode_base64(SV * in)
+decode_b64(SV * in)
+ ALIAS:
+ decode_b64u = 1
CODE:
{
+ int rv;
STRLEN in_len;
unsigned long out_len;
unsigned char *out_data, *in_data;
@@ -446,10 +557,14 @@ CryptX__decode_base64(SV * in)
}
else {
out_len = (unsigned long)in_len;
- RETVAL = NEWSV(0, out_len);
+ RETVAL = NEWSV(0, out_len); /* avoid zero! */
SvPOK_only(RETVAL);
out_data = (unsigned char *)SvPVX(RETVAL);
- if (base64_decode(in_data, (unsigned long)in_len, out_data, &out_len) != CRYPT_OK) {
+ if (ix == 1)
+ rv = base64url_decode(in_data, (unsigned long)in_len, out_data, &out_len);
+ else
+ rv = base64_decode(in_data, (unsigned long)in_len, out_data, &out_len);
+ if (rv != CRYPT_OK) {
SvREFCNT_dec(RETVAL);
XSRETURN_UNDEF;
}
@@ -460,7 +575,11 @@ CryptX__decode_base64(SV * in)
RETVAL
SV *
-CryptX__encode_b32(SV *in, unsigned idx)
+encode_b32r(SV *in)
+ ALIAS:
+ encode_b32b = 1
+ encode_b32z = 2
+ encode_b32c = 3
CODE:
{
STRLEN in_len;
@@ -469,10 +588,10 @@ CryptX__encode_b32(SV *in, unsigned idx)
int id = -1;
if (!SvPOK(in)) XSRETURN_UNDEF;
- if (idx == 0) id = BASE32_RFC4648;
- if (idx == 1) id = BASE32_BASE32HEX;
- if (idx == 2) id = BASE32_ZBASE32;
- if (idx == 3) id = BASE32_CROCKFORD;
+ if (ix == 0) id = BASE32_RFC4648;
+ if (ix == 1) id = BASE32_BASE32HEX;
+ if (ix == 2) id = BASE32_ZBASE32;
+ if (ix == 3) id = BASE32_CROCKFORD;
if (id == -1) XSRETURN_UNDEF;
in_data = (unsigned char *) SvPVbyte(in, in_len);
if (in_len == 0) {
@@ -480,7 +599,7 @@ CryptX__encode_b32(SV *in, unsigned idx)
}
else {
out_len = (unsigned long)((8 * in_len + 4) / 5);
- RETVAL = NEWSV(0, out_len);
+ RETVAL = NEWSV(0, out_len); /* avoid zero! */
SvPOK_only(RETVAL);
out_data = (unsigned char *)SvPVX(RETVAL);
if (base32_encode(in_data, (unsigned long)in_len, out_data, &out_len, id) != CRYPT_OK) {
@@ -494,7 +613,11 @@ CryptX__encode_b32(SV *in, unsigned idx)
RETVAL
SV *
-CryptX__decode_b32(SV *in, unsigned idx)
+decode_b32r(SV *in)
+ ALIAS:
+ decode_b32b = 1
+ decode_b32z = 2
+ decode_b32c = 3
CODE:
{
STRLEN in_len;
@@ -503,10 +626,10 @@ CryptX__decode_b32(SV *in, unsigned idx)
int id = -1;
if (!SvPOK(in)) XSRETURN_UNDEF;
- if (idx == 0) id = BASE32_RFC4648;
- if (idx == 1) id = BASE32_BASE32HEX;
- if (idx == 2) id = BASE32_ZBASE32;
- if (idx == 3) id = BASE32_CROCKFORD;
+ if (ix == 0) id = BASE32_RFC4648;
+ if (ix == 1) id = BASE32_BASE32HEX;
+ if (ix == 2) id = BASE32_ZBASE32;
+ if (ix == 3) id = BASE32_CROCKFORD;
if (id == -1) XSRETURN_UNDEF;
in_data = (unsigned char *)SvPVbyte(in, in_len);
if (in_len == 0) {
@@ -514,7 +637,7 @@ CryptX__decode_b32(SV *in, unsigned idx)
}
else {
out_len = (unsigned long)in_len;
- RETVAL = NEWSV(0, out_len);
+ RETVAL = NEWSV(0, out_len); /* avoid zero! */
SvPOK_only(RETVAL);
out_data = (unsigned char *)SvPVX(RETVAL);
if (base32_decode(in_data, (unsigned long)in_len, out_data, &out_len, id) != CRYPT_OK) {
@@ -528,7 +651,7 @@ CryptX__decode_b32(SV *in, unsigned idx)
RETVAL
SV *
-CryptX__increment_octets_le(SV * in)
+increment_octets_le(SV * in)
CODE:
{
STRLEN len, i = 0;
@@ -536,28 +659,31 @@ CryptX__increment_octets_le(SV * in)
if (!SvPOK(in)) XSRETURN_UNDEF;
in_data = (unsigned char *)SvPVbyte(in, len);
- if (len == 0) XSRETURN_UNDEF;
-
- RETVAL = NEWSV(0, len);
- SvPOK_only(RETVAL);
- SvCUR_set(RETVAL, len);
- out_data = (unsigned char *)SvPVX(RETVAL);
- Copy(in_data, out_data, len, unsigned char);
- while (i < len) {
- out_data[i]++;
- if (0 != out_data[i]) break;
- i++;
+ if (len == 0) {
+ RETVAL = newSVpvn("", 0);
}
- if (i == len) {
- SvREFCNT_dec(RETVAL);
- croak("FATAL: increment_octets_le overflow");
+ else {
+ RETVAL = NEWSV(0, len); /* avoid zero! */
+ SvPOK_only(RETVAL);
+ SvCUR_set(RETVAL, len);
+ out_data = (unsigned char *)SvPVX(RETVAL);
+ Copy(in_data, out_data, len, unsigned char);
+ while (i < len) {
+ out_data[i]++;
+ if (0 != out_data[i]) break;
+ i++;
+ }
+ if (i == len) {
+ SvREFCNT_dec(RETVAL);
+ croak("FATAL: increment_octets_le overflow");
+ }
}
}
OUTPUT:
RETVAL
SV *
-CryptX__increment_octets_be(SV * in)
+increment_octets_be(SV * in)
CODE:
{
STRLEN len, i = 0;
@@ -565,119 +691,29 @@ CryptX__increment_octets_be(SV * in)
if (!SvPOK(in)) XSRETURN_UNDEF;
in_data = (unsigned char *)SvPVbyte(in, len);
- if (len == 0) XSRETURN_UNDEF;
-
- RETVAL = NEWSV(0, len);
- SvPOK_only(RETVAL);
- SvCUR_set(RETVAL, len);
- out_data = (unsigned char *)SvPVX(RETVAL);
- Copy(in_data, out_data, len, unsigned char);
- while (i < len) {
- out_data[len - 1 - i]++;
- if (0 != out_data[len - 1 - i]) break;
- i++;
- }
- if (i == len) {
- SvREFCNT_dec(RETVAL);
- croak("FATAL: increment_octets_be overflow");
+ if (len == 0) {
+ RETVAL = newSVpvn("", 0);
}
- }
- OUTPUT:
- RETVAL
-
-SV *
-CryptX__radix_to_bin(char *in, int radix)
- CODE:
- {
- STRLEN len;
- unsigned char *out_data;
- mp_int mpi;
-
- if (in == NULL || strlen(in) == 0) XSRETURN_UNDEF;
- if (mp_init(&mpi) != CRYPT_OK) XSRETURN_UNDEF;
-
- if (mp_read_radix(&mpi, in, radix) == CRYPT_OK) {
- len = mp_unsigned_bin_size(&mpi);
- RETVAL = NEWSV(0, len);
+ else {
+ RETVAL = NEWSV(0, len); /* avoid zero! */
SvPOK_only(RETVAL);
SvCUR_set(RETVAL, len);
out_data = (unsigned char *)SvPVX(RETVAL);
- mp_to_unsigned_bin(&mpi, out_data);
- mp_clear(&mpi);
- }
- else {
- XSRETURN_UNDEF;
- }
- }
- OUTPUT:
- RETVAL
-
-SV *
-CryptX__bin_to_radix(SV *in, int radix)
- CODE:
- {
- STRLEN len;
- unsigned char *in_data;
- char *out_data;
- mp_int mpi, tmp;
- mp_digit d;
- int digits = 0;
-
- if (!SvPOK(in) || radix < 2 || radix > 64) XSRETURN_UNDEF;
- in_data = (unsigned char *) SvPVbyte(in, len);
- if (len == 0) XSRETURN_UNDEF;
-
- mp_init(&mpi);
- if (mp_read_unsigned_bin(&mpi, in_data, (unsigned long)len) == CRYPT_OK) {
- mp_init_copy(&tmp, &mpi);
- while (mp_iszero(&tmp) == MP_NO) {
- mp_div_d(&tmp, (mp_digit)radix, &tmp, &d);
- digits++;
- }
- mp_clear(&tmp);
-
- if (digits == 0) {
- RETVAL = newSVpvn("", 0);
- mp_clear(&mpi);
+ Copy(in_data, out_data, len, unsigned char);
+ while (i < len) {
+ out_data[len - 1 - i]++;
+ if (0 != out_data[len - 1 - i]) break;
+ i++;
}
- else {
- RETVAL = NEWSV(0, digits + 2); /* +2 for sign and NUL byte */
- SvPOK_only(RETVAL);
- out_data = SvPVX(RETVAL);
- mp_toradix(&mpi, out_data, radix);
- SvCUR_set(RETVAL, strlen(out_data));
- mp_clear(&mpi);
+ if (i == len) {
+ SvREFCNT_dec(RETVAL);
+ croak("FATAL: increment_octets_be overflow");
}
}
- else {
- mp_clear(&mpi);
- XSRETURN_UNDEF;
- }
}
OUTPUT:
RETVAL
-SV *
-CryptX__ltc_build_settings()
- CODE:
- RETVAL = newSVpv(crypt_build_settings, 0);
- OUTPUT:
- RETVAL
-
-SV *
-CryptX__ltc_mp_name()
- CODE:
- RETVAL = newSVpv(ltc_mp.name, 0);
- OUTPUT:
- RETVAL
-
-int
-CryptX__ltc_mp_bits_per_digit()
- CODE:
- RETVAL = ltc_mp.bits_per_digit;
- OUTPUT:
- RETVAL
-
###############################################################################
INCLUDE: inc/CryptX_Digest.xs.inc
diff --git a/MANIFEST b/MANIFEST
index c453328c..86a49bb4 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -82,6 +82,10 @@ lib/Crypt/Digest/BLAKE2s_160.pm
lib/Crypt/Digest/BLAKE2s_224.pm
lib/Crypt/Digest/BLAKE2s_256.pm
lib/Crypt/Digest/CHAES.pm
+lib/Crypt/Digest/Keccak224.pm
+lib/Crypt/Digest/Keccak256.pm
+lib/Crypt/Digest/Keccak384.pm
+lib/Crypt/Digest/Keccak512.pm
lib/Crypt/Digest/MD2.pm
lib/Crypt/Digest/MD4.pm
lib/Crypt/Digest/MD5.pm
@@ -389,6 +393,16 @@ src/ltc/pk/asn1/der/boolean/der_decode_boolean.c
src/ltc/pk/asn1/der/boolean/der_encode_boolean.c
src/ltc/pk/asn1/der/boolean/der_length_boolean.c
src/ltc/pk/asn1/der/choice/der_decode_choice.c
+src/ltc/pk/asn1/der/custom_type/der_decode_custom_type.c
+src/ltc/pk/asn1/der/custom_type/der_encode_custom_type.c
+src/ltc/pk/asn1/der/custom_type/der_length_custom_type.c
+src/ltc/pk/asn1/der/general/der_asn1_maps.c
+src/ltc/pk/asn1/der/general/der_decode_asn1_identifier.c
+src/ltc/pk/asn1/der/general/der_decode_asn1_length.c
+src/ltc/pk/asn1/der/general/der_encode_asn1_identifier.c
+src/ltc/pk/asn1/der/general/der_encode_asn1_length.c
+src/ltc/pk/asn1/der/general/der_length_asn1_identifier.c
+src/ltc/pk/asn1/der/general/der_length_asn1_length.c
src/ltc/pk/asn1/der/generalizedtime/der_decode_generalizedtime.c
src/ltc/pk/asn1/der/generalizedtime/der_encode_generalizedtime.c
src/ltc/pk/asn1/der/generalizedtime/der_length_generalizedtime.c
@@ -410,10 +424,8 @@ src/ltc/pk/asn1/der/printable_string/der_length_printable_string.c
src/ltc/pk/asn1/der/sequence/der_decode_sequence_ex.c
src/ltc/pk/asn1/der/sequence/der_decode_sequence_flexi.c
src/ltc/pk/asn1/der/sequence/der_decode_sequence_multi.c
-src/ltc/pk/asn1/der/sequence/der_decode_subject_public_key_info.c
src/ltc/pk/asn1/der/sequence/der_encode_sequence_ex.c
src/ltc/pk/asn1/der/sequence/der_encode_sequence_multi.c
-src/ltc/pk/asn1/der/sequence/der_encode_subject_public_key_info.c
src/ltc/pk/asn1/der/sequence/der_length_sequence.c
src/ltc/pk/asn1/der/sequence/der_sequence_free.c
src/ltc/pk/asn1/der/sequence/der_sequence_shrink.c
@@ -430,6 +442,8 @@ src/ltc/pk/asn1/der/utctime/der_length_utctime.c
src/ltc/pk/asn1/der/utf8/der_decode_utf8_string.c
src/ltc/pk/asn1/der/utf8/der_encode_utf8_string.c
src/ltc/pk/asn1/der/utf8/der_length_utf8_string.c
+src/ltc/pk/asn1/x509/x509_decode_subject_public_key_info.c
+src/ltc/pk/asn1/x509/x509_encode_subject_public_key_info.c
src/ltc/pk/dh/dh.c
src/ltc/pk/dh/dh_check_pubkey.c
src/ltc/pk/dh/dh_export.c
@@ -458,33 +472,29 @@ src/ltc/pk/ecc/ecc.c
src/ltc/pk/ecc/ecc_ansi_x963_export.c
src/ltc/pk/ecc/ecc_ansi_x963_import.c
src/ltc/pk/ecc/ecc_decrypt_key.c
-src/ltc/pk/ecc/ecc_dp_clear.c
-src/ltc/pk/ecc/ecc_dp_fill_from_sets.c
-src/ltc/pk/ecc/ecc_dp_from_oid.c
-src/ltc/pk/ecc/ecc_dp_from_params.c
-src/ltc/pk/ecc/ecc_dp_init.c
-src/ltc/pk/ecc/ecc_dp_set.c
src/ltc/pk/ecc/ecc_encrypt_key.c
src/ltc/pk/ecc/ecc_export.c
-src/ltc/pk/ecc/ecc_export_full.c
-src/ltc/pk/ecc/ecc_export_raw.c
+src/ltc/pk/ecc/ecc_export_openssl.c
src/ltc/pk/ecc/ecc_free.c
+src/ltc/pk/ecc/ecc_get_key.c
+src/ltc/pk/ecc/ecc_get_set.c
src/ltc/pk/ecc/ecc_get_size.c
src/ltc/pk/ecc/ecc_import.c
-src/ltc/pk/ecc/ecc_import_full.c
+src/ltc/pk/ecc/ecc_import_openssl.c
src/ltc/pk/ecc/ecc_import_pkcs8.c
-src/ltc/pk/ecc/ecc_import_raw.c
+src/ltc/pk/ecc/ecc_import_x509.c
src/ltc/pk/ecc/ecc_make_key.c
+src/ltc/pk/ecc/ecc_set_dp.c
+src/ltc/pk/ecc/ecc_set_dp_internal.c
+src/ltc/pk/ecc/ecc_set_key.c
src/ltc/pk/ecc/ecc_shared_secret.c
src/ltc/pk/ecc/ecc_sign_hash.c
src/ltc/pk/ecc/ecc_sizes.c
src/ltc/pk/ecc/ecc_verify_hash.c
-src/ltc/pk/ecc/ecc_verify_key.c
src/ltc/pk/ecc/ltc_ecc_export_point.c
src/ltc/pk/ecc/ltc_ecc_import_point.c
src/ltc/pk/ecc/ltc_ecc_is_point.c
src/ltc/pk/ecc/ltc_ecc_is_point_at_infinity.c
-src/ltc/pk/ecc/ltc_ecc_is_valid_idx.c
src/ltc/pk/ecc/ltc_ecc_map.c
src/ltc/pk/ecc/ltc_ecc_mul2add.c
src/ltc/pk/ecc/ltc_ecc_mulmod.c
@@ -492,6 +502,7 @@ src/ltc/pk/ecc/ltc_ecc_mulmod_timing.c
src/ltc/pk/ecc/ltc_ecc_points.c
src/ltc/pk/ecc/ltc_ecc_projective_add_point.c
src/ltc/pk/ecc/ltc_ecc_projective_dbl_point.c
+src/ltc/pk/ecc/ltc_ecc_verify_key.c
src/ltc/pk/pkcs1/pkcs_1_i2osp.c
src/ltc/pk/pkcs1/pkcs_1_mgf1.c
src/ltc/pk/pkcs1/pkcs_1_oaep_decode.c
@@ -904,6 +915,10 @@ t/digest_blake2s_160.t
t/digest_blake2s_224.t
t/digest_blake2s_256.t
t/digest_chaes.t
+t/digest_keccak224.t
+t/digest_keccak256.t
+t/digest_keccak384.t
+t/digest_keccak512.t
t/digest_md2.t
t/digest_md4.t
t/digest_md5.t
diff --git a/META.json b/META.json
index 63bdfb21..b106d9be 100644
--- a/META.json
+++ b/META.json
@@ -45,6 +45,6 @@
"url" : "https://github.com/DCIT/perl-CryptX"
}
},
- "version" : "0.056",
+ "version" : "0.059",
"x_serialization_backend" : "JSON::PP version 2.94"
}
diff --git a/META.yml b/META.yml
index d3eb3d73..05e7e19d 100644
--- a/META.yml
+++ b/META.yml
@@ -22,5 +22,5 @@ requires:
resources:
bugtracker: https://github.com/DCIT/perl-CryptX/issues
repository: https://github.com/DCIT/perl-CryptX
-version: '0.056'
+version: '0.059'
x_serialization_backend: 'CPAN::Meta::YAML version 0.018'
diff --git a/Makefile.PL b/Makefile.PL
index e23147fb..11f9956a 100644
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -3,38 +3,58 @@ use warnings;
use ExtUtils::MakeMaker;
use Config;
-my @myobjs = map { s|.c$|$Config{obj_ext}|; $_ } grep { $_ !~ m|^src/ltc/\.*tab\.c$| } (
- glob('src/ltm/*.c'),
- glob('src/ltc/*/*.c'),
- glob('src/ltc/*/*/*.c'),
- glob('src/ltc/*/*/*/*.c'),
- glob('src/ltc/*/*/*/*/*.c'),
-);
-my $myextlib = "src/liballinone$Config{lib_ext}";
-my $mycflags = "$Config{ccflags} $Config{cccdlflags} $Config{optimize}";
-
-#FIX: this is particularly useful for Debian https://github.com/DCIT/perl-CryptX/pull/39
-$mycflags .= " $ENV{CFLAGS}" if $ENV{CFLAGS};
-$mycflags .= " $ENV{CPPFLAGS}" if $ENV{CPPFLAGS};
-
-#FIX: gcc with -flto is a trouble maker see https://github.com/DCIT/perl-CryptX/issues/32
-$mycflags =~ s/-flto\b//g;
-
-#FIX: avoid -Wwrite-strings -Wcast-qual -pedantic -pedantic-errors -ansi -std=c89
-$mycflags =~ s/-pedantic\b//g;
-$mycflags =~ s/-pedantic-errors\b//g;
-$mycflags =~ s/-std=c89\b//g;
-$mycflags =~ s/-ansi\b//g;
-$mycflags =~ s/-Wwrite-strings\b//g;
-$mycflags =~ s/-Wcast-qual\b//g;
-
-#FIX: avoid "ar: fatal: Numeric group ID too large" see https://github.com/DCIT/perl-CryptX/issues/33
-my $myarflags = '$(AR_STATIC_ARGS)';
-if ($^O ne 'MSWin32' && $Config{ar}) {
- # for ar's "deterministic mode" we need GNU binutils 2.20+ (2009-10-16)
- my $arver = `$Config{ar} --version 2>/dev/null`;
- my ($maj, $min) = $arver =~ /^GNU ar [^\d]*(\d)\.(\d+)\.\d+/s;
- $myarflags = 'rcD' if ($maj && $min && $maj >= 2 && $min >= 20) || $arver=~ /^BSD ar /;
+my (@EUMM_INC_LIB, $myarflags, $mycflags);
+
+if ($ENV{CRYPTX_CFLAGS} || $ENV{CRYPTX_LDFLAGS}) {
+ # EXPERIMENTAL: use system libraries libtomcrypt + libtommath
+ # e.g.
+ # CRYPTX_LDFLAGS='-L/usr/local/lib -ltommath -ltomcrypt' CRYPTX_CFLAGS='-DLTM_DESC -I/usr/local/include' perl Makefile.PL
+ print "CRYPTX_CFLAGS = $ENV{CRYPTX_CFLAGS}\n" if $ENV{CRYPTX_CFLAGS};
+ print "CRYPTX_LDFLAGS = $ENV{CRYPTX_LDFLAGS}\n" if $ENV{CRYPTX_LDFLAGS};
+ @EUMM_INC_LIB = (
+ INC => $ENV{CRYPTX_CFLAGS},
+ LIBS => [ $ENV{CRYPTX_LDFLAGS} ],
+ );
+}
+else {
+ # PREFERRED: use bundled libtomcrypt + libtommath (from ./src subdir)
+ my @myobjs = map { s|.c$|$Config{obj_ext}|; $_ } grep { $_ !~ m|^src/ltc/\.*tab\.c$| } (
+ glob('src/ltm/*.c'),
+ glob('src/ltc/*/*.c'),
+ glob('src/ltc/*/*/*.c'),
+ glob('src/ltc/*/*/*/*.c'),
+ glob('src/ltc/*/*/*/*/*.c'),
+ );
+ $mycflags = "$Config{ccflags} $Config{cccdlflags} $Config{optimize}";
+
+ #FIX: this is particularly useful for Debian https://github.com/DCIT/perl-CryptX/pull/39
+ $mycflags .= " $ENV{CFLAGS}" if $ENV{CFLAGS};
+ $mycflags .= " $ENV{CPPFLAGS}" if $ENV{CPPFLAGS};
+
+ #FIX: gcc with -flto is a trouble maker see https://github.com/DCIT/perl-CryptX/issues/32
+ $mycflags =~ s/-flto\b//g;
+
+ #FIX: avoid -Wwrite-strings -Wcast-qual -pedantic -pedantic-errors -ansi -std=c89
+ $mycflags =~ s/-pedantic\b//g;
+ $mycflags =~ s/-pedantic-errors\b//g;
+ $mycflags =~ s/-std=c89\b//g;
+ $mycflags =~ s/-ansi\b//g;
+ $mycflags =~ s/-Wwrite-strings\b//g;
+ $mycflags =~ s/-Wcast-qual\b//g;
+
+ #FIX: avoid "ar: fatal: Numeric group ID too large" see https://github.com/DCIT/perl-CryptX/issues/33
+ $myarflags = '$(AR_STATIC_ARGS)';
+ if ($^O ne 'MSWin32' && $Config{ar}) {
+ # for ar's "deterministic mode" we need GNU binutils 2.20+ (2009-10-16)
+ my $arver = `$Config{ar} --version 2>/dev/null`;
+ my ($maj, $min) = $arver =~ /^GNU ar [^\d]*(\d)\.(\d+)\.\d+/s;
+ $myarflags = 'rcD' if ($maj && $min && $maj >= 2 && $min >= 20) || $arver=~ /^BSD ar /;
+ }
+ @EUMM_INC_LIB = (
+ INC => '-DLTM_DESC -Isrc/ltc/headers -Isrc/ltm',
+ MYEXTLIB => "src/liballinone$Config{lib_ext}",
+ clean => { 'FILES' => join(' ', @myobjs, "src/liballinone$Config{lib_ext}") },
+ );
}
my %eumm_args = (
@@ -46,23 +66,10 @@ my %eumm_args = (
LICENSE => 'perl_5',
META_MERGE => { resources => { repository => 'https://github.com/DCIT/perl-CryptX', bugtracker => 'https://github.com/DCIT/perl-CryptX/issues' } },
dist => { 'PREOP' => 'perldoc -u lib/CryptX.pm | pod2markdown > README.md' },
- ($ENV{CRYPTX_CFLAGS} || $ENV{CRYPTX_LDFLAGS})
- ?
- (
- # e.g. CRYPTX_LDFLAGS='-L/usr/local/lib -ltommath -ltomcrypt' CRYPTX_CFLAGS='-DLTM_DESC -I/usr/local/include' perl Makefile.PL
- INC => $ENV{CRYPTX_CFLAGS},
- LIBS => [ $ENV{CRYPTX_LDFLAGS} ],
- )
- :
- (
- # bundled libtomcrypt + libtommath
- INC => '-DLTM_DESC -Isrc/ltc/headers -Isrc/ltm',
- MYEXTLIB => $myextlib,
- clean => { 'FILES' => join(' ', @myobjs, $myextlib) },
- )
+ @EUMM_INC_LIB
);
-my $eumm_ver = eval $ExtUtils::MakeMaker::VERSION;
+my $eumm_ver = eval $ExtUtils::MakeMaker::VERSION;
delete $eumm_args{MIN_PERL_VERSION} if $eumm_ver < 6.48;
delete $eumm_args{META_ADD} if $eumm_ver < 6.46;
delete $eumm_args{META_MERGE} if $eumm_ver < 6.46;
@@ -70,25 +77,25 @@ delete $eumm_args{LICENSE} if $eumm_ver < 6.31;
WriteMakefile(%eumm_args);
-# ARFLAGS=\$(AR_STATIC_ARGS) RANLIB=\$(RANLIB) AR=\$(AR)
-
sub MY::postamble {
- my $myextlib = qq{
+ return "" unless $mycflags && $myarflags;
+
+ my $extra_targets = qq{
\$(MYEXTLIB): src/Makefile
cd src && \$(MAKE) ARFLAGS="$myarflags" RANLIB="\$(RANLIB)" AR="\$(AR)" CC="\$(CC)" LIB_EXT=\$(LIB_EXT) OBJ_EXT=\$(OBJ_EXT) CFLAGS="$mycflags"
};
- $myextlib = qq{
+ $extra_targets = qq{
\$(MYEXTLIB): src/Makefile
cd src && \$(MAKE) -f Makefile.nmake CFLAGS="$mycflags"
} if $^O eq 'MSWin32' && $Config{make} =~ /nmake/ && $Config{cc} =~ /cl/;
- $myextlib = qq{
+ $extra_targets = qq{
\$(MYEXTLIB): src/Makefile
cd src && \$(MAKE) CC="$Config{cc}" CFLAGS="$mycflags"
} if $^O eq 'MSWin32' && $Config{cc} =~ /gcc/;
- my $version_patch = q{
+ $extra_targets .= q{
versionsync:
$(NOECHO) perl _generators/version_patch.pl sync
versioninc:
@@ -107,7 +114,12 @@ openssltest: all
$(NOECHO) perl -Mblib t/openssl/dsa-test.pl
$(NOECHO) perl -Mblib t/openssl/ecc-test.pl
$(NOECHO) perl -Mblib t/openssl/rsa-test.pl
+rebuild-pre:
+ $(RM_F) src/liballinone.a
+ $(TOUCH) CryptX.xs
+rebuild: rebuild-pre all
+
};
- return "$myextlib\n$version_patch";
+ return $extra_targets;
}
diff --git a/README.md b/README.md
index b071bbe4..65cdc1dd 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@ CryptX - Cryptographic toolkit (self-contained, no external libraries needed)
Cryptography in CryptX is based on [https://github.com/libtom/libtomcrypt](https://github.com/libtom/libtomcrypt)
-Currently available modules:
+Available modules:
- Symmetric ciphers - see [Crypt::Cipher](https://metacpan.org/pod/Crypt::Cipher) and related modules
@@ -36,11 +36,12 @@ Currently available modules:
[Crypt::Digest::CHAES](https://metacpan.org/pod/Crypt::Digest::CHAES), [Crypt::Digest::MD2](https://metacpan.org/pod/Crypt::Digest::MD2), [Crypt::Digest::MD4](https://metacpan.org/pod/Crypt::Digest::MD4), [Crypt::Digest::MD5](https://metacpan.org/pod/Crypt::Digest::MD5), [Crypt::Digest::RIPEMD128](https://metacpan.org/pod/Crypt::Digest::RIPEMD128), [Crypt::Digest::RIPEMD160](https://metacpan.org/pod/Crypt::Digest::RIPEMD160),
[Crypt::Digest::RIPEMD256](https://metacpan.org/pod/Crypt::Digest::RIPEMD256), [Crypt::Digest::RIPEMD320](https://metacpan.org/pod/Crypt::Digest::RIPEMD320), [Crypt::Digest::SHA1](https://metacpan.org/pod/Crypt::Digest::SHA1), [Crypt::Digest::SHA224](https://metacpan.org/pod/Crypt::Digest::SHA224), [Crypt::Digest::SHA256](https://metacpan.org/pod/Crypt::Digest::SHA256), [Crypt::Digest::SHA384](https://metacpan.org/pod/Crypt::Digest::SHA384),
[Crypt::Digest::SHA512](https://metacpan.org/pod/Crypt::Digest::SHA512), [Crypt::Digest::SHA512\_224](https://metacpan.org/pod/Crypt::Digest::SHA512_224), [Crypt::Digest::SHA512\_256](https://metacpan.org/pod/Crypt::Digest::SHA512_256), [Crypt::Digest::Tiger192](https://metacpan.org/pod/Crypt::Digest::Tiger192), [Crypt::Digest::Whirlpool](https://metacpan.org/pod/Crypt::Digest::Whirlpool),
+ [Crypt::Digest::Keccak224](https://metacpan.org/pod/Crypt::Digest::Keccak224), [Crypt::Digest::Keccak256](https://metacpan.org/pod/Crypt::Digest::Keccak256), [Crypt::Digest::Keccak384](https://metacpan.org/pod/Crypt::Digest::Keccak384), [Crypt::Digest::Keccak512](https://metacpan.org/pod/Crypt::Digest::Keccak512),
[Crypt::Digest::SHA3\_224](https://metacpan.org/pod/Crypt::Digest::SHA3_224), [Crypt::Digest::SHA3\_256](https://metacpan.org/pod/Crypt::Digest::SHA3_256), [Crypt::Digest::SHA3\_384](https://metacpan.org/pod/Crypt::Digest::SHA3_384), [Crypt::Digest::SHA3\_512](https://metacpan.org/pod/Crypt::Digest::SHA3_512), [Crypt::Digest::SHAKE](https://metacpan.org/pod/Crypt::Digest::SHAKE)
- Checksums
- [Crypt::Checksum](https://metacpan.org/pod/Crypt::Checksum), [Crypt::Checksum::Adler32](https://metacpan.org/pod/Crypt::Checksum::Adler32), [Crypt::Checksum::CRC32](https://metacpan.org/pod/Crypt::Checksum::CRC32)
+ [Crypt::Checksum::Adler32](https://metacpan.org/pod/Crypt::Checksum::Adler32), [Crypt::Checksum::CRC32](https://metacpan.org/pod/Crypt::Checksum::CRC32)
- Message Authentication Codes
@@ -51,9 +52,9 @@ Currently available modules:
[Crypt::PK::RSA](https://metacpan.org/pod/Crypt::PK::RSA), [Crypt::PK::DSA](https://metacpan.org/pod/Crypt::PK::DSA), [Crypt::PK::ECC](https://metacpan.org/pod/Crypt::PK::ECC), [Crypt::PK::DH](https://metacpan.org/pod/Crypt::PK::DH)
-- Cryptographically secure random number generators
+- Cryptographically secure random number generators - see [Crypt::PRNG](https://metacpan.org/pod/Crypt::PRNG) and related modules
- [Crypt::PRNG](https://metacpan.org/pod/Crypt::PRNG), [Crypt::PRNG::Fortuna](https://metacpan.org/pod/Crypt::PRNG::Fortuna), [Crypt::PRNG::Yarrow](https://metacpan.org/pod/Crypt::PRNG::Yarrow), [Crypt::PRNG::RC4](https://metacpan.org/pod/Crypt::PRNG::RC4), [Crypt::PRNG::Sober128](https://metacpan.org/pod/Crypt::PRNG::Sober128), [Crypt::PRNG::ChaCha20](https://metacpan.org/pod/Crypt::PRNG::ChaCha20)
+ [Crypt::PRNG::Fortuna](https://metacpan.org/pod/Crypt::PRNG::Fortuna), [Crypt::PRNG::Yarrow](https://metacpan.org/pod/Crypt::PRNG::Yarrow), [Crypt::PRNG::RC4](https://metacpan.org/pod/Crypt::PRNG::RC4), [Crypt::PRNG::Sober128](https://metacpan.org/pod/Crypt::PRNG::Sober128), [Crypt::PRNG::ChaCha20](https://metacpan.org/pod/Crypt::PRNG::ChaCha20)
- Key derivation functions - PBKDF1, PBKDF2 and HKDF
@@ -69,4 +70,4 @@ This program is free software; you can redistribute it and/or modify it under th
# COPYRIGHT
-Copyright (c) 2013+ DCIT, a.s. [http://www.dcit.cz](http://www.dcit.cz) / Karel Miko
+Copyright (c) 2013+ DCIT, a.s. [https://www.dcit.cz](https://www.dcit.cz) / Karel Miko
diff --git a/inc/CryptX_AuthEnc_CCM.xs.inc b/inc/CryptX_AuthEnc_CCM.xs.inc
index f2be57a1..312feebb 100644
--- a/inc/CryptX_AuthEnc_CCM.xs.inc
+++ b/inc/CryptX_AuthEnc_CCM.xs.inc
@@ -1,7 +1,9 @@
MODULE = CryptX PACKAGE = Crypt::AuthEnc::CCM
+PROTOTYPES: DISABLE
+
Crypt::AuthEnc::CCM
-_new(char * cipher_name, SV * key, SV * nonce, SV * adata, int tag_len, int pt_len)
+new(Class, char * cipher_name, SV * key, SV * nonce, SV * adata, int tag_len, int pt_len)
CODE:
{
unsigned char *k=NULL;
@@ -21,30 +23,27 @@ _new(char * cipher_name, SV * key, SV * nonce, SV * adata, int tag_len, int pt_l
if (!SvPOK(adata)) croak("FATAL: adata must be string/buffer scalar");
h = (unsigned char *) SvPVbyte(adata, h_len);
- id = find_cipher(cipher_name);
+ id = _find_cipher(cipher_name);
if (id == -1) croak("FATAL: find_cipfer failed for '%s'", cipher_name);
- Newz(0, RETVAL, 1, struct ccm_struct);
+ Newz(0, RETVAL, 1, ccm_state);
if (!RETVAL) croak("FATAL: Newz failed");
- rv = ccm_init(&RETVAL->state, id, k, (int)k_len, (int)pt_len, (int)tag_len, (int)h_len); /* XXX-TODO why int? */
+ rv = ccm_init(RETVAL, id, k, (int)k_len, (int)pt_len, (int)tag_len, (int)h_len); /* XXX-TODO why int? */
if (rv != CRYPT_OK) {
Safefree(RETVAL);
croak("FATAL: ccm_init failed: %s", error_to_string(rv));
}
- rv = ccm_add_nonce(&RETVAL->state, n, (unsigned long)n_len);
+ rv = ccm_add_nonce(RETVAL, n, (unsigned long)n_len);
if (rv != CRYPT_OK) {
Safefree(RETVAL);
croak("FATAL: ccm_add_nonce failed: %s", error_to_string(rv));
}
- rv = ccm_add_aad(&RETVAL->state, h, (unsigned long)h_len);
+ rv = ccm_add_aad(RETVAL, h, (unsigned long)h_len);
if (rv != CRYPT_OK) {
Safefree(RETVAL);
croak("FATAL: ccm_add_aad failed: %s", error_to_string(rv));
}
- RETVAL->direction = -1;
- RETVAL->tag_len = tag_len;
- RETVAL->pt_len = pt_len;
}
OUTPUT:
RETVAL
@@ -57,9 +56,9 @@ DESTROY(Crypt::AuthEnc::CCM self)
Crypt::AuthEnc::CCM
clone(Crypt::AuthEnc::CCM self)
CODE:
- Newz(0, RETVAL, 1, struct ccm_struct);
+ Newz(0, RETVAL, 1, ccm_state);
if (!RETVAL) croak("FATAL: Newz failed");
- Copy(&self->state, &RETVAL->state, 1, struct ccm_struct);
+ Copy(self, RETVAL, 1, ccm_state);
OUTPUT:
RETVAL
@@ -76,21 +75,15 @@ encrypt_add(Crypt::AuthEnc::CCM self, SV * data)
RETVAL = newSVpvn("", 0);
}
else {
- if (self->direction == -1) self->direction = CCM_ENCRYPT;
- if (self->direction != CCM_ENCRYPT) {
- croak("FATAL: encrypt_add failed: wrong direction");
- }
- if (self->pt_len < in_data_len) croak("FATAL: encrypt_add failed: pt_len mismatch");
- RETVAL = NEWSV(0, in_data_len);
+ RETVAL = NEWSV(0, in_data_len); /* avoid zero! */
SvPOK_only(RETVAL);
SvCUR_set(RETVAL, in_data_len);
out_data = (unsigned char *)SvPVX(RETVAL);
- rv = ccm_process(&self->state, in_data, (unsigned long)in_data_len, out_data, self->direction);
+ rv = ccm_process(self, in_data, (unsigned long)in_data_len, out_data, CCM_ENCRYPT);
if (rv != CRYPT_OK) {
SvREFCNT_dec(RETVAL);
croak("FATAL: ccm_process failed: %s", error_to_string(rv));
}
- self->pt_len -= (unsigned long)in_data_len;
}
}
OUTPUT:
@@ -109,21 +102,15 @@ decrypt_add(Crypt::AuthEnc::CCM self, SV * data)
RETVAL = newSVpvn("", 0);
}
else {
- if (self->direction == -1) self->direction = CCM_DECRYPT;
- if (self->direction != CCM_DECRYPT) {
- croak("FATAL: decrypt_add failed: wrong direction");
- }
- if (self->pt_len < in_data_len) croak("FATAL: decrypt_add failed: pt_len mismatch");
- RETVAL = NEWSV(0, in_data_len);
+ RETVAL = NEWSV(0, in_data_len); /* avoid zero! */
SvPOK_only(RETVAL);
SvCUR_set(RETVAL, in_data_len);
out_data = (unsigned char *)SvPVX(RETVAL);
- rv = ccm_process(&self->state, out_data, (unsigned long)in_data_len, in_data, CCM_DECRYPT);
+ rv = ccm_process(self, out_data, (unsigned long)in_data_len, in_data, CCM_DECRYPT);
if (rv != CRYPT_OK) {
SvREFCNT_dec(RETVAL);
croak("FATAL: ccm_process failed: %s", error_to_string(rv));
}
- self->pt_len -= (unsigned long)in_data_len;
}
}
OUTPUT:
@@ -135,13 +122,9 @@ encrypt_done(Crypt::AuthEnc::CCM self)
{
int rv;
unsigned char tag[MAXBLOCKSIZE];
- unsigned long tag_len = self->tag_len;
+ unsigned long tag_len = MAXBLOCKSIZE;
- if (self->direction != CCM_ENCRYPT) {
- croak("FATAL: encrypt_done failed: wrong direction");
- }
- if (self->pt_len != 0) croak("FATAL: encrypt_done failed: pt_len mismatch");
- rv = ccm_done(&self->state, tag, &tag_len);
+ rv = ccm_done(self, tag, &tag_len);
if (rv != CRYPT_OK) croak("FATAL: ccm_done failed: %s", error_to_string(rv));
XPUSHs(sv_2mortal(newSVpvn((char*)tag, tag_len)));
}
@@ -152,15 +135,11 @@ decrypt_done(Crypt::AuthEnc::CCM self, ...)
{
int rv;
unsigned char tag[MAXBLOCKSIZE];
- unsigned long tag_len = self->tag_len;
+ unsigned long tag_len = MAXBLOCKSIZE;
STRLEN expected_tag_len;
unsigned char *expected_tag;
- if (self->direction != CCM_DECRYPT) {
- croak("FATAL: decrypt_done failed: wrong direction");
- }
- if (self->pt_len != 0) croak("FATAL: decrypt_done failed: pt_len mismatch");
- rv = ccm_done(&self->state, tag, &tag_len);
+ rv = ccm_done(self, tag, &tag_len);
if (rv != CRYPT_OK) croak("FATAL: ccm_done failed: %s", error_to_string(rv));
if (items == 1) {
XPUSHs(sv_2mortal(newSVpvn((char*)tag, tag_len)));
@@ -179,3 +158,73 @@ decrypt_done(Crypt::AuthEnc::CCM self, ...)
}
}
}
+
+void
+ccm_encrypt_authenticate(char *cipher_name, SV *key, SV *nonce, SV *header, unsigned long tag_len, SV *plaintext)
+ PPCODE:
+ {
+ STRLEN k_len = 0, n_len = 0, h_len = 0, pt_len = 0;
+ unsigned char *k = NULL, *n = NULL, *h = NULL, *pt = NULL;
+ int rv, id;
+ unsigned char tag[MAXBLOCKSIZE];
+ SV *output;
+
+ if (SvPOK(key)) k = (unsigned char *) SvPVbyte(key, k_len);
+ if (SvPOK(nonce)) n = (unsigned char *) SvPVbyte(nonce, n_len);
+ if (SvPOK(plaintext)) pt = (unsigned char *) SvPVbyte(plaintext, pt_len);
+ if (SvPOK(header)) h = (unsigned char *) SvPVbyte(header, h_len);
+
+ id = _find_cipher(cipher_name);
+ if(id==-1) croak("FATAL: find_cipfer failed for '%s'", cipher_name);
+ output = NEWSV(0, pt_len > 0 ? pt_len : 1); /* avoid zero! */
+ SvPOK_only(output);
+ SvCUR_set(output, pt_len);
+ if(tag_len < 4 || tag_len > 16) tag_len = 16;
+
+ rv = ccm_memory(id, k, (unsigned long)k_len, NULL, n, (unsigned long)n_len, h, (unsigned long)h_len,
+ pt, (unsigned long)pt_len, (unsigned char *)SvPVX(output), tag, &tag_len, CCM_ENCRYPT);
+
+ if (rv != CRYPT_OK) {
+ SvREFCNT_dec(output);
+ croak("FATAL: ccm_memory failed: %s", error_to_string(rv));
+ }
+ XPUSHs(sv_2mortal(output));
+ XPUSHs(sv_2mortal(newSVpvn((char*)tag, tag_len)));
+ }
+
+void
+ccm_decrypt_verify(char *cipher_name, SV *key, SV *nonce, SV *header, SV *ciphertext, SV *tagsv)
+ PPCODE:
+ {
+ STRLEN k_len = 0, n_len = 0, h_len = 0, ct_len = 0, t_len = 0;
+ unsigned char *k = NULL, *n = NULL, *h = NULL, *ct = NULL, *t = NULL;
+ int rv, id;
+ unsigned char tag[MAXBLOCKSIZE];
+ unsigned long tag_len;
+ SV *output;
+
+ if (SvPOK(key)) k = (unsigned char *) SvPVbyte(key, k_len);
+ if (SvPOK(nonce)) n = (unsigned char *) SvPVbyte(nonce, n_len);
+ if (SvPOK(ciphertext)) ct = (unsigned char *) SvPVbyte(ciphertext, ct_len);
+ if (SvPOK(tagsv)) t = (unsigned char *) SvPVbyte(tagsv, t_len);
+ if (SvPOK(header)) h = (unsigned char *) SvPVbyte(header, h_len);
+
+ id = _find_cipher(cipher_name);
+ if(id==-1) croak("FATAL: find_cipfer failed for '%s'", cipher_name);
+ output = NEWSV(0, ct_len > 0 ? ct_len : 1); /* avoid zero! */
+ SvPOK_only(output);
+ SvCUR_set(output, ct_len);
+ tag_len = (unsigned long)t_len;
+ Copy(t, tag, t_len, unsigned char);
+
+ rv = ccm_memory(id, k, (unsigned long)k_len, NULL, n, (unsigned long)n_len, h, (unsigned long)h_len,
+ (unsigned char *)SvPVX(output), (unsigned long)ct_len, ct, tag, &tag_len, CCM_DECRYPT);
+
+ if (rv != CRYPT_OK) {
+ SvREFCNT_dec(output);
+ XPUSHs(sv_2mortal(newSVpvn(NULL,0))); /* undef */
+ }
+ else {
+ XPUSHs(sv_2mortal(output));
+ }
+ }
diff --git a/inc/CryptX_AuthEnc_ChaCha20Poly1305.xs.inc b/inc/CryptX_AuthEnc_ChaCha20Poly1305.xs.inc
index 7b8ff58d..8a32ef49 100644
--- a/inc/CryptX_AuthEnc_ChaCha20Poly1305.xs.inc
+++ b/inc/CryptX_AuthEnc_ChaCha20Poly1305.xs.inc
@@ -1,7 +1,9 @@
MODULE = CryptX PACKAGE = Crypt::AuthEnc::ChaCha20Poly1305
+PROTOTYPES: DISABLE
+
Crypt::AuthEnc::ChaCha20Poly1305
-_new(SV * key, SV * nonce = NULL)
+new(Class, SV * key, SV * nonce = NULL)
CODE:
{
int rv;
@@ -15,17 +17,17 @@ _new(SV * key, SV * nonce = NULL)
iv = (unsigned char *) SvPVbyte(nonce, iv_len);
}
- Newz(0, RETVAL, 1, struct chacha20poly1305_struct);
+ Newz(0, RETVAL, 1, chacha20poly1305_state);
if (!RETVAL) croak("FATAL: Newz failed");
- rv = chacha20poly1305_init(&RETVAL->state, k, (unsigned long)k_len);
+ rv = chacha20poly1305_init(RETVAL, k, (unsigned long)k_len);
if (rv != CRYPT_OK) {
Safefree(RETVAL);
croak("FATAL: chacha20poly1305_init failed: %s", error_to_string(rv));
}
if (iv && iv_len > 0) {
- rv = chacha20poly1305_setiv(&RETVAL->state, iv, (unsigned long)iv_len);
+ rv = chacha20poly1305_setiv(RETVAL, iv, (unsigned long)iv_len);
if (rv != CRYPT_OK) {
Safefree(RETVAL);
croak("FATAL: chacha20poly1305_setiv failed: %s", error_to_string(rv));
@@ -43,9 +45,9 @@ DESTROY(Crypt::AuthEnc::ChaCha20Poly1305 self)
Crypt::AuthEnc::ChaCha20Poly1305
clone(Crypt::AuthEnc::ChaCha20Poly1305 self)
CODE:
- Newz(0, RETVAL, 1, struct chacha20poly1305_struct);
+ Newz(0, RETVAL, 1, chacha20poly1305_state);
if (!RETVAL) croak("FATAL: Newz failed");
- Copy(&self->state, &RETVAL->state, 1, struct chacha20poly1305_struct);
+ Copy(self, RETVAL, 1, chacha20poly1305_state);
OUTPUT:
RETVAL
@@ -59,7 +61,7 @@ set_iv(Crypt::AuthEnc::ChaCha20Poly1305 self, SV * nonce)
if (!SvPOK(nonce)) croak("FATAL: nonce must be string/buffer scalar");
iv = (unsigned char *) SvPVbyte(nonce, iv_len);
- rv = chacha20poly1305_setiv(&self->state, iv, (unsigned long)iv_len);
+ rv = chacha20poly1305_setiv(self, iv, (unsigned long)iv_len);
if (rv != CRYPT_OK) croak("FATAL: chacha20poly1305_setiv failed: %s", error_to_string(rv));
XPUSHs(ST(0)); /* return self */;
}
@@ -74,7 +76,7 @@ set_iv_rfc7905(Crypt::AuthEnc::ChaCha20Poly1305 self, SV * nonce, UV seqnum)
if (!SvPOK(nonce)) croak("FATAL: nonce must be string/buffer scalar");
iv = (unsigned char *) SvPVbyte(nonce, iv_len);
- rv = chacha20poly1305_setiv_rfc7905(&self->state, iv, (unsigned long)iv_len, (ulong64)seqnum);
+ rv = chacha20poly1305_setiv_rfc7905(self, iv, (unsigned long)iv_len, (ulong64)seqnum);
if (rv != CRYPT_OK) croak("FATAL: chacha20poly1305_setiv_rfc7905 failed: %s", error_to_string(rv));
XPUSHs(ST(0)); /* return self */
}
@@ -88,7 +90,7 @@ adata_add(Crypt::AuthEnc::ChaCha20Poly1305 self, SV * data)
unsigned char *in_data;
in_data = (unsigned char *)SvPVbyte(data, in_data_len);
- rv = chacha20poly1305_add_aad(&self->state, in_data, (unsigned long)in_data_len);
+ rv = chacha20poly1305_add_aad(self, in_data, (unsigned long)in_data_len);
if (rv != CRYPT_OK) croak("FATAL: chacha20poly1305_add_aad failed: %s", error_to_string(rv));
XPUSHs(ST(0)); /* return self */
}
@@ -106,11 +108,11 @@ decrypt_add(Crypt::AuthEnc::ChaCha20Poly1305 self, SV * data)
RETVAL = newSVpvn("", 0);
}
else {
- RETVAL = NEWSV(0, in_data_len);
+ RETVAL = NEWSV(0, in_data_len); /* avoid zero! */
SvPOK_only(RETVAL);
SvCUR_set(RETVAL, in_data_len);
out_data = (unsigned char *)SvPVX(RETVAL);
- rv = chacha20poly1305_decrypt(&self->state, in_data, (unsigned long)in_data_len, out_data);
+ rv = chacha20poly1305_decrypt(self, in_data, (unsigned long)in_data_len, out_data);
if (rv != CRYPT_OK) {
SvREFCNT_dec(RETVAL);
croak("FATAL: chacha20poly1305_decrypt failed: %s", error_to_string(rv));
@@ -133,11 +135,11 @@ encrypt_add(Crypt::AuthEnc::ChaCha20Poly1305 self, SV * data)
RETVAL = newSVpvn("", 0);
}
else {
- RETVAL = NEWSV(0, in_data_len);
+ RETVAL = NEWSV(0, in_data_len); /* avoid zero! */
SvPOK_only(RETVAL);
SvCUR_set(RETVAL, in_data_len);
out_data = (unsigned char *)SvPVX(RETVAL);
- rv = chacha20poly1305_encrypt(&self->state, in_data, (unsigned long)in_data_len, out_data);
+ rv = chacha20poly1305_encrypt(self, in_data, (unsigned long)in_data_len, out_data);
if (rv != CRYPT_OK) {
SvREFCNT_dec(RETVAL);
croak("FATAL: chacha20poly1305_encrypt failed: %s", error_to_string(rv));
@@ -155,7 +157,7 @@ encrypt_done(Crypt::AuthEnc::ChaCha20Poly1305 self)
unsigned char tag[MAXBLOCKSIZE];
unsigned long tag_len = sizeof(tag);
- rv = chacha20poly1305_done(&self->state, tag, &tag_len);
+ rv = chacha20poly1305_done(self, tag, &tag_len);
if (rv != CRYPT_OK) croak("FATAL: chacha20poly1305_done failed: %s", error_to_string(rv));
XPUSHs(sv_2mortal(newSVpvn((char*)tag, tag_len)));
}
@@ -170,7 +172,7 @@ decrypt_done(Crypt::AuthEnc::ChaCha20Poly1305 self, ...)
STRLEN expected_tag_len;
unsigned char *expected_tag;
- rv = chacha20poly1305_done(&self->state, tag, &tag_len);
+ rv = chacha20poly1305_done(self, tag, &tag_len);
if (rv != CRYPT_OK) croak("FATAL: chacha20poly1305_done failed: %s", error_to_string(rv));
if (items == 1) {
XPUSHs(sv_2mortal(newSVpvn((char*)tag, tag_len)));
@@ -189,3 +191,71 @@ decrypt_done(Crypt::AuthEnc::ChaCha20Poly1305 self, ...)
}
}
}
+
+void
+chacha20poly1305_encrypt_authenticate(SV *key, SV *nonce, SV *header, SV *plaintext)
+ PPCODE:
+ {
+ STRLEN k_len = 0, n_len = 0, h_len = 0, pt_len = 0;
+ unsigned char *k = NULL, *n = NULL, *h = NULL, *pt = NULL;
+ int rv;
+ unsigned char tag[MAXBLOCKSIZE];
+ unsigned long tag_len = sizeof(tag);
+ SV *output;
+
+ if (SvPOK(key)) k = (unsigned char *) SvPVbyte(key, k_len);
+ if (SvPOK(nonce)) n = (unsigned char *) SvPVbyte(nonce, n_len);
+ if (SvPOK(plaintext)) pt = (unsigned char *) SvPVbyte(plaintext, pt_len);
+ if (SvPOK(header)) h = (unsigned char *) SvPVbyte(header, h_len);
+
+ output = NEWSV(0, pt_len > 0 ? pt_len : 1); /* avoid zero! */
+ SvPOK_only(output);
+ SvCUR_set(output, pt_len);
+
+ rv = chacha20poly1305_memory(k, (unsigned long)k_len, n, (unsigned long)n_len, h, (unsigned long)h_len,
+ pt, (unsigned long)pt_len, (unsigned char *)SvPVX(output), tag, &tag_len,
+ CHACHA20POLY1305_ENCRYPT);
+
+ if (rv != CRYPT_OK) {
+ SvREFCNT_dec(output);
+ croak("FATAL: ccm_memory failed: %s", error_to_string(rv));
+ }
+ XPUSHs(sv_2mortal(output));
+ XPUSHs(sv_2mortal(newSVpvn((char*)tag, tag_len)));
+ }
+
+void
+chacha20poly1305_decrypt_verify(SV *key, SV *nonce, SV *header, SV *ciphertext, SV *tagsv)
+ PPCODE:
+ {
+ STRLEN k_len = 0, n_len = 0, h_len = 0, ct_len = 0, t_len = 0;
+ unsigned char *k = NULL, *n = NULL, *h = NULL, *ct = NULL, *t = NULL;
+ int rv;
+ unsigned char tag[MAXBLOCKSIZE];
+ unsigned long tag_len;
+ SV *output;
+
+ if (SvPOK(key)) k = (unsigned char *) SvPVbyte(key, k_len);
+ if (SvPOK(nonce)) n = (unsigned char *) SvPVbyte(nonce, n_len);
+ if (SvPOK(ciphertext)) ct = (unsigned char *) SvPVbyte(ciphertext, ct_len);
+ if (SvPOK(tagsv)) t = (unsigned char *) SvPVbyte(tagsv, t_len);
+ if (SvPOK(header)) h = (unsigned char *) SvPVbyte(header, h_len);
+
+ output = NEWSV(0, ct_len > 0 ? ct_len : 1); /* avoid zero! */
+ SvPOK_only(output);
+ SvCUR_set(output, ct_len);
+ tag_len = (unsigned long)t_len;
+ Copy(t, tag, t_len, unsigned char);
+
+ rv = chacha20poly1305_memory(k, (unsigned long)k_len, n, (unsigned long)n_len, h, (unsigned long)h_len,
+ ct, (unsigned long)ct_len, (unsigned char *)SvPVX(output), tag, &tag_len,
+ CHACHA20POLY1305_DECRYPT);
+
+ if (rv != CRYPT_OK) {
+ SvREFCNT_dec(output);
+ XPUSHs(sv_2mortal(newSVpvn(NULL,0))); /* undef */
+ }
+ else {
+ XPUSHs(sv_2mortal(output));
+ }
+ }
diff --git a/inc/CryptX_AuthEnc_EAX.xs.inc b/inc/CryptX_AuthEnc_EAX.xs.inc
index dc2d619c..54762e2d 100644
--- a/inc/CryptX_AuthEnc_EAX.xs.inc
+++ b/inc/CryptX_AuthEnc_EAX.xs.inc
@@ -1,7 +1,9 @@
MODULE = CryptX PACKAGE = Crypt::AuthEnc::EAX
+PROTOTYPES: DISABLE
+
Crypt::AuthEnc::EAX
-_new(char * cipher_name, SV * key, SV * nonce, SV * adata=&PL_sv_undef)
+new(Class, char * cipher_name, SV * key, SV * nonce, SV * adata=&PL_sv_undef)
CODE:
{
STRLEN k_len=0;
@@ -21,13 +23,13 @@ _new(char * cipher_name, SV * key, SV * nonce, SV * adata=&PL_sv_undef)
h = (unsigned char *) SvPVbyte(adata, h_len);
}
- id = find_cipher(cipher_name);
+ id = _find_cipher(cipher_name);
if (id == -1) croak("FATAL: find_cipfer failed for '%s'", cipher_name);
- Newz(0, RETVAL, 1, struct eax_struct);
+ Newz(0, RETVAL, 1, eax_state);
if (!RETVAL) croak("FATAL: Newz failed");
- rv = eax_init(&RETVAL->state, id, k, (unsigned long)k_len, n, (unsigned long)n_len, h, (unsigned long)h_len);
+ rv = eax_init(RETVAL, id, k, (unsigned long)k_len, n, (unsigned long)n_len, h, (unsigned long)h_len);
if (rv != CRYPT_OK) {
Safefree(RETVAL);
croak("FATAL: eax setup failed: %s", error_to_string(rv));
@@ -44,9 +46,9 @@ DESTROY(Crypt::AuthEnc::EAX self)
Crypt::AuthEnc::EAX
clone(Crypt::AuthEnc::EAX self)
CODE:
- Newz(0, RETVAL, 1, struct eax_struct);
+ Newz(0, RETVAL, 1, eax_state);
if (!RETVAL) croak("FATAL: Newz failed");
- Copy(&self->state, &RETVAL->state, 1, struct eax_struct);
+ Copy(self, RETVAL, 1, eax_state);
OUTPUT:
RETVAL
@@ -63,11 +65,11 @@ encrypt_add(Crypt::AuthEnc::EAX self, SV * data)
RETVAL = newSVpvn("", 0);
}
else {
- RETVAL = NEWSV(0, in_data_len);
+ RETVAL = NEWSV(0, in_data_len); /* avoid zero! */
SvPOK_only(RETVAL);
SvCUR_set(RETVAL, in_data_len);
out_data = (unsigned char *)SvPVX(RETVAL);
- rv = eax_encrypt(&self->state, in_data, out_data, (unsigned long)in_data_len);
+ rv = eax_encrypt(self, in_data, out_data, (unsigned long)in_data_len);
if (rv != CRYPT_OK) {
SvREFCNT_dec(RETVAL);
croak("FATAL: eax_encrypt failed: %s", error_to_string(rv));
@@ -90,11 +92,11 @@ decrypt_add(Crypt::AuthEnc::EAX self, SV * data)
RETVAL = newSVpvn("", 0);
}
else {
- RETVAL = NEWSV(0, in_data_len);
+ RETVAL = NEWSV(0, in_data_len); /* avoid zero! */
SvPOK_only(RETVAL);
SvCUR_set(RETVAL, in_data_len);
out_data = (unsigned char *)SvPVX(RETVAL);
- rv = eax_decrypt(&self->state, in_data, out_data, (unsigned long)in_data_len);
+ rv = eax_decrypt(self, in_data, out_data, (unsigned long)in_data_len);
if (rv != CRYPT_OK) {
SvREFCNT_dec(RETVAL);
croak("FATAL: eax_decrypt failed: %s", error_to_string(rv));
@@ -112,7 +114,7 @@ encrypt_done(Crypt::AuthEnc::EAX self)
unsigned char tag[MAXBLOCKSIZE];
unsigned long tag_len = sizeof(tag);
- rv = eax_done(&self->state, tag, &tag_len);
+ rv = eax_done(self, tag, &tag_len);
if (rv != CRYPT_OK) croak("FATAL: eax_done failed: %s", error_to_string(rv));
XPUSHs(sv_2mortal(newSVpvn((char*)tag, tag_len)));
}
@@ -127,7 +129,7 @@ decrypt_done(Crypt::AuthEnc::EAX self, ...)
STRLEN expected_tag_len;
unsigned char *expected_tag;
- rv = eax_done(&self->state, tag, &tag_len);
+ rv = eax_done(self, tag, &tag_len);
if (rv != CRYPT_OK) croak("FATAL: eax_done failed: %s", error_to_string(rv));
if (items == 1) {
XPUSHs(sv_2mortal(newSVpvn((char*)tag, tag_len)));
@@ -155,7 +157,78 @@ adata_add(Crypt::AuthEnc::EAX self, SV * adata)
int rv;
unsigned char *h;
h = (unsigned char *)SvPVbyte(adata, h_len);
- rv = eax_addheader(&self->state, h, (unsigned long)h_len);
+ rv = eax_addheader(self, h, (unsigned long)h_len);
if (rv != CRYPT_OK) croak("FATAL: eax_addheader failed: %s", error_to_string(rv));
XPUSHs(ST(0)); /* return self */
}
+
+void
+eax_encrypt_authenticate(char *cipher_name, SV *key, SV *nonce, SV *header, SV *plaintext)
+ PPCODE:
+ {
+ STRLEN k_len = 0, n_len = 0, h_len = 0, pt_len = 0;
+ unsigned char *k = NULL, *n = NULL, *h = NULL, *pt = NULL;
+ int rv, id;
+ unsigned char tag[MAXBLOCKSIZE];
+ unsigned long tag_len = sizeof(tag);
+ SV *output;
+
+ if (SvPOK(key)) k = (unsigned char *) SvPVbyte(key, k_len);
+ if (SvPOK(nonce)) n = (unsigned char *) SvPVbyte(nonce, n_len);
+ if (SvPOK(plaintext)) pt = (unsigned char *) SvPVbyte(plaintext, pt_len);
+ if (SvPOK(header)) h = (unsigned char *) SvPVbyte(header, h_len);
+
+ id = _find_cipher(cipher_name);
+ if(id==-1) croak("FATAL: find_cipfer failed for '%s'", cipher_name);
+ output = NEWSV(0, pt_len > 0 ? pt_len : 1); /* avoid zero! */
+ SvPOK_only(output);
+ SvCUR_set(output, pt_len);
+
+ rv = eax_encrypt_authenticate_memory(id, k, (unsigned long)k_len, n, (unsigned long)n_len,
+ h, (unsigned long)h_len, pt, (unsigned long)pt_len,
+ (unsigned char *)SvPVX(output), tag, &tag_len);
+
+ if (rv != CRYPT_OK) {
+ SvREFCNT_dec(output);
+ croak("FATAL: ccm_memory failed: %s", error_to_string(rv));
+ }
+ XPUSHs(sv_2mortal(output));
+ XPUSHs(sv_2mortal(newSVpvn((char*)tag, tag_len)));
+ }
+
+void
+eax_decrypt_verify(char *cipher_name, SV *key, SV *nonce, SV *header, SV *ciphertext, SV *tagsv)
+ PPCODE:
+ {
+ STRLEN k_len = 0, n_len = 0, h_len = 0, ct_len = 0, t_len = 0;
+ unsigned char *k = NULL, *n = NULL, *h = NULL, *ct = NULL, *t = NULL;
+ int rv, id, stat = 0;
+ unsigned char tag[MAXBLOCKSIZE];
+ unsigned long tag_len;
+ SV *output;
+
+ if (SvPOK(key)) k = (unsigned char *) SvPVbyte(key, k_len);
+ if (SvPOK(nonce)) n = (unsigned char *) SvPVbyte(nonce, n_len);
+ if (SvPOK(ciphertext)) ct = (unsigned char *) SvPVbyte(ciphertext, ct_len);
+ if (SvPOK(tagsv)) t = (unsigned char *) SvPVbyte(tagsv, t_len);
+ if (SvPOK(header)) h = (unsigned char *) SvPVbyte(header, h_len);
+
+ id = _find_cipher(cipher_name);
+ if(id==-1) croak("FATAL: find_cipfer failed for '%s'", cipher_name);
+ output = NEWSV(0, ct_len > 0 ? ct_len : 1); /* avoid zero! */
+ SvPOK_only(output);
+ SvCUR_set(output, ct_len);
+ tag_len = (unsigned long)t_len;
+ Copy(t, tag, t_len, unsigned char);
+
+ rv = eax_decrypt_verify_memory(id, k, (unsigned long)k_len, n, (unsigned long)n_len, h, (unsigned long)h_len,
+ ct, (unsigned long)ct_len, (unsigned char *)SvPVX(output), tag, tag_len, &stat);
+
+ if (rv != CRYPT_OK || stat != 1) {
+ SvREFCNT_dec(output);
+ XPUSHs(sv_2mortal(newSVpvn(NULL,0))); /* undef */
+ }
+ else {
+ XPUSHs(sv_2mortal(output));
+ }
+ }
diff --git a/inc/CryptX_AuthEnc_GCM.xs.inc b/inc/CryptX_AuthEnc_GCM.xs.inc
index 5ea007b8..0618a2c9 100644
--- a/inc/CryptX_AuthEnc_GCM.xs.inc
+++ b/inc/CryptX_AuthEnc_GCM.xs.inc
@@ -1,7 +1,9 @@
MODULE = CryptX PACKAGE = Crypt::AuthEnc::GCM
+PROTOTYPES: DISABLE
+
Crypt::AuthEnc::GCM
-_new(char * cipher_name, SV * key, SV * nonce = NULL)
+new(Class, char * cipher_name, SV * key, SV * nonce = NULL)
CODE:
{
STRLEN k_len = 0, iv_len = 0;
@@ -15,20 +17,20 @@ _new(char * cipher_name, SV * key, SV * nonce = NULL)
iv = (unsigned char *)SvPVbyte(nonce, iv_len);
}
- id = find_cipher(cipher_name);
+ id = _find_cipher(cipher_name);
if (id == -1) croak("FATAL: find_cipfer failed for '%s'", cipher_name);
- Newz(0, RETVAL, 1, struct gcm_struct);
+ Newz(0, RETVAL, 1, gcm_state);
if (!RETVAL) croak("FATAL: Newz failed");
- rv = gcm_init(&RETVAL->state, id, k, (unsigned long)k_len);
+ rv = gcm_init(RETVAL, id, k, (unsigned long)k_len);
if (rv != CRYPT_OK) {
Safefree(RETVAL);
croak("FATAL: gcm_init failed: %s", error_to_string(rv));
}
if (iv && iv_len > 0) {
- rv = gcm_add_iv(&RETVAL->state, iv, (unsigned long)iv_len);
+ rv = gcm_add_iv(RETVAL, iv, (unsigned long)iv_len);
if (rv != CRYPT_OK) {
Safefree(RETVAL);
croak("FATAL: gcm_add_iv failed: %s", error_to_string(rv));
@@ -46,9 +48,9 @@ DESTROY(Crypt::AuthEnc::GCM self)
Crypt::AuthEnc::GCM
clone(Crypt::AuthEnc::GCM self)
CODE:
- Newz(0, RETVAL, 1, struct gcm_struct);
+ Newz(0, RETVAL, 1, gcm_state);
if (!RETVAL) croak("FATAL: Newz failed");
- Copy(&self->state, &RETVAL->state, 1, struct gcm_struct);
+ Copy(self, RETVAL, 1, gcm_state);
OUTPUT:
RETVAL
@@ -57,7 +59,7 @@ reset(Crypt::AuthEnc::GCM self)
PPCODE:
{
int rv;
- rv = gcm_reset(&self->state);
+ rv = gcm_reset(self);
if (rv != CRYPT_OK) croak("FATAL: gcm_reset failed: %s", error_to_string(rv));
XPUSHs(ST(0)); /* return self */
}
@@ -76,11 +78,11 @@ encrypt_add(Crypt::AuthEnc::GCM self, SV * data)
}
else
{
- RETVAL = NEWSV(0, in_data_len);
+ RETVAL = NEWSV(0, in_data_len); /* avoid zero! */
SvPOK_only(RETVAL);
SvCUR_set(RETVAL, in_data_len);
out_data = (unsigned char *)SvPVX(RETVAL);
- rv = gcm_process(&self->state, in_data, (unsigned long)in_data_len, out_data, GCM_ENCRYPT);
+ rv = gcm_process(self, in_data, (unsigned long)in_data_len, out_data, GCM_ENCRYPT);
if (rv != CRYPT_OK) {
SvREFCNT_dec(RETVAL);
croak("FATAL: encrypt_add/gcm_process failed: %s", error_to_string(rv));
@@ -99,7 +101,7 @@ iv_add(Crypt::AuthEnc::GCM self, SV * data)
unsigned char *in_data;
in_data = (unsigned char *)SvPVbyte(data, in_data_len);
- rv = gcm_add_iv(&self->state, in_data, (unsigned long)in_data_len);
+ rv = gcm_add_iv(self, in_data, (unsigned long)in_data_len);
if (rv != CRYPT_OK) croak("FATAL: gcm_add_iv failed: %s", error_to_string(rv));
XPUSHs(ST(0)); /* return self */
}
@@ -113,7 +115,7 @@ adata_add(Crypt::AuthEnc::GCM self, SV * data)
unsigned char *in_data;
in_data = (unsigned char *)SvPVbyte(data, in_data_len);
- rv = gcm_add_aad(&self->state, in_data, (unsigned long)in_data_len);
+ rv = gcm_add_aad(self, in_data, (unsigned long)in_data_len);
if (rv != CRYPT_OK) croak("FATAL: gcm_add_aad failed: %s", error_to_string(rv));
XPUSHs(ST(0)); /* return self */
}
@@ -131,11 +133,11 @@ decrypt_add(Crypt::AuthEnc::GCM self, SV * data)
RETVAL = newSVpvn("", 0);
}
else {
- RETVAL = NEWSV(0, in_data_len);
+ RETVAL = NEWSV(0, in_data_len); /* avoid zero! */
SvPOK_only(RETVAL);
SvCUR_set(RETVAL, in_data_len);
out_data = (unsigned char *)SvPVX(RETVAL);
- rv = gcm_process(&self->state, out_data, (unsigned long)in_data_len, in_data, GCM_DECRYPT);
+ rv = gcm_process(self, out_data, (unsigned long)in_data_len, in_data, GCM_DECRYPT);
if (rv != CRYPT_OK) {
SvREFCNT_dec(RETVAL);
croak("FATAL: encrypt_add/gcm_process failed: %s", error_to_string(rv));
@@ -154,7 +156,7 @@ encrypt_done(Crypt::AuthEnc::GCM self)
unsigned char tag[MAXBLOCKSIZE];
unsigned long tag_len = sizeof(tag);
- rv = gcm_done(&self->state, tag, &tag_len);
+ rv = gcm_done(self, tag, &tag_len);
if (rv != CRYPT_OK) croak("FATAL: gcm_done failed: %s", error_to_string(rv));
XPUSHs(sv_2mortal(newSVpvn((char*)tag, tag_len)));
}
@@ -169,7 +171,7 @@ decrypt_done(Crypt::AuthEnc::GCM self, ...)
STRLEN expected_tag_len;
unsigned char *expected_tag;
- rv = gcm_done(&self->state, tag, &tag_len);
+ rv = gcm_done(self, tag, &tag_len);
if (rv != CRYPT_OK) croak("FATAL: gcm_done failed: %s", error_to_string(rv));
if (items == 1) {
XPUSHs(sv_2mortal(newSVpvn((char*)tag, tag_len)));
@@ -188,3 +190,73 @@ decrypt_done(Crypt::AuthEnc::GCM self, ...)
}
}
}
+
+void
+gcm_encrypt_authenticate(char *cipher_name, SV *key, SV *nonce, SV *header = NULL, SV *plaintext)
+ PPCODE:
+ {
+ STRLEN k_len = 0, n_len = 0, h_len = 0, pt_len = 0;
+ unsigned char *k = NULL, *n = NULL, *h = NULL, *pt = NULL;
+ int rv, id;
+ unsigned char tag[MAXBLOCKSIZE];
+ unsigned long tag_len = sizeof(tag);
+ SV *output;
+
+ if (SvPOK(key)) k = (unsigned char *) SvPVbyte(key, k_len);
+ if (SvPOK(nonce)) n = (unsigned char *) SvPVbyte(nonce, n_len);
+ if (SvPOK(plaintext)) pt = (unsigned char *) SvPVbyte(plaintext, pt_len);
+ if (SvPOK(header)) h = (unsigned char *) SvPVbyte(header, h_len);
+
+ id = _find_cipher(cipher_name);
+ if(id==-1) croak("FATAL: find_cipfer failed for '%s'", cipher_name);
+ output = NEWSV(0, pt_len > 0 ? pt_len : 1); /* avoid zero! */
+ SvPOK_only(output);
+ SvCUR_set(output, pt_len);
+
+ rv = gcm_memory(id, k, (unsigned long)k_len, n, (unsigned long)n_len, h, (unsigned long)h_len,
+ pt, (unsigned long)pt_len, (unsigned char *)SvPVX(output), tag, &tag_len, GCM_ENCRYPT);
+
+ if (rv != CRYPT_OK) {
+ SvREFCNT_dec(output);
+ croak("FATAL: ccm_memory failed: %s", error_to_string(rv));
+ }
+ XPUSHs(sv_2mortal(output));
+ XPUSHs(sv_2mortal(newSVpvn((char*)tag, tag_len)));
+ }
+
+void
+gcm_decrypt_verify(char *cipher_name, SV *key, SV *nonce, SV *header, SV *ciphertext, SV *tagsv)
+ PPCODE:
+ {
+ STRLEN k_len = 0, n_len = 0, h_len = 0, ct_len = 0, t_len = 0;
+ unsigned char *k = NULL, *n = NULL, *h = NULL, *ct = NULL, *t = NULL;
+ int rv, id;
+ unsigned char tag[MAXBLOCKSIZE];
+ unsigned long tag_len;
+ SV *output;
+
+ if (SvPOK(key)) k = (unsigned char *) SvPVbyte(key, k_len);
+ if (SvPOK(nonce)) n = (unsigned char *) SvPVbyte(nonce, n_len);
+ if (SvPOK(ciphertext)) ct = (unsigned char *) SvPVbyte(ciphertext, ct_len);
+ if (SvPOK(tagsv)) t = (unsigned char *) SvPVbyte(tagsv, t_len);
+ if (SvPOK(header)) h = (unsigned char *) SvPVbyte(header, h_len);
+
+ id = _find_cipher(cipher_name);
+ if(id==-1) croak("FATAL: find_cipfer failed for '%s'", cipher_name);
+ output = NEWSV(0, ct_len > 0 ? ct_len : 1); /* avoid zero! */
+ SvPOK_only(output);
+ SvCUR_set(output, ct_len);
+ tag_len = (unsigned long)t_len;
+ Copy(t, tag, t_len, unsigned char);
+
+ rv = gcm_memory(id, k, (unsigned long)k_len, n, (unsigned long)n_len, h, (unsigned long)h_len,
+ (unsigned char *)SvPVX(output), (unsigned long)ct_len, ct, tag, &tag_len, GCM_DECRYPT);
+
+ if (rv != CRYPT_OK) {
+ SvREFCNT_dec(output);
+ XPUSHs(sv_2mortal(newSVpvn(NULL,0))); /* undef */
+ }
+ else {
+ XPUSHs(sv_2mortal(output));
+ }
+ }
diff --git a/inc/CryptX_AuthEnc_OCB.xs.inc b/inc/CryptX_AuthEnc_OCB.xs.inc
index e5a92cee..8d06e34c 100644
--- a/inc/CryptX_AuthEnc_OCB.xs.inc
+++ b/inc/CryptX_AuthEnc_OCB.xs.inc
@@ -1,7 +1,9 @@
MODULE = CryptX PACKAGE = Crypt::AuthEnc::OCB
+PROTOTYPES: DISABLE
+
Crypt::AuthEnc::OCB
-_new(char * cipher_name, SV * key, SV * nonce, unsigned long taglen)
+new(Class, char * cipher_name, SV * key, SV * nonce, unsigned long taglen)
CODE:
{
STRLEN k_len=0;
@@ -15,13 +17,13 @@ _new(char * cipher_name, SV * key, SV * nonce, unsigned long taglen)
if (!SvPOK(nonce)) croak("FATAL: nonce must be string/buffer scalar");
n = (unsigned char *) SvPVbyte(nonce, n_len);
- id = find_cipher(cipher_name);
+ id = _find_cipher(cipher_name);
if (id == -1) croak("FATAL: find_cipfer failed for '%s'", cipher_name);
- Newz(0, RETVAL, 1, struct ocb_struct);
+ Newz(0, RETVAL, 1, ocb3_state);
if (!RETVAL) croak("FATAL: Newz failed");
- rv = ocb3_init(&RETVAL->state, id, k, (unsigned long)k_len, n, (unsigned long)n_len, taglen);
+ rv = ocb3_init(RETVAL, id, k, (unsigned long)k_len, n, (unsigned long)n_len, taglen);
if (rv != CRYPT_OK) {
Safefree(RETVAL);
croak("FATAL: ocb setup failed: %s", error_to_string(rv));
@@ -38,9 +40,9 @@ DESTROY(Crypt::AuthEnc::OCB self)
Crypt::AuthEnc::OCB
clone(Crypt::AuthEnc::OCB self)
CODE:
- Newz(0, RETVAL, 1, struct ocb_struct);
+ Newz(0, RETVAL, 1, ocb3_state);
if (!RETVAL) croak("FATAL: Newz failed");
- Copy(&self->state, &RETVAL->state, 1, struct ocb_struct);
+ Copy(self, RETVAL, 1, ocb3_state);
OUTPUT:
RETVAL
@@ -55,7 +57,7 @@ adata_add(Crypt::AuthEnc::OCB self, SV * data)
in_data = (unsigned char *)SvPVbyte(data, in_data_len);
if (in_data_len>0) {
- rv = ocb3_add_aad(&self->state, in_data, (unsigned long)in_data_len);
+ rv = ocb3_add_aad(self, in_data, (unsigned long)in_data_len);
if (rv != CRYPT_OK) croak("FATAL: ocb3_add_aad failed: %s", error_to_string(rv));
}
XPUSHs(ST(0)); /* return self */
@@ -77,11 +79,11 @@ encrypt_add(Crypt::AuthEnc::OCB self, SV * data)
if (in_data_len % 16) {
croak ("FATAL: sizeof(data) should be multiple of 16");
}
- RETVAL = NEWSV(0, in_data_len);
+ RETVAL = NEWSV(0, in_data_len); /* avoid zero! */
SvPOK_only(RETVAL);
SvCUR_set(RETVAL, in_data_len);
out_data = (unsigned char *)SvPVX(RETVAL);
- rv = ocb3_encrypt(&self->state, in_data, (unsigned long)in_data_len, out_data);
+ rv = ocb3_encrypt(self, in_data, (unsigned long)in_data_len, out_data);
if (rv != CRYPT_OK) {
SvREFCNT_dec(RETVAL);
croak("FATAL: ocb3_encrypt failed: %s", error_to_string(rv));
@@ -101,18 +103,18 @@ encrypt_last(Crypt::AuthEnc::OCB self, SV * data)
in_data = (unsigned char *)SvPVbyte(data, in_data_len);
if (in_data_len == 0) {
- rv = ocb3_encrypt_last(&self->state, in_data, 0, NULL);
+ rv = ocb3_encrypt_last(self, in_data, 0, NULL);
if (rv != CRYPT_OK) {
croak("FATAL: ocb3_encrypt_last failed: %s", error_to_string(rv));
}
RETVAL = newSVpvn("", 0);
}
else {
- RETVAL = NEWSV(0, in_data_len);
+ RETVAL = NEWSV(0, in_data_len); /* avoid zero! */
SvPOK_only(RETVAL);
SvCUR_set(RETVAL, in_data_len);
out_data = (unsigned char *)SvPVX(RETVAL);
- rv = ocb3_encrypt_last(&self->state, in_data, (unsigned long)in_data_len, out_data);
+ rv = ocb3_encrypt_last(self, in_data, (unsigned long)in_data_len, out_data);
if (rv != CRYPT_OK) {
SvREFCNT_dec(RETVAL);
croak("FATAL: ocb3_encrypt_last failed: %s", error_to_string(rv));
@@ -138,11 +140,11 @@ decrypt_add(Crypt::AuthEnc::OCB self, SV * data)
if (in_data_len % 16) {
croak ("FATAL: sizeof(data) should be multiple of 16");
}
- RETVAL = NEWSV(0, in_data_len);
+ RETVAL = NEWSV(0, in_data_len); /* avoid zero! */
SvPOK_only(RETVAL);
SvCUR_set(RETVAL, in_data_len);
out_data = (unsigned char *)SvPVX(RETVAL);
- rv = ocb3_decrypt(&self->state, in_data, (unsigned long)in_data_len, out_data);
+ rv = ocb3_decrypt(self, in_data, (unsigned long)in_data_len, out_data);
if (rv != CRYPT_OK) {
SvREFCNT_dec(RETVAL);
croak("FATAL: ocb3_decrypt failed: %s", error_to_string(rv));
@@ -162,18 +164,18 @@ decrypt_last(Crypt::AuthEnc::OCB self, SV * data)
in_data = (unsigned char *)SvPVbyte(data, in_data_len);
if (in_data_len == 0) {
- rv = ocb3_decrypt_last(&self->state, in_data, 0, NULL);
+ rv = ocb3_decrypt_last(self, in_data, 0, NULL);
if (rv != CRYPT_OK) {
croak("FATAL: ocb3_encrypt_last failed: %s", error_to_string(rv));
}
RETVAL = newSVpvn("", 0);
}
else {
- RETVAL = NEWSV(0, in_data_len);
+ RETVAL = NEWSV(0, in_data_len); /* avoid zero! */
SvPOK_only(RETVAL);
SvCUR_set(RETVAL, in_data_len);
out_data = (unsigned char *)SvPVX(RETVAL);
- rv = ocb3_decrypt_last(&self->state, in_data, (unsigned long)in_data_len, out_data);
+ rv = ocb3_decrypt_last(self, in_data, (unsigned long)in_data_len, out_data);
if (rv != CRYPT_OK) {
SvREFCNT_dec(RETVAL);
croak("FATAL: ocb3_encrypt_last failed: %s", error_to_string(rv));
@@ -191,7 +193,7 @@ encrypt_done(Crypt::AuthEnc::OCB self)
unsigned char tag[MAXBLOCKSIZE];
unsigned long tag_len = sizeof(tag);
- rv = ocb3_done(&self->state, tag, &tag_len);
+ rv = ocb3_done(self, tag, &tag_len);
if (rv != CRYPT_OK) croak("FATAL: ocb3_done_encrypt failed: %s", error_to_string(rv));
XPUSHs(sv_2mortal(newSVpvn((char*)tag, tag_len)));
@@ -207,7 +209,7 @@ decrypt_done(Crypt::AuthEnc::OCB self, ...)
STRLEN expected_tag_len;
unsigned char *expected_tag;
- rv = ocb3_done(&self->state, tag, &tag_len);
+ rv = ocb3_done(self, tag, &tag_len);
if (rv != CRYPT_OK) croak("FATAL: ocb3_done_decrypt failed: %s", error_to_string(rv));
if (items == 1) {
XPUSHs(sv_2mortal(newSVpvn((char*)tag, tag_len)));
@@ -226,3 +228,71 @@ decrypt_done(Crypt::AuthEnc::OCB self, ...)
}
}
}
+
+void
+ocb_encrypt_authenticate(char *cipher_name, SV *key, SV *nonce, SV *header, unsigned long tag_len, SV *plaintext)
+ PPCODE:
+ {
+ STRLEN k_len = 0, n_len = 0, h_len = 0, pt_len = 0;
+ unsigned char *k = NULL, *n = NULL, *h = NULL, *pt = NULL;
+ int rv, id;
+ unsigned char tag[MAXBLOCKSIZE];
+ SV *output;
+
+ if (SvPOK(key)) k = (unsigned char *) SvPVbyte(key, k_len);
+ if (SvPOK(nonce)) n = (unsigned char *) SvPVbyte(nonce, n_len);
+ if (SvPOK(plaintext)) pt = (unsigned char *) SvPVbyte(plaintext, pt_len);
+ if (SvPOK(header)) h = (unsigned char *) SvPVbyte(header, h_len);
+
+ id = _find_cipher(cipher_name);
+ if(id==-1) croak("FATAL: find_cipfer failed for '%s'", cipher_name);
+ output = NEWSV(0, pt_len > 0 ? pt_len : 1); /* avoid zero! */
+ SvPOK_only(output);
+ SvCUR_set(output, pt_len);
+ if(tag_len < 4 || tag_len > 16) tag_len = 16;
+
+ rv = ocb3_encrypt_authenticate_memory(id, k, (unsigned long)k_len, n, (unsigned long)n_len,
+ h, (unsigned long)h_len, pt, (unsigned long)pt_len,
+ (unsigned char *)SvPVX(output), tag, &tag_len);
+
+ if (rv != CRYPT_OK) {
+ SvREFCNT_dec(output);
+ croak("FATAL: ccm_memory failed: %s", error_to_string(rv));
+ }
+ XPUSHs(sv_2mortal(output));
+ XPUSHs(sv_2mortal(newSVpvn((char*)tag, tag_len)));
+ }
+
+void
+ocb_decrypt_verify(char *cipher_name, SV *key, SV *nonce, SV *header, SV *ciphertext, SV *tagsv)
+ PPCODE:
+ {
+ STRLEN k_len = 0, n_len = 0, h_len = 0, ct_len = 0, t_len = 0;
+ unsigned char *k = NULL, *n = NULL, *h = NULL, *ct = NULL, *t = NULL;
+ int rv, id, stat = 0;
+ SV *output;
+
+ if (SvPOK(key)) k = (unsigned char *) SvPVbyte(key, k_len);
+ if (SvPOK(nonce)) n = (unsigned char *) SvPVbyte(nonce, n_len);
+ if (SvPOK(ciphertext)) ct = (unsigned char *) SvPVbyte(ciphertext, ct_len);
+ if (SvPOK(tagsv)) t = (unsigned char *) SvPVbyte(tagsv, t_len);
+ if (SvPOK(header)) h = (unsigned char *) SvPVbyte(header, h_len);
+
+ id = _find_cipher(cipher_name);
+ if(id==-1) croak("FATAL: find_cipfer failed for '%s'", cipher_name);
+ output = NEWSV(0, ct_len > 0 ? ct_len : 1); /* avoid zero! */
+ SvPOK_only(output);
+ SvCUR_set(output, ct_len);
+
+ rv = ocb3_decrypt_verify_memory(id, k, (unsigned long)k_len, n, (unsigned long)n_len,
+ h, (unsigned long)h_len, ct, (unsigned long)ct_len,
+ (unsigned char *)SvPVX(output), t, (unsigned long)t_len, &stat);
+
+ if (rv != CRYPT_OK || stat != 1) {
+ SvREFCNT_dec(output);
+ XPUSHs(sv_2mortal(newSVpvn(NULL,0))); /* undef */
+ }
+ else {
+ XPUSHs(sv_2mortal(output));
+ }
+ }
diff --git a/inc/CryptX_BigInt_LTM.xs.inc b/inc/CryptX_BigInt_LTM.xs.inc
index e321c385..db760109 100644
--- a/inc/CryptX_BigInt_LTM.xs.inc
+++ b/inc/CryptX_BigInt_LTM.xs.inc
@@ -1,5 +1,6 @@
MODULE = CryptX PACKAGE = Math::BigInt::LTM
+PROTOTYPES: DISABLE
##############################################################################
# _new()
diff --git a/inc/CryptX_Checksum_Adler32.xs.inc b/inc/CryptX_Checksum_Adler32.xs.inc
index f3b7692b..eb30b819 100644
--- a/inc/CryptX_Checksum_Adler32.xs.inc
+++ b/inc/CryptX_Checksum_Adler32.xs.inc
@@ -1,5 +1,7 @@
MODULE = CryptX PACKAGE = Crypt::Checksum::Adler32
+PROTOTYPES: DISABLE
+
Crypt::Checksum::Adler32
new(Class)
CODE:
@@ -51,27 +53,67 @@ add(Crypt::Checksum::Adler32 self, ...)
SV *
digest(Crypt::Checksum::Adler32 self)
+ ALIAS:
+ hexdigest = 1
+ intdigest = 2
CODE:
{
- unsigned char hash[4];
+ int rv;
+ unsigned char hash[4], out[8];
+ unsigned long outlen = 8;
+ unsigned int ui32;
+
adler32_finish(self, hash, 4); /* returns void */
- RETVAL = newSVpvn((char *) hash, 4);
+ if (ix == 1) {
+ rv = _base16_encode(hash, 4, out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base16_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn((char *)out, outlen);
+ }
+ else if (ix == 2) {
+ LOAD32H(ui32, hash);
+ RETVAL = newSVuv(ui32);
+ }
+ else {
+ RETVAL = newSVpvn((char *) hash, 4);
+ }
}
OUTPUT:
RETVAL
SV *
-hexdigest(Crypt::Checksum::Adler32 self)
+adler32_data(...)
+ ALIAS:
+ adler32_data_hex = 1
+ adler32_data_int = 2
CODE:
{
- unsigned long i;
- unsigned char hash[4];
- char hash_hex[4*2 + 1];
- adler32_finish(self, hash, 4); /* returns void */
- hash_hex[0] = '\0';
- for(i=0; i<4; i++) sprintf(&hash_hex[2*i], "%02x", hash[i]);
- RETVAL = newSVpvn(hash_hex, strlen(hash_hex));
+ adler32_state st;
+ int rv, j;
+ unsigned char hash[4], out[8], *in;
+ unsigned long outlen = 8;
+ unsigned int ui32;
+ STRLEN inlen;
+
+ adler32_init(&st);
+ for(j = 0; j < items; j++) {
+ in = (unsigned char *)SvPVbyte(ST(j), inlen);
+ if (inlen > 0) {
+ adler32_update(&st, in, (unsigned long)inlen); /* returns void */
+ }
+ }
+ adler32_finish(&st, hash, 4); /* returns void */
+ if (ix == 1) {
+ rv = _base16_encode(hash, 4, out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base16_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn((char *)out, outlen);
+ }
+ else if (ix == 2) {
+ LOAD32H(ui32, hash);
+ RETVAL = newSVuv(ui32);
+ }
+ else {
+ RETVAL = newSVpvn((char *) hash, 4);
+ }
}
OUTPUT:
RETVAL
-
diff --git a/inc/CryptX_Checksum_CRC32.xs.inc b/inc/CryptX_Checksum_CRC32.xs.inc
index b4d591a7..3c86e7ca 100644
--- a/inc/CryptX_Checksum_CRC32.xs.inc
+++ b/inc/CryptX_Checksum_CRC32.xs.inc
@@ -1,5 +1,7 @@
MODULE = CryptX PACKAGE = Crypt::Checksum::CRC32
+PROTOTYPES: DISABLE
+
Crypt::Checksum::CRC32
new(Class)
CODE:
@@ -51,27 +53,67 @@ add(Crypt::Checksum::CRC32 self, ...)
SV *
digest(Crypt::Checksum::CRC32 self)
+ ALIAS:
+ hexdigest = 1
+ intdigest = 2
CODE:
{
- unsigned char hash[4];
+ int rv;
+ unsigned char hash[4], out[8];
+ unsigned long outlen = 8;
+ unsigned int ui32;
+
crc32_finish(self, hash, 4); /* returns void */
- RETVAL = newSVpvn((char *) hash, 4);
+ if (ix == 1) {
+ rv = _base16_encode(hash, 4, out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base16_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn((char *)out, outlen);
+ }
+ else if (ix == 2) {
+ LOAD32H(ui32, hash);
+ RETVAL = newSVuv(ui32);
+ }
+ else {
+ RETVAL = newSVpvn((char *) hash, 4);
+ }
}
OUTPUT:
RETVAL
SV *
-hexdigest(Crypt::Checksum::CRC32 self)
+crc32_data(...)
+ ALIAS:
+ crc32_data_hex = 1
+ crc32_data_int = 2
CODE:
{
- unsigned long i;
- unsigned char hash[4];
- char hash_hex[4*2 + 1];
- crc32_finish(self, hash, 4); /* returns void */
- hash_hex[0] = '\0';
- for(i=0; i<4; i++) sprintf(&hash_hex[2*i], "%02x", hash[i]);
- RETVAL = newSVpvn(hash_hex, strlen(hash_hex));
+ crc32_state st;
+ int rv, j;
+ unsigned char hash[4], out[8], *in;
+ unsigned long outlen = 8;
+ unsigned int ui32;
+ STRLEN inlen;
+
+ crc32_init(&st);
+ for(j = 0; j < items; j++) {
+ in = (unsigned char *)SvPVbyte(ST(j), inlen);
+ if (inlen > 0) {
+ crc32_update(&st, in, (unsigned long)inlen); /* returns void */
+ }
+ }
+ crc32_finish(&st, hash, 4); /* returns void */
+ if (ix == 1) {
+ rv = _base16_encode(hash, 4, out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base16_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn((char *)out, outlen);
+ }
+ else if (ix == 2) {
+ LOAD32H(ui32, hash);
+ RETVAL = newSVuv(ui32);
+ }
+ else {
+ RETVAL = newSVpvn((char *) hash, 4);
+ }
}
OUTPUT:
RETVAL
-
diff --git a/inc/CryptX_Cipher.xs.inc b/inc/CryptX_Cipher.xs.inc
index b45c40a9..70d30d43 100644
--- a/inc/CryptX_Cipher.xs.inc
+++ b/inc/CryptX_Cipher.xs.inc
@@ -1,27 +1,36 @@
MODULE = CryptX PACKAGE = Crypt::Cipher
+PROTOTYPES: DISABLE
+
Crypt::Cipher
-_new(cipher_name, key, rounds=0)
- char * cipher_name
- SV * key
- int rounds
+new(char * class, ...)
CODE:
{
STRLEN key_len;
- unsigned char *key_data=NULL;
- int rv;
- int id;
+ unsigned char *key_data = NULL;
+ SV *key;
+ char *cipher_name;
+ int rv, id, rounds = 0, idx;
+
+ /* we need to handle:
+ Crypt::Cipher->new('AES');
+ Crypt::Cipher::AES->new();
+ */
+ idx = strcmp("Crypt::Cipher", class) == 0 ? 1 : 0;
+ if (idx + 1 > items) croak("FATAL: missing argument");
+ cipher_name = SvPVX(ST(idx));
+ key = ST(idx + 1);
+ if (idx + 3 <= items) rounds = (int)SvIV(ST(idx + 2));
if (!SvPOK (key)) croak("FATAL: key must be string scalar");
key_data = (unsigned char *)SvPVbyte(key, key_len);
- id = find_cipher(cipher_name);
+ id = _find_cipher(cipher_name);
if (id == -1) croak("FATAL: find_cipfer failed for '%s'", cipher_name);
Newz(0, RETVAL, 1, struct cipher_struct);
if (!RETVAL) croak("FATAL: Newz failed");
- RETVAL->id = id;
RETVAL->desc = &cipher_descriptor[id];
rv = RETVAL->desc->setup(key_data, (int)key_len, rounds, &RETVAL->skey);
if (rv != CRYPT_OK) {
@@ -33,47 +42,12 @@ _new(cipher_name, key, rounds=0)
RETVAL
void
-DESTROY(self)
- Crypt::Cipher self
+DESTROY(Crypt::Cipher self)
CODE:
Safefree(self);
-int
-_max_keysize(self, ...)
- Crypt::Cipher self
- CODE:
- RETVAL = self->desc->max_key_length;
- OUTPUT:
- RETVAL
-
-int
-_min_keysize(self, ...)
- Crypt::Cipher self
- CODE:
- RETVAL = self->desc->min_key_length;
- OUTPUT:
- RETVAL
-
-int
-_blocksize(self, ...)
- Crypt::Cipher self
- CODE:
- RETVAL = self->desc->block_length;
- OUTPUT:
- RETVAL
-
-int
-_default_rounds(self, ...)
- Crypt::Cipher self
- CODE:
- RETVAL = self->desc->default_rounds;
- OUTPUT:
- RETVAL
-
SV *
-encrypt(self, data)
- Crypt::Cipher self
- SV * data
+encrypt(Crypt::Cipher self, SV * data)
CODE:
{
int rv;
@@ -84,7 +58,7 @@ encrypt(self, data)
RETVAL = newSVpvn("", 0);
}
else if (len == (STRLEN)self->desc->block_length) {
- RETVAL = NEWSV(0, len);
+ RETVAL = NEWSV(0, len); /* avoid zero! */
SvPOK_only(RETVAL);
SvCUR_set(RETVAL, len);
rv = self->desc->ecb_encrypt((unsigned char *)plaintext, (unsigned char *)SvPVX(RETVAL), &self->skey);
@@ -101,9 +75,7 @@ encrypt(self, data)
RETVAL
SV *
-decrypt(self, data)
- Crypt::Cipher self
- SV * data
+decrypt(Crypt::Cipher self, SV * data)
CODE:
{
int rv;
@@ -114,7 +86,7 @@ decrypt(self, data)
RETVAL = newSVpvn("", 0);
}
else if (len == (STRLEN)self->desc->block_length) {
- RETVAL = NEWSV(0, len);
+ RETVAL = NEWSV(0, len); /* avoid zero! */
SvPOK_only(RETVAL);
SvCUR_set(RETVAL, len);
rv = self->desc->ecb_decrypt((unsigned char *)ciphertext, (unsigned char *)SvPVX(RETVAL), &self->skey);
@@ -131,69 +103,85 @@ decrypt(self, data)
RETVAL
int
-_block_length_by_name(cipher_name)
- char * cipher_name
+blocksize(SV * param, char * extra = NULL)
CODE:
{
- int rv, id;
-
- id = find_cipher(cipher_name);
- if (id == -1) croak("FATAL: find_cipfer failed for '%s'", cipher_name);
-
- rv = cipher_descriptor[id].block_length;
- if (!rv) XSRETURN_UNDEF;
- RETVAL = rv;
+ if (sv_isobject(param) && sv_derived_from(param, "Crypt::Cipher")) {
+ IV tmp = SvIV((SV*)SvRV(param));
+ Crypt__Cipher obj = INT2PTR(Crypt__Cipher, tmp);
+ RETVAL = obj->desc->block_length;
+ }
+ else {
+ char *name = SvPOK(param) && strcmp(SvPVX(param), "Crypt::Cipher") ? SvPVX(param) : extra;
+ int rv, id = _find_cipher(name);
+ if (id == -1) croak("FATAL: find_cipher failed for '%s'", name);
+ rv = cipher_descriptor[id].block_length;
+ if (!rv) croak("FATAL: invalid block_length for '%s'", name);
+ RETVAL = rv;
+ }
}
OUTPUT:
RETVAL
int
-_min_key_length_by_name(cipher_name)
- char * cipher_name
+max_keysize(SV * param, char * extra = NULL)
CODE:
{
- int rv, id;
-
- id = find_cipher(cipher_name);
- if (id == -1) croak("FATAL: find_cipfer failed for '%s'", cipher_name);
-
- rv = cipher_descriptor[id].min_key_length;
- if (!rv) XSRETURN_UNDEF;
- RETVAL = rv;
+ if (sv_isobject(param) && sv_derived_from(param, "Crypt::Cipher")) {
+ IV tmp = SvIV((SV*)SvRV(param));
+ Crypt__Cipher obj = INT2PTR(Crypt__Cipher, tmp);
+ RETVAL = obj->desc->max_key_length;
+ }
+ else {
+ char *name = SvPOK(param) && strcmp(SvPVX(param), "Crypt::Cipher") ? SvPVX(param) : extra;
+ int rv, id = _find_cipher(name);
+ if (id == -1) croak("FATAL: find_cipher failed for '%s'", name);
+ rv = cipher_descriptor[id].max_key_length;
+ if (!rv) croak("FATAL: invalid max_key_length for '%s'", name);
+ RETVAL = rv;
+ }
}
OUTPUT:
RETVAL
int
-_max_key_length_by_name(cipher_name)
- char * cipher_name
+min_keysize(SV * param, char * extra = NULL)
CODE:
{
- int rv, id;
-
- id = find_cipher(cipher_name);
- if (id == -1) croak("FATAL: find_cipfer failed for '%s'", cipher_name);
-
- rv = cipher_descriptor[id].max_key_length;
- if (!rv) XSRETURN_UNDEF;
- RETVAL = rv;
+ if (sv_isobject(param) && sv_derived_from(param, "Crypt::Cipher")) {
+ IV tmp = SvIV((SV*)SvRV(param));
+ Crypt__Cipher obj = INT2PTR(Crypt__Cipher, tmp);
+ RETVAL = obj->desc->min_key_length;
+ }
+ else {
+ char *name = SvPOK(param) && strcmp(SvPVX(param), "Crypt::Cipher") ? SvPVX(param) : extra;
+ int rv, id = _find_cipher(name);
+ if (id == -1) croak("FATAL: find_cipher failed for '%s'", name);
+ rv = cipher_descriptor[id].min_key_length;
+ if (!rv) croak("FATAL: invalid min_key_length for '%s'", name);
+ RETVAL = rv;
+ }
}
OUTPUT:
RETVAL
int
-_default_rounds_by_name(cipher_name)
- char * cipher_name
+default_rounds(SV * param, char * extra = NULL)
CODE:
{
- int rv, id;
-
- id = find_cipher(cipher_name);
- if (id == -1) croak("FATAL: find_cipfer failed for '%s'", cipher_name);
-
- rv = cipher_descriptor[id].default_rounds;
- if (!rv) XSRETURN_UNDEF;
- RETVAL = rv;
+ if (sv_isobject(param) && sv_derived_from(param, "Crypt::Cipher")) {
+ IV tmp = SvIV((SV*)SvRV(param));
+ Crypt__Cipher obj = INT2PTR(Crypt__Cipher, tmp);
+ RETVAL = obj->desc->default_rounds;
+ }
+ else {
+ char *name = SvPOK(param) && strcmp(SvPVX(param), "Crypt::Cipher") ? SvPVX(param) : extra;
+ int rv, id = _find_cipher(name);
+ if (id == -1) croak("FATAL: find_cipher failed for '%s'", name);
+ rv = cipher_descriptor[id].default_rounds;
+ if (!rv) XSRETURN_UNDEF;
+ RETVAL = rv;
+ }
}
OUTPUT:
RETVAL
diff --git a/inc/CryptX_Digest.xs.inc b/inc/CryptX_Digest.xs.inc
index 0a719a8f..8a97c1a9 100644
--- a/inc/CryptX_Digest.xs.inc
+++ b/inc/CryptX_Digest.xs.inc
@@ -1,20 +1,21 @@
MODULE = CryptX PACKAGE = Crypt::Digest
+PROTOTYPES: DISABLE
+
Crypt::Digest
-_new(digest_name)
- char * digest_name
+new(char * cname, char * pname = NULL)
CODE:
{
int rv;
int id;
+ char *digest_name = strcmp(cname, "Crypt::Digest") == 0 ? pname : cname;
- id = find_hash(digest_name);
+ id = _find_hash(digest_name);
if (id == -1) croak("FATAL: find_hash failed for '%s'", digest_name);
Newz(0, RETVAL, 1, struct digest_struct);
if (!RETVAL) croak("FATAL: Newz failed");
- RETVAL->id = id;
RETVAL->desc = &hash_descriptor[id];
rv = RETVAL->desc->init(&RETVAL->state);
if (rv != CRYPT_OK) {
@@ -26,14 +27,12 @@ _new(digest_name)
RETVAL
void
-DESTROY(self)
- Crypt::Digest self
+DESTROY(Crypt::Digest self)
CODE:
Safefree(self);
void
-reset(self)
- Crypt::Digest self
+reset(Crypt::Digest self)
PPCODE:
{
int rv;
@@ -43,8 +42,7 @@ reset(self)
}
Crypt::Digest
-clone(self)
- Crypt::Digest self
+clone(Crypt::Digest self)
CODE:
Newz(0, RETVAL, 1, struct digest_struct);
if (!RETVAL) croak("FATAL: Newz failed");
@@ -60,9 +58,9 @@ add(Crypt::Digest self, ...)
int rv, i;
unsigned char *in;
- for(i=1; i<items; i++) {
+ for(i = 1; i < items; i++) {
in = (unsigned char *)SvPVbyte(ST(i), inlen);
- if (inlen>0) {
+ if (inlen > 0) {
rv = self->desc->process(&self->state, in, (unsigned long)inlen);
if (rv != CRYPT_OK) croak("FATAL: digest process failed: %s", error_to_string(rv));
}
@@ -71,104 +69,118 @@ add(Crypt::Digest self, ...)
}
SV *
-digest(self)
- Crypt::Digest self
- CODE:
- {
- unsigned char hash[MAXBLOCKSIZE];
- int rv;
-
- rv = self->desc->done(&self->state, hash);
- if (rv != CRYPT_OK) croak("FATAL: digest done failed: %s", error_to_string(rv));
- RETVAL = newSVpvn((char *) hash, self->desc->hashsize);
- }
- OUTPUT:
- RETVAL
-
-SV *
-hexdigest(self)
- Crypt::Digest self
- CODE:
- {
- int rv;
- unsigned long i;
- unsigned char hash[MAXBLOCKSIZE];
- char hash_hex[MAXBLOCKSIZE*2 + 1];
-
- rv = self->desc->done(&self->state, hash);
- if (rv != CRYPT_OK) croak("FATAL: digest done failed: %s", error_to_string(rv));
-
- hash_hex[0] = '\0';
- for(i=0; i<self->desc->hashsize; i++)
- sprintf(&hash_hex[2*i], "%02x", hash[i]);
- RETVAL = newSVpvn(hash_hex, strlen(hash_hex));
- }
- OUTPUT:
- RETVAL
-
-SV *
-b64digest(self)
- Crypt::Digest self
+digest(Crypt::Digest self)
+ ALIAS:
+ hexdigest = 1
+ b64digest = 2
+ b64udigest = 3
CODE:
{
int rv;
unsigned long outlen;
unsigned char hash[MAXBLOCKSIZE];
- char hash_base64[MAXBLOCKSIZE*2 + 1];
+ char out[MAXBLOCKSIZE*2];
rv = self->desc->done(&self->state, hash);
if (rv != CRYPT_OK) croak("FATAL: digest done failed: %s", error_to_string(rv));
- outlen = sizeof(hash_base64);
- rv = base64_encode(hash, self->desc->hashsize, (unsigned char *)hash_base64, &outlen);
- if (rv != CRYPT_OK) croak("FATAL: base64_encode failed: %s", error_to_string(rv));
- RETVAL = newSVpvn(hash_base64, outlen);
+ outlen = sizeof(out);
+ if (ix == 3) {
+ rv = base64url_encode(hash, self->desc->hashsize, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base64url_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn(out, outlen);
+ }
+ else if (ix == 2) {
+ rv = base64_encode(hash, self->desc->hashsize, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base64_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn(out, outlen);
+ }
+ else if (ix == 1) {
+ rv = _base16_encode(hash, self->desc->hashsize, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base16_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn(out, outlen);
+ }
+ else {
+ RETVAL = newSVpvn((char *) hash, self->desc->hashsize);
+ }
}
OUTPUT:
RETVAL
SV *
-b64udigest(self)
- Crypt::Digest self
+digest_data(char * digest_name, ...)
+ ALIAS:
+ digest_data_hex = 1
+ digest_data_b64 = 2
+ digest_data_b64u = 3
CODE:
{
- int rv;
- unsigned long outlen;
- unsigned char hash[MAXBLOCKSIZE];
- char hash_base64[MAXBLOCKSIZE*2 + 1];
+ STRLEN inlen;
+ int rv, id, i;
+ unsigned char *in, hash[MAXBLOCKSIZE];
+ unsigned long len = sizeof(hash), outlen;
+ char out[MAXBLOCKSIZE*2];
+ hash_state md;
- rv = self->desc->done(&self->state, hash);
+ id = _find_hash(digest_name);
+ if (id == -1) croak("FATAL: find_digest failed for '%s'", digest_name);
+
+ /* digest_data("SHA1", $data1, $data2, $data3); */
+ len = hash_descriptor[id].hashsize;
+ rv = hash_descriptor[id].init(&md);
+ if (rv != CRYPT_OK) croak("FATAL: digest init failed: %s", error_to_string(rv));
+ for (i = 1; i < items; i++) {
+ in = (unsigned char *)SvPVbyte(ST(i), inlen);
+ if (inlen > 0) {
+ rv = hash_descriptor[id].process(&md, in, (unsigned long)inlen);
+ if (rv != CRYPT_OK) croak("FATAL: digest process failed: %s", error_to_string(rv));
+ }
+ }
+ rv = hash_descriptor[id].done(&md, hash);
if (rv != CRYPT_OK) croak("FATAL: digest done failed: %s", error_to_string(rv));
- outlen = sizeof(hash_base64);
- rv = base64url_encode(hash, self->desc->hashsize, (unsigned char *)hash_base64, &outlen);
- if (rv != CRYPT_OK) croak("FATAL: base64url_encode failed: %s", error_to_string(rv));
- RETVAL = newSVpvn(hash_base64, outlen);
+ outlen = sizeof(out);
+ if (ix == 3) {
+ rv = base64url_encode(hash, len, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base64url_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn((char *) out, outlen);
+ }
+ else if (ix == 2) {
+ rv = base64_encode(hash, len, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base64_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn((char *) out, outlen);
+ }
+ else if (ix == 1) {
+ rv = _base16_encode(hash, len, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base16_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn((char *) out, outlen);
+ }
+ else {
+ RETVAL = newSVpvn((char *) hash, len);
+ }
}
OUTPUT:
RETVAL
int
-_hashsize(self)
- Crypt::Digest self
- CODE:
- RETVAL = self->desc->hashsize;
- OUTPUT:
- RETVAL
-
-int
-_hashsize_by_name(digest_name)
- char * digest_name
+hashsize(SV * param, char * extra = NULL)
CODE:
{
- int rv, id;
-
- id = find_hash(digest_name);
- if (id == -1) croak("FATAL: find_digest failed for '%s'", digest_name);
-
- rv = hash_descriptor[id].hashsize;
- if (!rv) croak("FATAL: invalid hashsize for '%s'", digest_name);;
- RETVAL = rv;
+ if (sv_isobject(param) && sv_derived_from(param, "Crypt::Digest")) {
+ IV tmp = SvIV((SV*)SvRV(param));
+ Crypt__Digest obj = INT2PTR(Crypt__Digest, tmp);
+ RETVAL = obj->desc->hashsize;
+ }
+ else {
+ char *digest_name;
+ int rv, id;
+ digest_name = SvPOK(param) && strcmp(SvPVX(param), "Crypt::Digest") ? SvPVX(param) : extra;
+ id = _find_hash(digest_name);
+ if (id == -1) croak("FATAL: find_hash failed for '%s'", digest_name);
+ rv = hash_descriptor[id].hashsize;
+ if (!rv) croak("FATAL: invalid hashsize for '%s'", digest_name);;
+ RETVAL = rv;
+ }
}
OUTPUT:
RETVAL
diff --git a/inc/CryptX_Digest_SHAKE.xs.inc b/inc/CryptX_Digest_SHAKE.xs.inc
index 1ab196bc..07626668 100644
--- a/inc/CryptX_Digest_SHAKE.xs.inc
+++ b/inc/CryptX_Digest_SHAKE.xs.inc
@@ -1,7 +1,9 @@
MODULE = CryptX PACKAGE = Crypt::Digest::SHAKE
+PROTOTYPES: DISABLE
+
Crypt::Digest::SHAKE
-_new(int num)
+new(Class, int num)
CODE:
{
int rv;
@@ -68,14 +70,19 @@ done(Crypt::Digest::SHAKE self, STRLEN out_len)
int rv;
unsigned char *out_data;
- RETVAL = NEWSV(0, out_len);
- SvPOK_only(RETVAL);
- SvCUR_set(RETVAL, out_len);
- out_data = (unsigned char *)SvPVX(RETVAL);
- rv = sha3_shake_done(&self->state, out_data, (unsigned long)out_len);
- if (rv != CRYPT_OK) {
- SvREFCNT_dec(RETVAL);
- croak("FATAL: sha3_shake_done failed: %s", error_to_string(rv));
+ if (out_len == 0) {
+ RETVAL = newSVpvn("", 0);
+ }
+ else {
+ RETVAL = NEWSV(0, out_len); /* avoid zero! */
+ SvPOK_only(RETVAL);
+ SvCUR_set(RETVAL, out_len);
+ out_data = (unsigned char *)SvPVX(RETVAL);
+ rv = sha3_shake_done(&self->state, out_data, (unsigned long)out_len);
+ if (rv != CRYPT_OK) {
+ SvREFCNT_dec(RETVAL);
+ croak("FATAL: sha3_shake_done failed: %s", error_to_string(rv));
+ }
}
}
OUTPUT:
diff --git a/inc/CryptX_KeyDerivation.xs.inc b/inc/CryptX_KeyDerivation.xs.inc
index 9e88d160..9ae79206 100644
--- a/inc/CryptX_KeyDerivation.xs.inc
+++ b/inc/CryptX_KeyDerivation.xs.inc
@@ -1,15 +1,11 @@
MODULE = CryptX PACKAGE = Crypt::KeyDerivation
+PROTOTYPES: DISABLE
+
SV *
-_pkcs_5_alg1(SV * password, SV * salt, int iteration_count, char * hash_name, unsigned long output_len)
+pbkdf1(SV * password, SV * salt, int iteration_count = 5000, const char * hash_name = "SHA256", unsigned long output_len = 32)
CODE:
{
- /*
- int pkcs_5_alg1(const unsigned char *password, unsigned long password_len,
- const unsigned char *salt,
- int iteration_count, int hash_idx,
- unsigned char *out, unsigned long *outlen)
- */
int rv, id;
unsigned char *output;
unsigned char *password_ptr=NULL;
@@ -17,38 +13,37 @@ _pkcs_5_alg1(SV * password, SV * salt, int iteration_count, char * hash_name, un
unsigned char *salt_ptr=NULL;
STRLEN salt_len=0;
- id = find_hash(hash_name);
- if (id == -1) croak("FATAL: find_hash failed for '%s'", hash_name);
-
- password_ptr = (unsigned char *)SvPVbyte(password, password_len);
- salt_ptr = (unsigned char *)SvPVbyte(salt, salt_len);
- if (salt_len < 8) croak("FATAL: salt_len has to be 8");
-
- RETVAL = NEWSV(0, output_len);
- SvPOK_only(RETVAL);
- SvCUR_set(RETVAL, output_len);
- output = (unsigned char *)SvPVX(RETVAL);
-
- rv = pkcs_5_alg1(password_ptr, (unsigned long)password_len, salt_ptr, iteration_count, id, output, &output_len);
- if (rv != CRYPT_OK) {
- SvREFCNT_dec(RETVAL);
- croak("FATAL: pkcs_5_alg1 process failed: %s", error_to_string(rv));
+ if (output_len == 0) {
+ RETVAL = newSVpvn("", 0);
+ }
+ else {
+ id = _find_hash(hash_name);
+ if (id == -1) croak("FATAL: find_hash failed for '%s'", hash_name);
+
+ password_ptr = (unsigned char *)SvPVbyte(password, password_len);
+ salt_ptr = (unsigned char *)SvPVbyte(salt, salt_len);
+ if (salt_len < 8) croak("FATAL: salt_len has to be 8");
+
+ RETVAL = NEWSV(0, output_len); /* avoid zero! */
+ SvPOK_only(RETVAL);
+ SvCUR_set(RETVAL, output_len);
+ output = (unsigned char *)SvPVX(RETVAL);
+
+ rv = pkcs_5_alg1(password_ptr, (unsigned long)password_len, salt_ptr, iteration_count, id, output, &output_len);
+ if (rv != CRYPT_OK) {
+ SvREFCNT_dec(RETVAL);
+ croak("FATAL: pkcs_5_alg1 process failed: %s", error_to_string(rv));
+ }
+ SvCUR_set(RETVAL, output_len);
}
- SvCUR_set(RETVAL, output_len);
}
OUTPUT:
RETVAL
SV *
-_pkcs_5_alg2(SV * password, SV * salt, int iteration_count, char * hash_name, unsigned long output_len)
+pbkdf2(SV * password, SV * salt, int iteration_count = 5000, const char * hash_name = "SHA256", unsigned long output_len = 32)
CODE:
{
- /*
- int pkcs_5_alg2(const unsigned char *password, unsigned long password_len,
- const unsigned char *salt, unsigned long salt_len,
- int iteration_count, int hash_idx,
- unsigned char *out, unsigned long *outlen)
- */
int rv, id;
unsigned char *output;
unsigned char *password_ptr=NULL;
@@ -56,49 +51,47 @@ _pkcs_5_alg2(SV * password, SV * salt, int iteration_count, char * hash_name, un
unsigned char *salt_ptr=NULL;
STRLEN salt_len=0;
- id = find_hash(hash_name);
- if (id == -1) croak("FATAL: find_hash failed for '%s'", hash_name);
-
- password_ptr = (unsigned char *)SvPVbyte(password, password_len);
- salt_ptr = (unsigned char *)SvPVbyte(salt, salt_len);
-
- RETVAL = NEWSV(0, output_len);
- SvPOK_only(RETVAL);
- SvCUR_set(RETVAL, output_len);
- output = (unsigned char *)SvPVX(RETVAL);
-
- rv = pkcs_5_alg2(password_ptr, (unsigned long)password_len, salt_ptr, (unsigned long)salt_len, iteration_count, id, output, &output_len);
- if (rv != CRYPT_OK) {
- SvREFCNT_dec(RETVAL);
- croak("FATAL: pkcs_5_alg2 process failed: %s", error_to_string(rv));
+ if (output_len == 0) {
+ RETVAL = newSVpvn("", 0);
+ }
+ else {
+ id = _find_hash(hash_name);
+ if (id == -1) croak("FATAL: find_hash failed for '%s'", hash_name);
+
+ password_ptr = (unsigned char *)SvPVbyte(password, password_len);
+ salt_ptr = (unsigned char *)SvPVbyte(salt, salt_len);
+
+ RETVAL = NEWSV(0, output_len); /* avoid zero! */
+ SvPOK_only(RETVAL);
+ SvCUR_set(RETVAL, output_len);
+ output = (unsigned char *)SvPVX(RETVAL);
+
+ rv = pkcs_5_alg2(password_ptr, (unsigned long)password_len, salt_ptr, (unsigned long)salt_len, iteration_count, id, output, &output_len);
+ if (rv != CRYPT_OK) {
+ SvREFCNT_dec(RETVAL);
+ croak("FATAL: pkcs_5_alg2 process failed: %s", error_to_string(rv));
+ }
+ SvCUR_set(RETVAL, output_len);
}
- SvCUR_set(RETVAL, output_len);
}
OUTPUT:
RETVAL
SV *
-_hkdf_extract(char * hash_name, SV * salt, SV * in)
+hkdf_extract(SV * in, SV * salt = &PL_sv_undef, const char * hash_name = "SHA256")
CODE:
{
- /*
- int hkdf_extract(int hash_idx, const unsigned char *salt, unsigned long saltlen,
- const unsigned char *in, unsigned long inlen,
- unsigned char *out, unsigned long *outlen)
- */
int rv, id;
unsigned char output[MAXBLOCKSIZE];
unsigned long output_len;
- unsigned char *in_ptr=NULL;
- STRLEN in_len=0;
- unsigned char *salt_ptr=NULL;
- STRLEN salt_len=0;
+ unsigned char *in_ptr = NULL, *salt_ptr = NULL;
+ STRLEN in_len = 0, salt_len = 0;
- id = find_hash(hash_name);
+ id = _find_hash(hash_name);
if (id == -1) croak("FATAL: find_hash failed for '%s'", hash_name);
- in_ptr = (unsigned char *)SvPVbyte(in, in_len);
- salt_ptr = (unsigned char *)SvPVbyte(salt, salt_len);
+ if (SvPOK(in)) in_ptr = (unsigned char *)SvPVbyte(in, in_len);
+ if (SvPOK(salt)) salt_ptr = (unsigned char *)SvPVbyte(salt, salt_len);
output_len = sizeof(output);
rv = hkdf_extract(id, salt_ptr, (unsigned long)salt_len, in_ptr, (unsigned long)in_len, output, &output_len);
@@ -110,79 +103,72 @@ _hkdf_extract(char * hash_name, SV * salt, SV * in)
RETVAL
SV *
-_hkdf_expand(char * hash_name, SV * info, SV * in, unsigned long output_len)
+hkdf_expand(SV * in, const char * hash_name = "SHA256", unsigned long output_len = 32, SV * info = &PL_sv_undef)
CODE:
{
- /*
- int hkdf_expand(int hash_idx, const unsigned char *info, unsigned long infolen,
- const unsigned char *in, unsigned long inlen,
- unsigned char *out, unsigned long outlen)
- */
int rv, id;
unsigned char *output;
- unsigned char *in_ptr=NULL;
- STRLEN in_len=0;
- unsigned char *info_ptr=NULL;
- STRLEN info_len=0;
+ unsigned char *in_ptr = NULL, *info_ptr = NULL;
+ STRLEN in_len = 0, info_len = 0;
- id = find_hash(hash_name);
- if (id == -1) croak("FATAL: find_hash failed for '%s'", hash_name);
-
- in_ptr = (unsigned char *)SvPVbyte(in, in_len);
- info_ptr = (unsigned char *)SvPVbyte(info, info_len);
-
- RETVAL = NEWSV(0, output_len);
- SvPOK_only(RETVAL);
- SvCUR_set(RETVAL, output_len);
- output = (unsigned char *)SvPVX(RETVAL);
-
- rv = hkdf_expand(id, info_ptr, (unsigned long)info_len, in_ptr, (unsigned long)in_len, output, output_len);
- if (rv != CRYPT_OK) {
- SvREFCNT_dec(RETVAL);
- croak("FATAL: hkdf_expand process failed: %s", error_to_string(rv));
+ if (output_len == 0) {
+ RETVAL = newSVpvn("", 0);
+ }
+ else {
+ id = _find_hash(hash_name);
+ if (id == -1) croak("FATAL: find_hash failed for '%s'", hash_name);
+
+ if (SvPOK(in)) in_ptr = (unsigned char *)SvPVbyte(in, in_len);
+ if (SvPOK(info)) info_ptr = (unsigned char *)SvPVbyte(info, info_len);
+
+ RETVAL = NEWSV(0, output_len); /* avoid zero! */
+ SvPOK_only(RETVAL);
+ SvCUR_set(RETVAL, output_len);
+ output = (unsigned char *)SvPVX(RETVAL);
+
+ rv = hkdf_expand(id, info_ptr, (unsigned long)info_len, in_ptr, (unsigned long)in_len, output, output_len);
+ if (rv != CRYPT_OK) {
+ SvREFCNT_dec(RETVAL);
+ croak("FATAL: hkdf_expand process failed: %s", error_to_string(rv));
+ }
+ SvCUR_set(RETVAL, output_len);
}
- SvCUR_set(RETVAL, output_len);
}
OUTPUT:
RETVAL
SV *
-_hkdf(char * hash_name, SV * salt, SV * info, SV * in, unsigned long output_len)
+hkdf(SV * in, SV * salt, const char * hash_name = "SHA256", unsigned long output_len = 32, SV * info = &PL_sv_undef)
CODE:
{
- /*
- int hkdf(int hash_idx, const unsigned char *salt, unsigned long saltlen,
- const unsigned char *info, unsigned long infolen,
- const unsigned char *in, unsigned long inlen,
- unsigned char *out, unsigned long outlen)
- */
int rv, id;
unsigned char *output;
- unsigned char *in_ptr=NULL;
- STRLEN in_len=0;
- unsigned char *info_ptr=NULL;
- STRLEN info_len=0;
- unsigned char *salt_ptr=NULL;
- STRLEN salt_len=0;
-
- id = find_hash(hash_name);
- if (id == -1) croak("FATAL: find_hash failed for '%s'", hash_name);
+ unsigned char *in_ptr = NULL, *info_ptr = NULL, *salt_ptr = NULL;
+ STRLEN in_len = 0, info_len = 0, salt_len = 0;
- in_ptr = (unsigned char *)SvPVbyte(in, in_len);
- info_ptr = (unsigned char *)SvPVbyte(info, info_len);
- salt_ptr = (unsigned char *)SvPVbyte(salt, salt_len);
-
- RETVAL = NEWSV(0, output_len);
- SvPOK_only(RETVAL);
- SvCUR_set(RETVAL, output_len);
- output = (unsigned char *)SvPVX(RETVAL);
-
- rv = hkdf(id, salt_ptr, (unsigned long)salt_len, info_ptr, (unsigned long)info_len, in_ptr, (unsigned long)in_len, output, output_len);
- if (rv != CRYPT_OK) {
- SvREFCNT_dec(RETVAL);
- croak("FATAL: hkdf_expand process failed: %s", error_to_string(rv));
+ if (output_len == 0) {
+ RETVAL = newSVpvn("", 0);
+ }
+ else {
+ id = _find_hash(hash_name);
+ if (id == -1) croak("FATAL: find_hash failed for '%s'", hash_name);
+
+ if (SvPOK(in)) in_ptr = (unsigned char *)SvPVbyte(in, in_len);
+ if (SvPOK(info)) info_ptr = (unsigned char *)SvPVbyte(info, info_len);
+ if (SvPOK(salt)) salt_ptr = (unsigned char *)SvPVbyte(salt, salt_len);
+
+ RETVAL = NEWSV(0, output_len); /* avoid zero! */
+ SvPOK_only(RETVAL);
+ SvCUR_set(RETVAL, output_len);
+ output = (unsigned char *)SvPVX(RETVAL);
+
+ rv = hkdf(id, salt_ptr, (unsigned long)salt_len, info_ptr, (unsigned long)info_len, in_ptr, (unsigned long)in_len, output, output_len);
+ if (rv != CRYPT_OK) {
+ SvREFCNT_dec(RETVAL);
+ croak("FATAL: hkdf_expand process failed: %s", error_to_string(rv));
+ }
+ SvCUR_set(RETVAL, output_len);
}
- SvCUR_set(RETVAL, output_len);
}
OUTPUT:
RETVAL
diff --git a/inc/CryptX_Mac_BLAKE2b.xs.inc b/inc/CryptX_Mac_BLAKE2b.xs.inc
index ae73990d..6d27e3e2 100644
--- a/inc/CryptX_Mac_BLAKE2b.xs.inc
+++ b/inc/CryptX_Mac_BLAKE2b.xs.inc
@@ -1,9 +1,11 @@
MODULE = CryptX PACKAGE = Crypt::Mac::BLAKE2b
+PROTOTYPES: DISABLE
+
### BEWARE - GENERATED FILE, DO NOT EDIT MANUALLY!
Crypt::Mac::BLAKE2b
-_new(int size, SV * key)
+new(Class, unsigned long size, SV * key)
CODE:
{
STRLEN k_len=0;
@@ -13,10 +15,10 @@ _new(int size, SV * key)
if (!SvPOK(key)) croak("FATAL: key must be string/buffer scalar");
k = (unsigned char *) SvPVbyte(key, k_len);
- Newz(0, RETVAL, 1, struct blake2b_struct);
+ Newz(0, RETVAL, 1, blake2bmac_state);
if (!RETVAL) croak("FATAL: Newz failed");
- rv = blake2bmac_init(&RETVAL->state, size, k, (unsigned long)k_len);
+ rv = blake2bmac_init(RETVAL, size, k, (unsigned long)k_len);
if (rv != CRYPT_OK) {
Safefree(RETVAL);
croak("FATAL: blake2b_init failed: %s", error_to_string(rv));
@@ -33,101 +35,118 @@ DESTROY(Crypt::Mac::BLAKE2b self)
Crypt::Mac::BLAKE2b
clone(Crypt::Mac::BLAKE2b self)
CODE:
- Newz(0, RETVAL, 1, struct blake2b_struct);
+ Newz(0, RETVAL, 1, blake2bmac_state);
if (!RETVAL) croak("FATAL: Newz failed");
- Copy(&self->state, &RETVAL->state, 1, struct blake2b_struct);
+ Copy(self, RETVAL, 1, blake2bmac_state);
OUTPUT:
RETVAL
void
-_add_single(Crypt::Mac::BLAKE2b self, SV * data)
- CODE:
+add(Crypt::Mac::BLAKE2b self, ...)
+ PPCODE:
{
- int rv;
+ int rv, i;
STRLEN in_data_len;
unsigned char *in_data;
- in_data = (unsigned char *)SvPVbyte(data, in_data_len);
- if (in_data_len>0) {
- rv = blake2bmac_process(&self->state, in_data, (unsigned long)in_data_len);
- if (rv != CRYPT_OK) croak("FATAL: blake2b_process failed: %s", error_to_string(rv));
+ for(i = 1; i < items; i++) {
+ in_data = (unsigned char *)SvPVbyte(ST(i), in_data_len);
+ if (in_data_len > 0) {
+ rv = blake2bmac_process(self, in_data, (unsigned long)in_data_len);
+ if (rv != CRYPT_OK) croak("FATAL: blake2b_process failed: %s", error_to_string(rv));
+ }
}
+ XPUSHs(ST(0)); /* return self */
}
SV *
mac(Crypt::Mac::BLAKE2b self)
- CODE:
- {
- char mac[MAXBLOCKSIZE];
- unsigned long mac_len;
- int rv;
-
- mac_len = sizeof(mac);
- rv = blake2bmac_done(&self->state, (unsigned char*)mac, &mac_len);
- if (rv != CRYPT_OK) croak("FATAL: blake2bmac_done failed: %s", error_to_string(rv));
- RETVAL = newSVpvn(mac, mac_len);
- }
- OUTPUT:
- RETVAL
-
-SV *
-b64mac(Crypt::Mac::BLAKE2b self)
+ ALIAS:
+ hexmac = 1
+ b64mac = 2
+ b64umac = 3
CODE:
{
unsigned char mac[MAXBLOCKSIZE];
- unsigned long mac_len;
+ unsigned long maclen, outlen;
int rv;
- unsigned long outlen;
- char mac_base64[MAXBLOCKSIZE*2 + 1];
+ char out[MAXBLOCKSIZE*2];
- mac_len = sizeof(mac);
- rv = blake2bmac_done(&self->state, mac, &mac_len);
+ maclen = sizeof(mac);
+ rv = blake2bmac_done(self, mac, &maclen);
if (rv != CRYPT_OK) croak("FATAL: blake2bmac_done failed: %s", error_to_string(rv));
- outlen = sizeof(mac_base64);
- rv = base64_encode(mac, mac_len, (unsigned char*)mac_base64, &outlen);
- if (rv != CRYPT_OK) croak("FATAL: base64_encode failed: %s", error_to_string(rv));
- RETVAL = newSVpvn(mac_base64, outlen);
+ outlen = sizeof(out);
+ if (ix == 3) {
+ rv = base64url_encode(mac, maclen, (unsigned char*)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base64url_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn(out, outlen);
+ }
+ if (ix == 2) {
+ rv = base64_encode(mac, maclen, (unsigned char*)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base64_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn(out, outlen);
+ }
+ if (ix == 1) {
+ rv = _base16_encode(mac, maclen, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base16_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn(out, outlen);
+ }
+ else {
+ RETVAL = newSVpvn((char * )mac, maclen);
+ }
}
OUTPUT:
RETVAL
SV *
-b64umac(Crypt::Mac::BLAKE2b self)
+blake2b(unsigned long size, SV * key, ...)
+ ALIAS:
+ blake2b_hex = 1
+ blake2b_b64 = 2
+ blake2b_b64u = 3
CODE:
{
+ STRLEN inlen, klen;
+ unsigned char *in;
+ unsigned char *k = (unsigned char *)SvPVbyte(key, klen);
+ int rv, i;
unsigned char mac[MAXBLOCKSIZE];
- unsigned long mac_len;
- int rv;
- unsigned long outlen;
- char mac_base64[MAXBLOCKSIZE*2 + 1];
-
- mac_len = sizeof(mac);
- rv = blake2bmac_done(&self->state, mac, &mac_len);
+ unsigned long len = sizeof(mac), outlen;
+ char out[MAXBLOCKSIZE*2];
+ blake2bmac_state st;
+
+ if (size < len) len = size;
+ rv = blake2bmac_init(&st, len, k, (unsigned long)klen);
+ if (rv != CRYPT_OK) croak("FATAL: blake2bmac_init failed: %s", error_to_string(rv));
+ for (i = 2; i < items; i++) {
+ in = (unsigned char *)SvPVbyte(ST(i), inlen);
+ if (inlen > 0) {
+ rv = blake2bmac_process(&st, in, (unsigned long)inlen);
+ if (rv != CRYPT_OK) croak("FATAL: blake2bmac_process failed: %s", error_to_string(rv));
+ }
+ }
+ rv = blake2bmac_done(&st, mac, &len);
if (rv != CRYPT_OK) croak("FATAL: blake2bmac_done failed: %s", error_to_string(rv));
- outlen = sizeof(mac_base64);
- rv = base64url_encode(mac, mac_len, (unsigned char*)mac_base64, &outlen);
- if (rv != CRYPT_OK) croak("FATAL: base64url_encode failed: %s", error_to_string(rv));
- RETVAL = newSVpvn(mac_base64, outlen);
- }
- OUTPUT:
- RETVAL
-SV *
-hexmac(Crypt::Mac::BLAKE2b self)
- CODE:
- {
- unsigned char mac[MAXBLOCKSIZE];
- unsigned long mac_len, i;
- int rv;
- char mac_hex[MAXBLOCKSIZE*2 + 1];
-
- mac_len = sizeof(mac);
- rv = blake2bmac_done(&self->state, mac, &mac_len);
- if (rv != CRYPT_OK) croak("FATAL: blake2bmac_done failed: %s", error_to_string(rv));
- mac_hex[0] = '\0';
- for(i=0; i<mac_len; i++)
- sprintf(&mac_hex[2*i], "%02x", mac[i]);
- RETVAL = newSVpvn(mac_hex, strlen(mac_hex));
+ outlen = sizeof(out);
+ if (ix == 3) {
+ rv = base64url_encode(mac, len, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base64url_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn((char *) out, outlen);
+ }
+ else if (ix == 2) {
+ rv = base64_encode(mac, len, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base64_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn((char *) out, outlen);
+ }
+ else if (ix == 1) {
+ rv = _base16_encode(mac, len, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base16_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn((char *) out, outlen);
+ }
+ else {
+ RETVAL = newSVpvn((char *) mac, len);
+ }
}
OUTPUT:
RETVAL
diff --git a/inc/CryptX_Mac_BLAKE2s.xs.inc b/inc/CryptX_Mac_BLAKE2s.xs.inc
index 38e43cde..3ac34672 100644
--- a/inc/CryptX_Mac_BLAKE2s.xs.inc
+++ b/inc/CryptX_Mac_BLAKE2s.xs.inc
@@ -1,9 +1,11 @@
MODULE = CryptX PACKAGE = Crypt::Mac::BLAKE2s
+PROTOTYPES: DISABLE
+
### BEWARE - GENERATED FILE, DO NOT EDIT MANUALLY!
Crypt::Mac::BLAKE2s
-_new(int size, SV * key)
+new(Class, unsigned long size, SV * key)
CODE:
{
STRLEN k_len=0;
@@ -13,10 +15,10 @@ _new(int size, SV * key)
if (!SvPOK(key)) croak("FATAL: key must be string/buffer scalar");
k = (unsigned char *) SvPVbyte(key, k_len);
- Newz(0, RETVAL, 1, struct blake2s_struct);
+ Newz(0, RETVAL, 1, blake2smac_state);
if (!RETVAL) croak("FATAL: Newz failed");
- rv = blake2smac_init(&RETVAL->state, size, k, (unsigned long)k_len);
+ rv = blake2smac_init(RETVAL, size, k, (unsigned long)k_len);
if (rv != CRYPT_OK) {
Safefree(RETVAL);
croak("FATAL: blake2s_init failed: %s", error_to_string(rv));
@@ -33,101 +35,118 @@ DESTROY(Crypt::Mac::BLAKE2s self)
Crypt::Mac::BLAKE2s
clone(Crypt::Mac::BLAKE2s self)
CODE:
- Newz(0, RETVAL, 1, struct blake2s_struct);
+ Newz(0, RETVAL, 1, blake2smac_state);
if (!RETVAL) croak("FATAL: Newz failed");
- Copy(&self->state, &RETVAL->state, 1, struct blake2s_struct);
+ Copy(self, RETVAL, 1, blake2smac_state);
OUTPUT:
RETVAL
void
-_add_single(Crypt::Mac::BLAKE2s self, SV * data)
- CODE:
+add(Crypt::Mac::BLAKE2s self, ...)
+ PPCODE:
{
- int rv;
+ int rv, i;
STRLEN in_data_len;
unsigned char *in_data;
- in_data = (unsigned char *)SvPVbyte(data, in_data_len);
- if (in_data_len>0) {
- rv = blake2smac_process(&self->state, in_data, (unsigned long)in_data_len);
- if (rv != CRYPT_OK) croak("FATAL: blake2s_process failed: %s", error_to_string(rv));
+ for(i = 1; i < items; i++) {
+ in_data = (unsigned char *)SvPVbyte(ST(i), in_data_len);
+ if (in_data_len > 0) {
+ rv = blake2smac_process(self, in_data, (unsigned long)in_data_len);
+ if (rv != CRYPT_OK) croak("FATAL: blake2s_process failed: %s", error_to_string(rv));
+ }
}
+ XPUSHs(ST(0)); /* return self */
}
SV *
mac(Crypt::Mac::BLAKE2s self)
- CODE:
- {
- char mac[MAXBLOCKSIZE];
- unsigned long mac_len;
- int rv;
-
- mac_len = sizeof(mac);
- rv = blake2smac_done(&self->state, (unsigned char*)mac, &mac_len);
- if (rv != CRYPT_OK) croak("FATAL: blake2smac_done failed: %s", error_to_string(rv));
- RETVAL = newSVpvn(mac, mac_len);
- }
- OUTPUT:
- RETVAL
-
-SV *
-b64mac(Crypt::Mac::BLAKE2s self)
+ ALIAS:
+ hexmac = 1
+ b64mac = 2
+ b64umac = 3
CODE:
{
unsigned char mac[MAXBLOCKSIZE];
- unsigned long mac_len;
+ unsigned long maclen, outlen;
int rv;
- unsigned long outlen;
- char mac_base64[MAXBLOCKSIZE*2 + 1];
+ char out[MAXBLOCKSIZE*2];
- mac_len = sizeof(mac);
- rv = blake2smac_done(&self->state, mac, &mac_len);
+ maclen = sizeof(mac);
+ rv = blake2smac_done(self, mac, &maclen);
if (rv != CRYPT_OK) croak("FATAL: blake2smac_done failed: %s", error_to_string(rv));
- outlen = sizeof(mac_base64);
- rv = base64_encode(mac, mac_len, (unsigned char*)mac_base64, &outlen);
- if (rv != CRYPT_OK) croak("FATAL: base64_encode failed: %s", error_to_string(rv));
- RETVAL = newSVpvn(mac_base64, outlen);
+ outlen = sizeof(out);
+ if (ix == 3) {
+ rv = base64url_encode(mac, maclen, (unsigned char*)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base64url_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn(out, outlen);
+ }
+ if (ix == 2) {
+ rv = base64_encode(mac, maclen, (unsigned char*)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base64_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn(out, outlen);
+ }
+ if (ix == 1) {
+ rv = _base16_encode(mac, maclen, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base16_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn(out, outlen);
+ }
+ else {
+ RETVAL = newSVpvn((char * )mac, maclen);
+ }
}
OUTPUT:
RETVAL
SV *
-b64umac(Crypt::Mac::BLAKE2s self)
+blake2s(unsigned long size, SV * key, ...)
+ ALIAS:
+ blake2s_hex = 1
+ blake2s_b64 = 2
+ blake2s_b64u = 3
CODE:
{
+ STRLEN inlen, klen;
+ unsigned char *in;
+ unsigned char *k = (unsigned char *)SvPVbyte(key, klen);
+ int rv, i;
unsigned char mac[MAXBLOCKSIZE];
- unsigned long mac_len;
- int rv;
- unsigned long outlen;
- char mac_base64[MAXBLOCKSIZE*2 + 1];
-
- mac_len = sizeof(mac);
- rv = blake2smac_done(&self->state, mac, &mac_len);
+ unsigned long len = sizeof(mac), outlen;
+ char out[MAXBLOCKSIZE*2];
+ blake2smac_state st;
+
+ if (size < len) len = size;
+ rv = blake2smac_init(&st, len, k, (unsigned long)klen);
+ if (rv != CRYPT_OK) croak("FATAL: blake2smac_init failed: %s", error_to_string(rv));
+ for (i = 2; i < items; i++) {
+ in = (unsigned char *)SvPVbyte(ST(i), inlen);
+ if (inlen > 0) {
+ rv = blake2smac_process(&st, in, (unsigned long)inlen);
+ if (rv != CRYPT_OK) croak("FATAL: blake2smac_process failed: %s", error_to_string(rv));
+ }
+ }
+ rv = blake2smac_done(&st, mac, &len);
if (rv != CRYPT_OK) croak("FATAL: blake2smac_done failed: %s", error_to_string(rv));
- outlen = sizeof(mac_base64);
- rv = base64url_encode(mac, mac_len, (unsigned char*)mac_base64, &outlen);
- if (rv != CRYPT_OK) croak("FATAL: base64url_encode failed: %s", error_to_string(rv));
- RETVAL = newSVpvn(mac_base64, outlen);
- }
- OUTPUT:
- RETVAL
-SV *
-hexmac(Crypt::Mac::BLAKE2s self)
- CODE:
- {
- unsigned char mac[MAXBLOCKSIZE];
- unsigned long mac_len, i;
- int rv;
- char mac_hex[MAXBLOCKSIZE*2 + 1];
-
- mac_len = sizeof(mac);
- rv = blake2smac_done(&self->state, mac, &mac_len);
- if (rv != CRYPT_OK) croak("FATAL: blake2smac_done failed: %s", error_to_string(rv));
- mac_hex[0] = '\0';
- for(i=0; i<mac_len; i++)
- sprintf(&mac_hex[2*i], "%02x", mac[i]);
- RETVAL = newSVpvn(mac_hex, strlen(mac_hex));
+ outlen = sizeof(out);
+ if (ix == 3) {
+ rv = base64url_encode(mac, len, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base64url_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn((char *) out, outlen);
+ }
+ else if (ix == 2) {
+ rv = base64_encode(mac, len, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base64_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn((char *) out, outlen);
+ }
+ else if (ix == 1) {
+ rv = _base16_encode(mac, len, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base16_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn((char *) out, outlen);
+ }
+ else {
+ RETVAL = newSVpvn((char *) mac, len);
+ }
}
OUTPUT:
RETVAL
diff --git a/inc/CryptX_Mac_F9.xs.inc b/inc/CryptX_Mac_F9.xs.inc
index 359cdb73..e1782c6c 100644
--- a/inc/CryptX_Mac_F9.xs.inc
+++ b/inc/CryptX_Mac_F9.xs.inc
@@ -1,9 +1,11 @@
MODULE = CryptX PACKAGE = Crypt::Mac::F9
+PROTOTYPES: DISABLE
+
### BEWARE - GENERATED FILE, DO NOT EDIT MANUALLY!
Crypt::Mac::F9
-_new(char * cipher_name, SV * key)
+new(Class, char * cipher_name, SV * key)
CODE:
{
STRLEN k_len=0;
@@ -11,16 +13,16 @@ _new(char * cipher_name, SV * key)
int rv;
int id;
- id = find_cipher(cipher_name);
+ id = _find_cipher(cipher_name);
if (id == -1) croak("FATAL: find_cipfer failed for '%s'", cipher_name);
if (!SvPOK(key)) croak("FATAL: key must be string/buffer scalar");
k = (unsigned char *) SvPVbyte(key, k_len);
- Newz(0, RETVAL, 1, struct f9_struct);
+ Newz(0, RETVAL, 1, f9_state);
if (!RETVAL) croak("FATAL: Newz failed");
- rv = f9_init(&RETVAL->state, id, k, (unsigned long)k_len);
+ rv = f9_init(RETVAL, id, k, (unsigned long)k_len);
if (rv != CRYPT_OK) {
Safefree(RETVAL);
croak("FATAL: f9_init failed: %s", error_to_string(rv));
@@ -37,101 +39,119 @@ DESTROY(Crypt::Mac::F9 self)
Crypt::Mac::F9
clone(Crypt::Mac::F9 self)
CODE:
- Newz(0, RETVAL, 1, struct f9_struct);
+ Newz(0, RETVAL, 1, f9_state);
if (!RETVAL) croak("FATAL: Newz failed");
- Copy(&self->state, &RETVAL->state, 1, struct f9_struct);
+ Copy(self, RETVAL, 1, f9_state);
OUTPUT:
RETVAL
void
-_add_single(Crypt::Mac::F9 self, SV * data)
- CODE:
+add(Crypt::Mac::F9 self, ...)
+ PPCODE:
{
- int rv;
+ int rv, i;
STRLEN in_data_len;
unsigned char *in_data;
- in_data = (unsigned char *)SvPVbyte(data, in_data_len);
- if (in_data_len>0) {
- rv = f9_process(&self->state, in_data, (unsigned long)in_data_len);
- if (rv != CRYPT_OK) croak("FATAL: f9_process failed: %s", error_to_string(rv));
+ for(i = 1; i < items; i++) {
+ in_data = (unsigned char *)SvPVbyte(ST(i), in_data_len);
+ if (in_data_len > 0) {
+ rv = f9_process(self, in_data, (unsigned long)in_data_len);
+ if (rv != CRYPT_OK) croak("FATAL: f9_process failed: %s", error_to_string(rv));
+ }
}
+ XPUSHs(ST(0)); /* return self */
}
SV *
mac(Crypt::Mac::F9 self)
- CODE:
- {
- char mac[MAXBLOCKSIZE];
- unsigned long mac_len;
- int rv;
-
- mac_len = sizeof(mac);
- rv = f9_done(&self->state, (unsigned char*)mac, &mac_len);
- if (rv != CRYPT_OK) croak("FATAL: f9_done failed: %s", error_to_string(rv));
- RETVAL = newSVpvn(mac, mac_len);
- }
- OUTPUT:
- RETVAL
-
-SV *
-b64mac(Crypt::Mac::F9 self)
+ ALIAS:
+ hexmac = 1
+ b64mac = 2
+ b64umac = 3
CODE:
{
unsigned char mac[MAXBLOCKSIZE];
- unsigned long mac_len;
+ unsigned long maclen, outlen;
int rv;
- unsigned long outlen;
- char mac_base64[MAXBLOCKSIZE*2 + 1];
+ char out[MAXBLOCKSIZE*2];
- mac_len = sizeof(mac);
- rv = f9_done(&self->state, mac, &mac_len);
+ maclen = sizeof(mac);
+ rv = f9_done(self, mac, &maclen);
if (rv != CRYPT_OK) croak("FATAL: f9_done failed: %s", error_to_string(rv));
- outlen = sizeof(mac_base64);
- rv = base64_encode(mac, mac_len, (unsigned char*)mac_base64, &outlen);
- if (rv != CRYPT_OK) croak("FATAL: base64_encode failed: %s", error_to_string(rv));
- RETVAL = newSVpvn(mac_base64, outlen);
+ outlen = sizeof(out);
+ if (ix == 3) {
+ rv = base64url_encode(mac, maclen, (unsigned char*)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base64url_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn(out, outlen);
+ }
+ if (ix == 2) {
+ rv = base64_encode(mac, maclen, (unsigned char*)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base64_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn(out, outlen);
+ }
+ if (ix == 1) {
+ rv = _base16_encode(mac, maclen, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base16_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn(out, outlen);
+ }
+ else {
+ RETVAL = newSVpvn((char * )mac, maclen);
+ }
}
OUTPUT:
RETVAL
SV *
-b64umac(Crypt::Mac::F9 self)
+f9(char * cipher_name, SV * key, ...)
+ ALIAS:
+ f9_hex = 1
+ f9_b64 = 2
+ f9_b64u = 3
CODE:
{
+ STRLEN inlen, klen;
+ unsigned char *in;
+ unsigned char *k = (unsigned char *)SvPVbyte(key, klen);
+ int rv, i;
unsigned char mac[MAXBLOCKSIZE];
- unsigned long mac_len;
- int rv;
- unsigned long outlen;
- char mac_base64[MAXBLOCKSIZE*2 + 1];
-
- mac_len = sizeof(mac);
- rv = f9_done(&self->state, mac, &mac_len);
+ unsigned long len = sizeof(mac), outlen;
+ char out[MAXBLOCKSIZE*2];
+ f9_state st;
+
+ int id = _find_cipher(cipher_name);
+ if (id == -1) croak("FATAL: find_cipher failed for '%s'", cipher_name);
+ rv = f9_init(&st, id, k, (unsigned long)klen);
+ if (rv != CRYPT_OK) croak("FATAL: f9_init failed: %s", error_to_string(rv));
+ for (i = 2; i < items; i++) {
+ in = (unsigned char *)SvPVbyte(ST(i), inlen);
+ if (inlen > 0) {
+ rv = f9_process(&st, in, (unsigned long)inlen);
+ if (rv != CRYPT_OK) croak("FATAL: f9_process failed: %s", error_to_string(rv));
+ }
+ }
+ rv = f9_done(&st, mac, &len);
if (rv != CRYPT_OK) croak("FATAL: f9_done failed: %s", error_to_string(rv));
- outlen = sizeof(mac_base64);
- rv = base64url_encode(mac, mac_len, (unsigned char*)mac_base64, &outlen);
- if (rv != CRYPT_OK) croak("FATAL: base64url_encode failed: %s", error_to_string(rv));
- RETVAL = newSVpvn(mac_base64, outlen);
- }
- OUTPUT:
- RETVAL
-SV *
-hexmac(Crypt::Mac::F9 self)
- CODE:
- {
- unsigned char mac[MAXBLOCKSIZE];
- unsigned long mac_len, i;
- int rv;
- char mac_hex[MAXBLOCKSIZE*2 + 1];
-
- mac_len = sizeof(mac);
- rv = f9_done(&self->state, mac, &mac_len);
- if (rv != CRYPT_OK) croak("FATAL: f9_done failed: %s", error_to_string(rv));
- mac_hex[0] = '\0';
- for(i=0; i<mac_len; i++)
- sprintf(&mac_hex[2*i], "%02x", mac[i]);
- RETVAL = newSVpvn(mac_hex, strlen(mac_hex));
+ outlen = sizeof(out);
+ if (ix == 3) {
+ rv = base64url_encode(mac, len, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base64url_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn((char *) out, outlen);
+ }
+ else if (ix == 2) {
+ rv = base64_encode(mac, len, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base64_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn((char *) out, outlen);
+ }
+ else if (ix == 1) {
+ rv = _base16_encode(mac, len, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base16_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn((char *) out, outlen);
+ }
+ else {
+ RETVAL = newSVpvn((char *) mac, len);
+ }
}
OUTPUT:
RETVAL
diff --git a/inc/CryptX_Mac_HMAC.xs.inc b/inc/CryptX_Mac_HMAC.xs.inc
index 315aef41..8e4f73c9 100644
--- a/inc/CryptX_Mac_HMAC.xs.inc
+++ b/inc/CryptX_Mac_HMAC.xs.inc
@@ -1,9 +1,11 @@
MODULE = CryptX PACKAGE = Crypt::Mac::HMAC
+PROTOTYPES: DISABLE
+
### BEWARE - GENERATED FILE, DO NOT EDIT MANUALLY!
Crypt::Mac::HMAC
-_new(char * hash_name, SV * key)
+new(Class, char * hash_name, SV * key)
CODE:
{
STRLEN k_len=0;
@@ -11,16 +13,16 @@ _new(char * hash_name, SV * key)
int rv;
int id;
- id = find_hash(hash_name);
+ id = _find_hash(hash_name);
if (id == -1) croak("FATAL: find_hash failed for '%s'", hash_name);
if (!SvPOK(key)) croak("FATAL: key must be string/buffer scalar");
k = (unsigned char *) SvPVbyte(key, k_len);
- Newz(0, RETVAL, 1, struct hmac_struct);
+ Newz(0, RETVAL, 1, hmac_state);
if (!RETVAL) croak("FATAL: Newz failed");
- rv = hmac_init(&RETVAL->state, id, k, (unsigned long)k_len);
+ rv = hmac_init(RETVAL, id, k, (unsigned long)k_len);
if (rv != CRYPT_OK) {
Safefree(RETVAL);
croak("FATAL: hmac_init failed: %s", error_to_string(rv));
@@ -37,101 +39,119 @@ DESTROY(Crypt::Mac::HMAC self)
Crypt::Mac::HMAC
clone(Crypt::Mac::HMAC self)
CODE:
- Newz(0, RETVAL, 1, struct hmac_struct);
+ Newz(0, RETVAL, 1, hmac_state);
if (!RETVAL) croak("FATAL: Newz failed");
- Copy(&self->state, &RETVAL->state, 1, struct hmac_struct);
+ Copy(self, RETVAL, 1, hmac_state);
OUTPUT:
RETVAL
void
-_add_single(Crypt::Mac::HMAC self, SV * data)
- CODE:
+add(Crypt::Mac::HMAC self, ...)
+ PPCODE:
{
- int rv;
+ int rv, i;
STRLEN in_data_len;
unsigned char *in_data;
- in_data = (unsigned char *)SvPVbyte(data, in_data_len);
- if (in_data_len>0) {
- rv = hmac_process(&self->state, in_data, (unsigned long)in_data_len);
- if (rv != CRYPT_OK) croak("FATAL: hmac_process failed: %s", error_to_string(rv));
+ for(i = 1; i < items; i++) {
+ in_data = (unsigned char *)SvPVbyte(ST(i), in_data_len);
+ if (in_data_len > 0) {
+ rv = hmac_process(self, in_data, (unsigned long)in_data_len);
+ if (rv != CRYPT_OK) croak("FATAL: hmac_process failed: %s", error_to_string(rv));
+ }
}
+ XPUSHs(ST(0)); /* return self */
}
SV *
mac(Crypt::Mac::HMAC self)
- CODE:
- {
- char mac[MAXBLOCKSIZE];
- unsigned long mac_len;
- int rv;
-
- mac_len = sizeof(mac);
- rv = hmac_done(&self->state, (unsigned char*)mac, &mac_len);
- if (rv != CRYPT_OK) croak("FATAL: hmac_done failed: %s", error_to_string(rv));
- RETVAL = newSVpvn(mac, mac_len);
- }
- OUTPUT:
- RETVAL
-
-SV *
-b64mac(Crypt::Mac::HMAC self)
+ ALIAS:
+ hexmac = 1
+ b64mac = 2
+ b64umac = 3
CODE:
{
unsigned char mac[MAXBLOCKSIZE];
- unsigned long mac_len;
+ unsigned long maclen, outlen;
int rv;
- unsigned long outlen;
- char mac_base64[MAXBLOCKSIZE*2 + 1];
+ char out[MAXBLOCKSIZE*2];
- mac_len = sizeof(mac);
- rv = hmac_done(&self->state, mac, &mac_len);
+ maclen = sizeof(mac);
+ rv = hmac_done(self, mac, &maclen);
if (rv != CRYPT_OK) croak("FATAL: hmac_done failed: %s", error_to_string(rv));
- outlen = sizeof(mac_base64);
- rv = base64_encode(mac, mac_len, (unsigned char*)mac_base64, &outlen);
- if (rv != CRYPT_OK) croak("FATAL: base64_encode failed: %s", error_to_string(rv));
- RETVAL = newSVpvn(mac_base64, outlen);
+ outlen = sizeof(out);
+ if (ix == 3) {
+ rv = base64url_encode(mac, maclen, (unsigned char*)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base64url_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn(out, outlen);
+ }
+ if (ix == 2) {
+ rv = base64_encode(mac, maclen, (unsigned char*)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base64_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn(out, outlen);
+ }
+ if (ix == 1) {
+ rv = _base16_encode(mac, maclen, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base16_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn(out, outlen);
+ }
+ else {
+ RETVAL = newSVpvn((char * )mac, maclen);
+ }
}
OUTPUT:
RETVAL
SV *
-b64umac(Crypt::Mac::HMAC self)
+hmac(char * hash_name, SV * key, ...)
+ ALIAS:
+ hmac_hex = 1
+ hmac_b64 = 2
+ hmac_b64u = 3
CODE:
{
+ STRLEN inlen, klen;
+ unsigned char *in;
+ unsigned char *k = (unsigned char *)SvPVbyte(key, klen);
+ int rv, i;
unsigned char mac[MAXBLOCKSIZE];
- unsigned long mac_len;
- int rv;
- unsigned long outlen;
- char mac_base64[MAXBLOCKSIZE*2 + 1];
-
- mac_len = sizeof(mac);
- rv = hmac_done(&self->state, mac, &mac_len);
+ unsigned long len = sizeof(mac), outlen;
+ char out[MAXBLOCKSIZE*2];
+ hmac_state st;
+
+ int id = _find_hash(hash_name);
+ if (id == -1) croak("FATAL: find_digest failed for '%s'", hash_name);
+ rv = hmac_init(&st, id, k, (unsigned long)klen);
+ if (rv != CRYPT_OK) croak("FATAL: hmac_init failed: %s", error_to_string(rv));
+ for (i = 2; i < items; i++) {
+ in = (unsigned char *)SvPVbyte(ST(i), inlen);
+ if (inlen > 0) {
+ rv = hmac_process(&st, in, (unsigned long)inlen);
+ if (rv != CRYPT_OK) croak("FATAL: hmac_process failed: %s", error_to_string(rv));
+ }
+ }
+ rv = hmac_done(&st, mac, &len);
if (rv != CRYPT_OK) croak("FATAL: hmac_done failed: %s", error_to_string(rv));
- outlen = sizeof(mac_base64);
- rv = base64url_encode(mac, mac_len, (unsigned char*)mac_base64, &outlen);
- if (rv != CRYPT_OK) croak("FATAL: base64url_encode failed: %s", error_to_string(rv));
- RETVAL = newSVpvn(mac_base64, outlen);
- }
- OUTPUT:
- RETVAL
-SV *
-hexmac(Crypt::Mac::HMAC self)
- CODE:
- {
- unsigned char mac[MAXBLOCKSIZE];
- unsigned long mac_len, i;
- int rv;
- char mac_hex[MAXBLOCKSIZE*2 + 1];
-
- mac_len = sizeof(mac);
- rv = hmac_done(&self->state, mac, &mac_len);
- if (rv != CRYPT_OK) croak("FATAL: hmac_done failed: %s", error_to_string(rv));
- mac_hex[0] = '\0';
- for(i=0; i<mac_len; i++)
- sprintf(&mac_hex[2*i], "%02x", mac[i]);
- RETVAL = newSVpvn(mac_hex, strlen(mac_hex));
+ outlen = sizeof(out);
+ if (ix == 3) {
+ rv = base64url_encode(mac, len, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base64url_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn((char *) out, outlen);
+ }
+ else if (ix == 2) {
+ rv = base64_encode(mac, len, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base64_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn((char *) out, outlen);
+ }
+ else if (ix == 1) {
+ rv = _base16_encode(mac, len, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base16_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn((char *) out, outlen);
+ }
+ else {
+ RETVAL = newSVpvn((char *) mac, len);
+ }
}
OUTPUT:
RETVAL
diff --git a/inc/CryptX_Mac_OMAC.xs.inc b/inc/CryptX_Mac_OMAC.xs.inc
index 5f4565e8..aa8699af 100644
--- a/inc/CryptX_Mac_OMAC.xs.inc
+++ b/inc/CryptX_Mac_OMAC.xs.inc
@@ -1,9 +1,11 @@
MODULE = CryptX PACKAGE = Crypt::Mac::OMAC
+PROTOTYPES: DISABLE
+
### BEWARE - GENERATED FILE, DO NOT EDIT MANUALLY!
Crypt::Mac::OMAC
-_new(char * cipher_name, SV * key)
+new(Class, char * cipher_name, SV * key)
CODE:
{
STRLEN k_len=0;
@@ -11,16 +13,16 @@ _new(char * cipher_name, SV * key)
int rv;
int id;
- id = find_cipher(cipher_name);
+ id = _find_cipher(cipher_name);
if (id == -1) croak("FATAL: find_cipfer failed for '%s'", cipher_name);
if (!SvPOK(key)) croak("FATAL: key must be string/buffer scalar");
k = (unsigned char *) SvPVbyte(key, k_len);
- Newz(0, RETVAL, 1, struct omac_struct);
+ Newz(0, RETVAL, 1, omac_state);
if (!RETVAL) croak("FATAL: Newz failed");
- rv = omac_init(&RETVAL->state, id, k, (unsigned long)k_len);
+ rv = omac_init(RETVAL, id, k, (unsigned long)k_len);
if (rv != CRYPT_OK) {
Safefree(RETVAL);
croak("FATAL: omac_init failed: %s", error_to_string(rv));
@@ -37,101 +39,119 @@ DESTROY(Crypt::Mac::OMAC self)
Crypt::Mac::OMAC
clone(Crypt::Mac::OMAC self)
CODE:
- Newz(0, RETVAL, 1, struct omac_struct);
+ Newz(0, RETVAL, 1, omac_state);
if (!RETVAL) croak("FATAL: Newz failed");
- Copy(&self->state, &RETVAL->state, 1, struct omac_struct);
+ Copy(self, RETVAL, 1, omac_state);
OUTPUT:
RETVAL
void
-_add_single(Crypt::Mac::OMAC self, SV * data)
- CODE:
+add(Crypt::Mac::OMAC self, ...)
+ PPCODE:
{
- int rv;
+ int rv, i;
STRLEN in_data_len;
unsigned char *in_data;
- in_data = (unsigned char *)SvPVbyte(data, in_data_len);
- if (in_data_len>0) {
- rv = omac_process(&self->state, in_data, (unsigned long)in_data_len);
- if (rv != CRYPT_OK) croak("FATAL: omac_process failed: %s", error_to_string(rv));
+ for(i = 1; i < items; i++) {
+ in_data = (unsigned char *)SvPVbyte(ST(i), in_data_len);
+ if (in_data_len > 0) {
+ rv = omac_process(self, in_data, (unsigned long)in_data_len);
+ if (rv != CRYPT_OK) croak("FATAL: omac_process failed: %s", error_to_string(rv));
+ }
}
+ XPUSHs(ST(0)); /* return self */
}
SV *
mac(Crypt::Mac::OMAC self)
- CODE:
- {
- char mac[MAXBLOCKSIZE];
- unsigned long mac_len;
- int rv;
-
- mac_len = sizeof(mac);
- rv = omac_done(&self->state, (unsigned char*)mac, &mac_len);
- if (rv != CRYPT_OK) croak("FATAL: omac_done failed: %s", error_to_string(rv));
- RETVAL = newSVpvn(mac, mac_len);
- }
- OUTPUT:
- RETVAL
-
-SV *
-b64mac(Crypt::Mac::OMAC self)
+ ALIAS:
+ hexmac = 1
+ b64mac = 2
+ b64umac = 3
CODE:
{
unsigned char mac[MAXBLOCKSIZE];
- unsigned long mac_len;
+ unsigned long maclen, outlen;
int rv;
- unsigned long outlen;
- char mac_base64[MAXBLOCKSIZE*2 + 1];
+ char out[MAXBLOCKSIZE*2];
- mac_len = sizeof(mac);
- rv = omac_done(&self->state, mac, &mac_len);
+ maclen = sizeof(mac);
+ rv = omac_done(self, mac, &maclen);
if (rv != CRYPT_OK) croak("FATAL: omac_done failed: %s", error_to_string(rv));
- outlen = sizeof(mac_base64);
- rv = base64_encode(mac, mac_len, (unsigned char*)mac_base64, &outlen);
- if (rv != CRYPT_OK) croak("FATAL: base64_encode failed: %s", error_to_string(rv));
- RETVAL = newSVpvn(mac_base64, outlen);
+ outlen = sizeof(out);
+ if (ix == 3) {
+ rv = base64url_encode(mac, maclen, (unsigned char*)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base64url_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn(out, outlen);
+ }
+ if (ix == 2) {
+ rv = base64_encode(mac, maclen, (unsigned char*)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base64_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn(out, outlen);
+ }
+ if (ix == 1) {
+ rv = _base16_encode(mac, maclen, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base16_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn(out, outlen);
+ }
+ else {
+ RETVAL = newSVpvn((char * )mac, maclen);
+ }
}
OUTPUT:
RETVAL
SV *
-b64umac(Crypt::Mac::OMAC self)
+omac(char * cipher_name, SV * key, ...)
+ ALIAS:
+ omac_hex = 1
+ omac_b64 = 2
+ omac_b64u = 3
CODE:
{
+ STRLEN inlen, klen;
+ unsigned char *in;
+ unsigned char *k = (unsigned char *)SvPVbyte(key, klen);
+ int rv, i;
unsigned char mac[MAXBLOCKSIZE];
- unsigned long mac_len;
- int rv;
- unsigned long outlen;
- char mac_base64[MAXBLOCKSIZE*2 + 1];
-
- mac_len = sizeof(mac);
- rv = omac_done(&self->state, mac, &mac_len);
+ unsigned long len = sizeof(mac), outlen;
+ char out[MAXBLOCKSIZE*2];
+ omac_state st;
+
+ int id = _find_cipher(cipher_name);
+ if (id == -1) croak("FATAL: find_cipher failed for '%s'", cipher_name);
+ rv = omac_init(&st, id, k, (unsigned long)klen);
+ if (rv != CRYPT_OK) croak("FATAL: omac_init failed: %s", error_to_string(rv));
+ for (i = 2; i < items; i++) {
+ in = (unsigned char *)SvPVbyte(ST(i), inlen);
+ if (inlen > 0) {
+ rv = omac_process(&st, in, (unsigned long)inlen);
+ if (rv != CRYPT_OK) croak("FATAL: omac_process failed: %s", error_to_string(rv));
+ }
+ }
+ rv = omac_done(&st, mac, &len);
if (rv != CRYPT_OK) croak("FATAL: omac_done failed: %s", error_to_string(rv));
- outlen = sizeof(mac_base64);
- rv = base64url_encode(mac, mac_len, (unsigned char*)mac_base64, &outlen);
- if (rv != CRYPT_OK) croak("FATAL: base64url_encode failed: %s", error_to_string(rv));
- RETVAL = newSVpvn(mac_base64, outlen);
- }
- OUTPUT:
- RETVAL
-SV *
-hexmac(Crypt::Mac::OMAC self)
- CODE:
- {
- unsigned char mac[MAXBLOCKSIZE];
- unsigned long mac_len, i;
- int rv;
- char mac_hex[MAXBLOCKSIZE*2 + 1];
-
- mac_len = sizeof(mac);
- rv = omac_done(&self->state, mac, &mac_len);
- if (rv != CRYPT_OK) croak("FATAL: omac_done failed: %s", error_to_string(rv));
- mac_hex[0] = '\0';
- for(i=0; i<mac_len; i++)
- sprintf(&mac_hex[2*i], "%02x", mac[i]);
- RETVAL = newSVpvn(mac_hex, strlen(mac_hex));
+ outlen = sizeof(out);
+ if (ix == 3) {
+ rv = base64url_encode(mac, len, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base64url_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn((char *) out, outlen);
+ }
+ else if (ix == 2) {
+ rv = base64_encode(mac, len, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base64_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn((char *) out, outlen);
+ }
+ else if (ix == 1) {
+ rv = _base16_encode(mac, len, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base16_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn((char *) out, outlen);
+ }
+ else {
+ RETVAL = newSVpvn((char *) mac, len);
+ }
}
OUTPUT:
RETVAL
diff --git a/inc/CryptX_Mac_PMAC.xs.inc b/inc/CryptX_Mac_PMAC.xs.inc
index 1308fb0d..9ee709df 100644
--- a/inc/CryptX_Mac_PMAC.xs.inc
+++ b/inc/CryptX_Mac_PMAC.xs.inc
@@ -1,9 +1,11 @@
MODULE = CryptX PACKAGE = Crypt::Mac::PMAC
+PROTOTYPES: DISABLE
+
### BEWARE - GENERATED FILE, DO NOT EDIT MANUALLY!
Crypt::Mac::PMAC
-_new(char * cipher_name, SV * key)
+new(Class, char * cipher_name, SV * key)
CODE:
{
STRLEN k_len=0;
@@ -11,16 +13,16 @@ _new(char * cipher_name, SV * key)
int rv;
int id;
- id = find_cipher(cipher_name);
+ id = _find_cipher(cipher_name);
if (id == -1) croak("FATAL: find_cipfer failed for '%s'", cipher_name);
if (!SvPOK(key)) croak("FATAL: key must be string/buffer scalar");
k = (unsigned char *) SvPVbyte(key, k_len);
- Newz(0, RETVAL, 1, struct pmac_struct);
+ Newz(0, RETVAL, 1, pmac_state);
if (!RETVAL) croak("FATAL: Newz failed");
- rv = pmac_init(&RETVAL->state, id, k, (unsigned long)k_len);
+ rv = pmac_init(RETVAL, id, k, (unsigned long)k_len);
if (rv != CRYPT_OK) {
Safefree(RETVAL);
croak("FATAL: pmac_init failed: %s", error_to_string(rv));
@@ -37,101 +39,119 @@ DESTROY(Crypt::Mac::PMAC self)
Crypt::Mac::PMAC
clone(Crypt::Mac::PMAC self)
CODE:
- Newz(0, RETVAL, 1, struct pmac_struct);
+ Newz(0, RETVAL, 1, pmac_state);
if (!RETVAL) croak("FATAL: Newz failed");
- Copy(&self->state, &RETVAL->state, 1, struct pmac_struct);
+ Copy(self, RETVAL, 1, pmac_state);
OUTPUT:
RETVAL
void
-_add_single(Crypt::Mac::PMAC self, SV * data)
- CODE:
+add(Crypt::Mac::PMAC self, ...)
+ PPCODE:
{
- int rv;
+ int rv, i;
STRLEN in_data_len;
unsigned char *in_data;
- in_data = (unsigned char *)SvPVbyte(data, in_data_len);
- if (in_data_len>0) {
- rv = pmac_process(&self->state, in_data, (unsigned long)in_data_len);
- if (rv != CRYPT_OK) croak("FATAL: pmac_process failed: %s", error_to_string(rv));
+ for(i = 1; i < items; i++) {
+ in_data = (unsigned char *)SvPVbyte(ST(i), in_data_len);
+ if (in_data_len > 0) {
+ rv = pmac_process(self, in_data, (unsigned long)in_data_len);
+ if (rv != CRYPT_OK) croak("FATAL: pmac_process failed: %s", error_to_string(rv));
+ }
}
+ XPUSHs(ST(0)); /* return self */
}
SV *
mac(Crypt::Mac::PMAC self)
- CODE:
- {
- char mac[MAXBLOCKSIZE];
- unsigned long mac_len;
- int rv;
-
- mac_len = sizeof(mac);
- rv = pmac_done(&self->state, (unsigned char*)mac, &mac_len);
- if (rv != CRYPT_OK) croak("FATAL: pmac_done failed: %s", error_to_string(rv));
- RETVAL = newSVpvn(mac, mac_len);
- }
- OUTPUT:
- RETVAL
-
-SV *
-b64mac(Crypt::Mac::PMAC self)
+ ALIAS:
+ hexmac = 1
+ b64mac = 2
+ b64umac = 3
CODE:
{
unsigned char mac[MAXBLOCKSIZE];
- unsigned long mac_len;
+ unsigned long maclen, outlen;
int rv;
- unsigned long outlen;
- char mac_base64[MAXBLOCKSIZE*2 + 1];
+ char out[MAXBLOCKSIZE*2];
- mac_len = sizeof(mac);
- rv = pmac_done(&self->state, mac, &mac_len);
+ maclen = sizeof(mac);
+ rv = pmac_done(self, mac, &maclen);
if (rv != CRYPT_OK) croak("FATAL: pmac_done failed: %s", error_to_string(rv));
- outlen = sizeof(mac_base64);
- rv = base64_encode(mac, mac_len, (unsigned char*)mac_base64, &outlen);
- if (rv != CRYPT_OK) croak("FATAL: base64_encode failed: %s", error_to_string(rv));
- RETVAL = newSVpvn(mac_base64, outlen);
+ outlen = sizeof(out);
+ if (ix == 3) {
+ rv = base64url_encode(mac, maclen, (unsigned char*)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base64url_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn(out, outlen);
+ }
+ if (ix == 2) {
+ rv = base64_encode(mac, maclen, (unsigned char*)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base64_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn(out, outlen);
+ }
+ if (ix == 1) {
+ rv = _base16_encode(mac, maclen, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base16_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn(out, outlen);
+ }
+ else {
+ RETVAL = newSVpvn((char * )mac, maclen);
+ }
}
OUTPUT:
RETVAL
SV *
-b64umac(Crypt::Mac::PMAC self)
+pmac(char * cipher_name, SV * key, ...)
+ ALIAS:
+ pmac_hex = 1
+ pmac_b64 = 2
+ pmac_b64u = 3
CODE:
{
+ STRLEN inlen, klen;
+ unsigned char *in;
+ unsigned char *k = (unsigned char *)SvPVbyte(key, klen);
+ int rv, i;
unsigned char mac[MAXBLOCKSIZE];
- unsigned long mac_len;
- int rv;
- unsigned long outlen;
- char mac_base64[MAXBLOCKSIZE*2 + 1];
-
- mac_len = sizeof(mac);
- rv = pmac_done(&self->state, mac, &mac_len);
+ unsigned long len = sizeof(mac), outlen;
+ char out[MAXBLOCKSIZE*2];
+ pmac_state st;
+
+ int id = _find_cipher(cipher_name);
+ if (id == -1) croak("FATAL: find_cipher failed for '%s'", cipher_name);
+ rv = pmac_init(&st, id, k, (unsigned long)klen);
+ if (rv != CRYPT_OK) croak("FATAL: pmac_init failed: %s", error_to_string(rv));
+ for (i = 2; i < items; i++) {
+ in = (unsigned char *)SvPVbyte(ST(i), inlen);
+ if (inlen > 0) {
+ rv = pmac_process(&st, in, (unsigned long)inlen);
+ if (rv != CRYPT_OK) croak("FATAL: pmac_process failed: %s", error_to_string(rv));
+ }
+ }
+ rv = pmac_done(&st, mac, &len);
if (rv != CRYPT_OK) croak("FATAL: pmac_done failed: %s", error_to_string(rv));
- outlen = sizeof(mac_base64);
- rv = base64url_encode(mac, mac_len, (unsigned char*)mac_base64, &outlen);
- if (rv != CRYPT_OK) croak("FATAL: base64url_encode failed: %s", error_to_string(rv));
- RETVAL = newSVpvn(mac_base64, outlen);
- }
- OUTPUT:
- RETVAL
-SV *
-hexmac(Crypt::Mac::PMAC self)
- CODE:
- {
- unsigned char mac[MAXBLOCKSIZE];
- unsigned long mac_len, i;
- int rv;
- char mac_hex[MAXBLOCKSIZE*2 + 1];
-
- mac_len = sizeof(mac);
- rv = pmac_done(&self->state, mac, &mac_len);
- if (rv != CRYPT_OK) croak("FATAL: pmac_done failed: %s", error_to_string(rv));
- mac_hex[0] = '\0';
- for(i=0; i<mac_len; i++)
- sprintf(&mac_hex[2*i], "%02x", mac[i]);
- RETVAL = newSVpvn(mac_hex, strlen(mac_hex));
+ outlen = sizeof(out);
+ if (ix == 3) {
+ rv = base64url_encode(mac, len, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base64url_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn((char *) out, outlen);
+ }
+ else if (ix == 2) {
+ rv = base64_encode(mac, len, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base64_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn((char *) out, outlen);
+ }
+ else if (ix == 1) {
+ rv = _base16_encode(mac, len, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base16_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn((char *) out, outlen);
+ }
+ else {
+ RETVAL = newSVpvn((char *) mac, len);
+ }
}
OUTPUT:
RETVAL
diff --git a/inc/CryptX_Mac_Pelican.xs.inc b/inc/CryptX_Mac_Pelican.xs.inc
index 6e92f867..34840192 100644
--- a/inc/CryptX_Mac_Pelican.xs.inc
+++ b/inc/CryptX_Mac_Pelican.xs.inc
@@ -1,9 +1,11 @@
MODULE = CryptX PACKAGE = Crypt::Mac::Pelican
+PROTOTYPES: DISABLE
+
### BEWARE - GENERATED FILE, DO NOT EDIT MANUALLY!
Crypt::Mac::Pelican
-_new(SV * key)
+new(Class, SV * key)
CODE:
{
STRLEN k_len=0;
@@ -13,10 +15,10 @@ _new(SV * key)
if (!SvPOK(key)) croak("FATAL: key must be string/buffer scalar");
k = (unsigned char *) SvPVbyte(key, k_len);
- Newz(0, RETVAL, 1, struct pelican_struct);
+ Newz(0, RETVAL, 1, pelican_state);
if (!RETVAL) croak("FATAL: Newz failed");
- rv = pelican_init(&RETVAL->state, k, (unsigned long)k_len);
+ rv = pelican_init(RETVAL, k, (unsigned long)k_len);
if (rv != CRYPT_OK) {
Safefree(RETVAL);
croak("FATAL: pelican_init failed: %s", error_to_string(rv));
@@ -33,101 +35,118 @@ DESTROY(Crypt::Mac::Pelican self)
Crypt::Mac::Pelican
clone(Crypt::Mac::Pelican self)
CODE:
- Newz(0, RETVAL, 1, struct pelican_struct);
+ Newz(0, RETVAL, 1, pelican_state);
if (!RETVAL) croak("FATAL: Newz failed");
- Copy(&self->state, &RETVAL->state, 1, struct pelican_struct);
+ Copy(self, RETVAL, 1, pelican_state);
OUTPUT:
RETVAL
void
-_add_single(Crypt::Mac::Pelican self, SV * data)
- CODE:
+add(Crypt::Mac::Pelican self, ...)
+ PPCODE:
{
- int rv;
+ int rv, i;
STRLEN in_data_len;
unsigned char *in_data;
- in_data = (unsigned char *)SvPVbyte(data, in_data_len);
- if (in_data_len>0) {
- rv = pelican_process(&self->state, in_data, (unsigned long)in_data_len);
- if (rv != CRYPT_OK) croak("FATAL: pelican_process failed: %s", error_to_string(rv));
+ for(i = 1; i < items; i++) {
+ in_data = (unsigned char *)SvPVbyte(ST(i), in_data_len);
+ if (in_data_len > 0) {
+ rv = pelican_process(self, in_data, (unsigned long)in_data_len);
+ if (rv != CRYPT_OK) croak("FATAL: pelican_process failed: %s", error_to_string(rv));
+ }
}
+ XPUSHs(ST(0)); /* return self */
}
SV *
mac(Crypt::Mac::Pelican self)
- CODE:
- {
- char mac[MAXBLOCKSIZE];
- unsigned long mac_len;
- int rv;
-
- mac_len = 16;
- rv = pelican_done(&self->state, (unsigned char*)mac);
- if (rv != CRYPT_OK) croak("FATAL: pelican_done failed: %s", error_to_string(rv));
- RETVAL = newSVpvn(mac, mac_len);
- }
- OUTPUT:
- RETVAL
-
-SV *
-b64mac(Crypt::Mac::Pelican self)
+ ALIAS:
+ hexmac = 1
+ b64mac = 2
+ b64umac = 3
CODE:
{
unsigned char mac[MAXBLOCKSIZE];
- unsigned long mac_len;
+ unsigned long maclen, outlen;
int rv;
- unsigned long outlen;
- char mac_base64[MAXBLOCKSIZE*2 + 1];
+ char out[MAXBLOCKSIZE*2];
- mac_len = 16;
- rv = pelican_done(&self->state, mac);
+ maclen = 16;
+ rv = pelican_done(self, mac);
if (rv != CRYPT_OK) croak("FATAL: pelican_done failed: %s", error_to_string(rv));
- outlen = sizeof(mac_base64);
- rv = base64_encode(mac, mac_len, (unsigned char*)mac_base64, &outlen);
- if (rv != CRYPT_OK) croak("FATAL: base64_encode failed: %s", error_to_string(rv));
- RETVAL = newSVpvn(mac_base64, outlen);
+ outlen = sizeof(out);
+ if (ix == 3) {
+ rv = base64url_encode(mac, maclen, (unsigned char*)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base64url_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn(out, outlen);
+ }
+ if (ix == 2) {
+ rv = base64_encode(mac, maclen, (unsigned char*)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base64_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn(out, outlen);
+ }
+ if (ix == 1) {
+ rv = _base16_encode(mac, maclen, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base16_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn(out, outlen);
+ }
+ else {
+ RETVAL = newSVpvn((char * )mac, maclen);
+ }
}
OUTPUT:
RETVAL
SV *
-b64umac(Crypt::Mac::Pelican self)
+pelican(SV * key, ...)
+ ALIAS:
+ pelican_hex = 1
+ pelican_b64 = 2
+ pelican_b64u = 3
CODE:
{
+ STRLEN inlen, klen;
+ unsigned char *in;
+ unsigned char *k = (unsigned char *)SvPVbyte(key, klen);
+ int rv, i;
unsigned char mac[MAXBLOCKSIZE];
- unsigned long mac_len;
- int rv;
- unsigned long outlen;
- char mac_base64[MAXBLOCKSIZE*2 + 1];
-
- mac_len = 16;
- rv = pelican_done(&self->state, mac);
+ unsigned long len = sizeof(mac), outlen;
+ char out[MAXBLOCKSIZE*2];
+ pelican_state st;
+
+ len = 16;
+ rv = pelican_init(&st, k, (unsigned long)klen);
+ if (rv != CRYPT_OK) croak("FATAL: pelican_init failed: %s", error_to_string(rv));
+ for (i = 1; i < items; i++) {
+ in = (unsigned char *)SvPVbyte(ST(i), inlen);
+ if (inlen > 0) {
+ rv = pelican_process(&st, in, (unsigned long)inlen);
+ if (rv != CRYPT_OK) croak("FATAL: pelican_process failed: %s", error_to_string(rv));
+ }
+ }
+ rv = pelican_done(&st, mac);
if (rv != CRYPT_OK) croak("FATAL: pelican_done failed: %s", error_to_string(rv));
- outlen = sizeof(mac_base64);
- rv = base64url_encode(mac, mac_len, (unsigned char*)mac_base64, &outlen);
- if (rv != CRYPT_OK) croak("FATAL: base64url_encode failed: %s", error_to_string(rv));
- RETVAL = newSVpvn(mac_base64, outlen);
- }
- OUTPUT:
- RETVAL
-SV *
-hexmac(Crypt::Mac::Pelican self)
- CODE:
- {
- unsigned char mac[MAXBLOCKSIZE];
- unsigned long mac_len, i;
- int rv;
- char mac_hex[MAXBLOCKSIZE*2 + 1];
-
- mac_len = 16;
- rv = pelican_done(&self->state, mac);
- if (rv != CRYPT_OK) croak("FATAL: pelican_done failed: %s", error_to_string(rv));
- mac_hex[0] = '\0';
- for(i=0; i<mac_len; i++)
- sprintf(&mac_hex[2*i], "%02x", mac[i]);
- RETVAL = newSVpvn(mac_hex, strlen(mac_hex));
+ outlen = sizeof(out);
+ if (ix == 3) {
+ rv = base64url_encode(mac, len, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base64url_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn((char *) out, outlen);
+ }
+ else if (ix == 2) {
+ rv = base64_encode(mac, len, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base64_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn((char *) out, outlen);
+ }
+ else if (ix == 1) {
+ rv = _base16_encode(mac, len, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base16_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn((char *) out, outlen);
+ }
+ else {
+ RETVAL = newSVpvn((char *) mac, len);
+ }
}
OUTPUT:
RETVAL
diff --git a/inc/CryptX_Mac_Poly1305.xs.inc b/inc/CryptX_Mac_Poly1305.xs.inc
index a8128156..6e50821a 100644
--- a/inc/CryptX_Mac_Poly1305.xs.inc
+++ b/inc/CryptX_Mac_Poly1305.xs.inc
@@ -1,9 +1,11 @@
MODULE = CryptX PACKAGE = Crypt::Mac::Poly1305
+PROTOTYPES: DISABLE
+
### BEWARE - GENERATED FILE, DO NOT EDIT MANUALLY!
Crypt::Mac::Poly1305
-_new(SV * key)
+new(Class, SV * key)
CODE:
{
STRLEN k_len=0;
@@ -13,10 +15,10 @@ _new(SV * key)
if (!SvPOK(key)) croak("FATAL: key must be string/buffer scalar");
k = (unsigned char *) SvPVbyte(key, k_len);
- Newz(0, RETVAL, 1, struct poly1305_struct);
+ Newz(0, RETVAL, 1, poly1305_state);
if (!RETVAL) croak("FATAL: Newz failed");
- rv = poly1305_init(&RETVAL->state, k, (unsigned long)k_len);
+ rv = poly1305_init(RETVAL, k, (unsigned long)k_len);
if (rv != CRYPT_OK) {
Safefree(RETVAL);
croak("FATAL: poly1305_init failed: %s", error_to_string(rv));
@@ -33,101 +35,117 @@ DESTROY(Crypt::Mac::Poly1305 self)
Crypt::Mac::Poly1305
clone(Crypt::Mac::Poly1305 self)
CODE:
- Newz(0, RETVAL, 1, struct poly1305_struct);
+ Newz(0, RETVAL, 1, poly1305_state);
if (!RETVAL) croak("FATAL: Newz failed");
- Copy(&self->state, &RETVAL->state, 1, struct poly1305_struct);
+ Copy(self, RETVAL, 1, poly1305_state);
OUTPUT:
RETVAL
void
-_add_single(Crypt::Mac::Poly1305 self, SV * data)
- CODE:
+add(Crypt::Mac::Poly1305 self, ...)
+ PPCODE:
{
- int rv;
+ int rv, i;
STRLEN in_data_len;
unsigned char *in_data;
- in_data = (unsigned char *)SvPVbyte(data, in_data_len);
- if (in_data_len>0) {
- rv = poly1305_process(&self->state, in_data, (unsigned long)in_data_len);
- if (rv != CRYPT_OK) croak("FATAL: poly1305_process failed: %s", error_to_string(rv));
+ for(i = 1; i < items; i++) {
+ in_data = (unsigned char *)SvPVbyte(ST(i), in_data_len);
+ if (in_data_len > 0) {
+ rv = poly1305_process(self, in_data, (unsigned long)in_data_len);
+ if (rv != CRYPT_OK) croak("FATAL: poly1305_process failed: %s", error_to_string(rv));
+ }
}
+ XPUSHs(ST(0)); /* return self */
}
SV *
mac(Crypt::Mac::Poly1305 self)
- CODE:
- {
- char mac[MAXBLOCKSIZE];
- unsigned long mac_len;
- int rv;
-
- mac_len = sizeof(mac);
- rv = poly1305_done(&self->state, (unsigned char*)mac, &mac_len);
- if (rv != CRYPT_OK) croak("FATAL: poly1305_done failed: %s", error_to_string(rv));
- RETVAL = newSVpvn(mac, mac_len);
- }
- OUTPUT:
- RETVAL
-
-SV *
-b64mac(Crypt::Mac::Poly1305 self)
+ ALIAS:
+ hexmac = 1
+ b64mac = 2
+ b64umac = 3
CODE:
{
unsigned char mac[MAXBLOCKSIZE];
- unsigned long mac_len;
+ unsigned long maclen, outlen;
int rv;
- unsigned long outlen;
- char mac_base64[MAXBLOCKSIZE*2 + 1];
+ char out[MAXBLOCKSIZE*2];
- mac_len = sizeof(mac);
- rv = poly1305_done(&self->state, mac, &mac_len);
+ maclen = sizeof(mac);
+ rv = poly1305_done(self, mac, &maclen);
if (rv != CRYPT_OK) croak("FATAL: poly1305_done failed: %s", error_to_string(rv));
- outlen = sizeof(mac_base64);
- rv = base64_encode(mac, mac_len, (unsigned char*)mac_base64, &outlen);
- if (rv != CRYPT_OK) croak("FATAL: base64_encode failed: %s", error_to_string(rv));
- RETVAL = newSVpvn(mac_base64, outlen);
+ outlen = sizeof(out);
+ if (ix == 3) {
+ rv = base64url_encode(mac, maclen, (unsigned char*)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base64url_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn(out, outlen);
+ }
+ if (ix == 2) {
+ rv = base64_encode(mac, maclen, (unsigned char*)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base64_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn(out, outlen);
+ }
+ if (ix == 1) {
+ rv = _base16_encode(mac, maclen, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base16_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn(out, outlen);
+ }
+ else {
+ RETVAL = newSVpvn((char * )mac, maclen);
+ }
}
OUTPUT:
RETVAL
SV *
-b64umac(Crypt::Mac::Poly1305 self)
+poly1305(SV * key, ...)
+ ALIAS:
+ poly1305_hex = 1
+ poly1305_b64 = 2
+ poly1305_b64u = 3
CODE:
{
+ STRLEN inlen, klen;
+ unsigned char *in;
+ unsigned char *k = (unsigned char *)SvPVbyte(key, klen);
+ int rv, i;
unsigned char mac[MAXBLOCKSIZE];
- unsigned long mac_len;
- int rv;
- unsigned long outlen;
- char mac_base64[MAXBLOCKSIZE*2 + 1];
-
- mac_len = sizeof(mac);
- rv = poly1305_done(&self->state, mac, &mac_len);
+ unsigned long len = sizeof(mac), outlen;
+ char out[MAXBLOCKSIZE*2];
+ poly1305_state st;
+
+ rv = poly1305_init(&st, k, (unsigned long)klen);
+ if (rv != CRYPT_OK) croak("FATAL: poly1305_init failed: %s", error_to_string(rv));
+ for (i = 1; i < items; i++) {
+ in = (unsigned char *)SvPVbyte(ST(i), inlen);
+ if (inlen > 0) {
+ rv = poly1305_process(&st, in, (unsigned long)inlen);
+ if (rv != CRYPT_OK) croak("FATAL: poly1305_process failed: %s", error_to_string(rv));
+ }
+ }
+ rv = poly1305_done(&st, mac, &len);
if (rv != CRYPT_OK) croak("FATAL: poly1305_done failed: %s", error_to_string(rv));
- outlen = sizeof(mac_base64);
- rv = base64url_encode(mac, mac_len, (unsigned char*)mac_base64, &outlen);
- if (rv != CRYPT_OK) croak("FATAL: base64url_encode failed: %s", error_to_string(rv));
- RETVAL = newSVpvn(mac_base64, outlen);
- }
- OUTPUT:
- RETVAL
-SV *
-hexmac(Crypt::Mac::Poly1305 self)
- CODE:
- {
- unsigned char mac[MAXBLOCKSIZE];
- unsigned long mac_len, i;
- int rv;
- char mac_hex[MAXBLOCKSIZE*2 + 1];
-
- mac_len = sizeof(mac);
- rv = poly1305_done(&self->state, mac, &mac_len);
- if (rv != CRYPT_OK) croak("FATAL: poly1305_done failed: %s", error_to_string(rv));
- mac_hex[0] = '\0';
- for(i=0; i<mac_len; i++)
- sprintf(&mac_hex[2*i], "%02x", mac[i]);
- RETVAL = newSVpvn(mac_hex, strlen(mac_hex));
+ outlen = sizeof(out);
+ if (ix == 3) {
+ rv = base64url_encode(mac, len, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base64url_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn((char *) out, outlen);
+ }
+ else if (ix == 2) {
+ rv = base64_encode(mac, len, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base64_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn((char *) out, outlen);
+ }
+ else if (ix == 1) {
+ rv = _base16_encode(mac, len, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base16_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn((char *) out, outlen);
+ }
+ else {
+ RETVAL = newSVpvn((char *) mac, len);
+ }
}
OUTPUT:
RETVAL
diff --git a/inc/CryptX_Mac_XCBC.xs.inc b/inc/CryptX_Mac_XCBC.xs.inc
index 01f37172..6563b677 100644
--- a/inc/CryptX_Mac_XCBC.xs.inc
+++ b/inc/CryptX_Mac_XCBC.xs.inc
@@ -1,9 +1,11 @@
MODULE = CryptX PACKAGE = Crypt::Mac::XCBC
+PROTOTYPES: DISABLE
+
### BEWARE - GENERATED FILE, DO NOT EDIT MANUALLY!
Crypt::Mac::XCBC
-_new(char * cipher_name, SV * key)
+new(Class, char * cipher_name, SV * key)
CODE:
{
STRLEN k_len=0;
@@ -11,16 +13,16 @@ _new(char * cipher_name, SV * key)
int rv;
int id;
- id = find_cipher(cipher_name);
+ id = _find_cipher(cipher_name);
if (id == -1) croak("FATAL: find_cipfer failed for '%s'", cipher_name);
if (!SvPOK(key)) croak("FATAL: key must be string/buffer scalar");
k = (unsigned char *) SvPVbyte(key, k_len);
- Newz(0, RETVAL, 1, struct xcbc_struct);
+ Newz(0, RETVAL, 1, xcbc_state);
if (!RETVAL) croak("FATAL: Newz failed");
- rv = xcbc_init(&RETVAL->state, id, k, (unsigned long)k_len);
+ rv = xcbc_init(RETVAL, id, k, (unsigned long)k_len);
if (rv != CRYPT_OK) {
Safefree(RETVAL);
croak("FATAL: xcbc_init failed: %s", error_to_string(rv));
@@ -37,101 +39,119 @@ DESTROY(Crypt::Mac::XCBC self)
Crypt::Mac::XCBC
clone(Crypt::Mac::XCBC self)
CODE:
- Newz(0, RETVAL, 1, struct xcbc_struct);
+ Newz(0, RETVAL, 1, xcbc_state);
if (!RETVAL) croak("FATAL: Newz failed");
- Copy(&self->state, &RETVAL->state, 1, struct xcbc_struct);
+ Copy(self, RETVAL, 1, xcbc_state);
OUTPUT:
RETVAL
void
-_add_single(Crypt::Mac::XCBC self, SV * data)
- CODE:
+add(Crypt::Mac::XCBC self, ...)
+ PPCODE:
{
- int rv;
+ int rv, i;
STRLEN in_data_len;
unsigned char *in_data;
- in_data = (unsigned char *)SvPVbyte(data, in_data_len);
- if (in_data_len>0) {
- rv = xcbc_process(&self->state, in_data, (unsigned long)in_data_len);
- if (rv != CRYPT_OK) croak("FATAL: xcbc_process failed: %s", error_to_string(rv));
+ for(i = 1; i < items; i++) {
+ in_data = (unsigned char *)SvPVbyte(ST(i), in_data_len);
+ if (in_data_len > 0) {
+ rv = xcbc_process(self, in_data, (unsigned long)in_data_len);
+ if (rv != CRYPT_OK) croak("FATAL: xcbc_process failed: %s", error_to_string(rv));
+ }
}
+ XPUSHs(ST(0)); /* return self */
}
SV *
mac(Crypt::Mac::XCBC self)
- CODE:
- {
- char mac[MAXBLOCKSIZE];
- unsigned long mac_len;
- int rv;
-
- mac_len = sizeof(mac);
- rv = xcbc_done(&self->state, (unsigned char*)mac, &mac_len);
- if (rv != CRYPT_OK) croak("FATAL: xcbc_done failed: %s", error_to_string(rv));
- RETVAL = newSVpvn(mac, mac_len);
- }
- OUTPUT:
- RETVAL
-
-SV *
-b64mac(Crypt::Mac::XCBC self)
+ ALIAS:
+ hexmac = 1
+ b64mac = 2
+ b64umac = 3
CODE:
{
unsigned char mac[MAXBLOCKSIZE];
- unsigned long mac_len;
+ unsigned long maclen, outlen;
int rv;
- unsigned long outlen;
- char mac_base64[MAXBLOCKSIZE*2 + 1];
+ char out[MAXBLOCKSIZE*2];
- mac_len = sizeof(mac);
- rv = xcbc_done(&self->state, mac, &mac_len);
+ maclen = sizeof(mac);
+ rv = xcbc_done(self, mac, &maclen);
if (rv != CRYPT_OK) croak("FATAL: xcbc_done failed: %s", error_to_string(rv));
- outlen = sizeof(mac_base64);
- rv = base64_encode(mac, mac_len, (unsigned char*)mac_base64, &outlen);
- if (rv != CRYPT_OK) croak("FATAL: base64_encode failed: %s", error_to_string(rv));
- RETVAL = newSVpvn(mac_base64, outlen);
+ outlen = sizeof(out);
+ if (ix == 3) {
+ rv = base64url_encode(mac, maclen, (unsigned char*)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base64url_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn(out, outlen);
+ }
+ if (ix == 2) {
+ rv = base64_encode(mac, maclen, (unsigned char*)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base64_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn(out, outlen);
+ }
+ if (ix == 1) {
+ rv = _base16_encode(mac, maclen, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base16_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn(out, outlen);
+ }
+ else {
+ RETVAL = newSVpvn((char * )mac, maclen);
+ }
}
OUTPUT:
RETVAL
SV *
-b64umac(Crypt::Mac::XCBC self)
+xcbc(char * cipher_name, SV * key, ...)
+ ALIAS:
+ xcbc_hex = 1
+ xcbc_b64 = 2
+ xcbc_b64u = 3
CODE:
{
+ STRLEN inlen, klen;
+ unsigned char *in;
+ unsigned char *k = (unsigned char *)SvPVbyte(key, klen);
+ int rv, i;
unsigned char mac[MAXBLOCKSIZE];
- unsigned long mac_len;
- int rv;
- unsigned long outlen;
- char mac_base64[MAXBLOCKSIZE*2 + 1];
-
- mac_len = sizeof(mac);
- rv = xcbc_done(&self->state, mac, &mac_len);
+ unsigned long len = sizeof(mac), outlen;
+ char out[MAXBLOCKSIZE*2];
+ xcbc_state st;
+
+ int id = _find_cipher(cipher_name);
+ if (id == -1) croak("FATAL: find_cipher failed for '%s'", cipher_name);
+ rv = xcbc_init(&st, id, k, (unsigned long)klen);
+ if (rv != CRYPT_OK) croak("FATAL: xcbc_init failed: %s", error_to_string(rv));
+ for (i = 2; i < items; i++) {
+ in = (unsigned char *)SvPVbyte(ST(i), inlen);
+ if (inlen > 0) {
+ rv = xcbc_process(&st, in, (unsigned long)inlen);
+ if (rv != CRYPT_OK) croak("FATAL: xcbc_process failed: %s", error_to_string(rv));
+ }
+ }
+ rv = xcbc_done(&st, mac, &len);
if (rv != CRYPT_OK) croak("FATAL: xcbc_done failed: %s", error_to_string(rv));
- outlen = sizeof(mac_base64);
- rv = base64url_encode(mac, mac_len, (unsigned char*)mac_base64, &outlen);
- if (rv != CRYPT_OK) croak("FATAL: base64url_encode failed: %s", error_to_string(rv));
- RETVAL = newSVpvn(mac_base64, outlen);
- }
- OUTPUT:
- RETVAL
-SV *
-hexmac(Crypt::Mac::XCBC self)
- CODE:
- {
- unsigned char mac[MAXBLOCKSIZE];
- unsigned long mac_len, i;
- int rv;
- char mac_hex[MAXBLOCKSIZE*2 + 1];
-
- mac_len = sizeof(mac);
- rv = xcbc_done(&self->state, mac, &mac_len);
- if (rv != CRYPT_OK) croak("FATAL: xcbc_done failed: %s", error_to_string(rv));
- mac_hex[0] = '\0';
- for(i=0; i<mac_len; i++)
- sprintf(&mac_hex[2*i], "%02x", mac[i]);
- RETVAL = newSVpvn(mac_hex, strlen(mac_hex));
+ outlen = sizeof(out);
+ if (ix == 3) {
+ rv = base64url_encode(mac, len, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base64url_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn((char *) out, outlen);
+ }
+ else if (ix == 2) {
+ rv = base64_encode(mac, len, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base64_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn((char *) out, outlen);
+ }
+ else if (ix == 1) {
+ rv = _base16_encode(mac, len, (unsigned char *)out, &outlen);
+ if (rv != CRYPT_OK) croak("FATAL: base16_encode failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn((char *) out, outlen);
+ }
+ else {
+ RETVAL = newSVpvn((char *) mac, len);
+ }
}
OUTPUT:
RETVAL
diff --git a/inc/CryptX_Mode_CBC.xs.inc b/inc/CryptX_Mode_CBC.xs.inc
index 6a86b794..c7cbe0a8 100644
--- a/inc/CryptX_Mode_CBC.xs.inc
+++ b/inc/CryptX_Mode_CBC.xs.inc
@@ -1,9 +1,11 @@
MODULE = CryptX PACKAGE = Crypt::Mode::CBC
+PROTOTYPES: DISABLE
+
### BEWARE - GENERATED FILE, DO NOT EDIT MANUALLY!
Crypt::Mode::CBC
-_new(char * cipher_name, int padding=1, int rounds=0)
+new(Class, char * cipher_name, int padding=1, int rounds=0)
CODE:
{
Newz(0, RETVAL, 1, struct cbc_struct);
@@ -12,7 +14,7 @@ _new(char * cipher_name, int padding=1, int rounds=0)
RETVAL->padlen = 0;
RETVAL->direction = 0;
RETVAL->cipher_rounds = rounds;
- RETVAL->cipher_id = find_cipher(cipher_name);
+ RETVAL->cipher_id = _find_cipher(cipher_name);
if (RETVAL->cipher_id == -1) {
Safefree(RETVAL);
croak("FATAL: find_cipfer failed for '%s'", cipher_name);
@@ -26,16 +28,11 @@ DESTROY(Crypt::Mode::CBC self)
CODE:
Safefree(self);
-int
-_get_dir(Crypt::Mode::CBC self)
- CODE:
- RETVAL = self->direction;
- OUTPUT:
- RETVAL
-
void
-_start(Crypt::Mode::CBC self, int dir, SV * key, SV * iv)
- CODE:
+start_decrypt(Crypt::Mode::CBC self, SV * key, SV * iv)
+ ALIAS:
+ start_encrypt = 1
+ PPCODE:
{
int rv;
STRLEN k_len=0;
@@ -56,243 +53,215 @@ _start(Crypt::Mode::CBC self, int dir, SV * key, SV * iv)
croak("FATAL: cbc_start failed: %s", error_to_string(rv));
}
- self->direction = dir;
+ self->direction = ix == 1 ? 1 : -1;
self->padlen = 0;
+ XPUSHs(ST(0)); /* return self */
}
SV *
-_encrypt(Crypt::Mode::CBC self, SV * data)
+add(Crypt::Mode::CBC self, ...)
CODE:
{
- int rv, has_tmp_block, blen;
+ int rv, has_tmp_block, blen, j;
unsigned long i;
-
- STRLEN in_data_len, in_data_start;
+ STRLEN in_data_len, in_data_start, out_len = 0;
unsigned char *in_data, *out_data, tmp_block[MAXBLOCKSIZE];
- if (self->direction != 1) croak("FATAL: encrypt error, call start_encrypt first (%d)", self->direction);
+ RETVAL = newSVpvn("", 0);
+ for (j = 1; j < items; j++) {
+ in_data = (unsigned char *)SvPVbyte(ST(j), in_data_len);
+ blen = (&self->state)->blocklen;
+ in_data_start = 0;
+ has_tmp_block = 0;
+ if (in_data_len > 0) {
+ if (self->direction == 1) {
+ /* handle non-empty self->pad buffer */
+ if (self->padlen > 0) {
+ i = (blen - self->padlen);
+ if (in_data_len >= i) { /* enough data to fill pad */
+ Copy(in_data, self->pad+self->padlen, i, unsigned char);
+ in_data_len -= i;
+ in_data_start = i;
+ rv = cbc_encrypt(self->pad, tmp_block, blen, &self->state);
+ if (rv != CRYPT_OK) {
+ SvREFCNT_dec(RETVAL);
+ croak("FATAL: cbc_encrypt failed: %s", error_to_string(rv));
+ }
+ self->padlen = 0;
+ has_tmp_block = 1;
+ }
+ else { /* not enough data to fill pad */
+ Copy(in_data, self->pad+self->padlen, in_data_len, unsigned char);
+ self->padlen += (int)in_data_len;
+ in_data_len = 0;
+ }
+ }
- blen = (&self->state)->blocklen;
- in_data_start = 0;
- has_tmp_block = 0;
- in_data = (unsigned char *)SvPVbyte(data, in_data_len);
- if (in_data_len == 0) {
- RETVAL = newSVpvn("", 0);
- }
- else {
- if (self->padlen > 0) {
- i = (blen - self->padlen);
- if (in_data_len >= i) { /* enough data to fill pad */
- Copy(in_data, self->pad+self->padlen, i, unsigned char);
- in_data_len -= i;
- in_data_start = i;
- rv = cbc_encrypt(self->pad, tmp_block, blen, &self->state);
- if (rv != CRYPT_OK) croak("FATAL: cbc_encrypt failed: %s", error_to_string(rv));
- self->padlen = 0;
- has_tmp_block = 1;
- }
- else { /* not enough data to fill pad */
- Copy(in_data, self->pad+self->padlen, in_data_len, unsigned char);
- self->padlen += (int)in_data_len;
- in_data_len = 0;
+ i = (unsigned long)(in_data_len % blen);
+ if (in_data_len > 0 && i > 0) { /* save tail of data into pad */
+ Copy(in_data + in_data_start + in_data_len - i, self->pad, i, unsigned char);
+ self->padlen = i;
+ in_data_len -= i;
+ }
+
+ if (in_data_len > 0) {
+ i = (unsigned long)(has_tmp_block ? in_data_len + blen : in_data_len);
+ out_data = (unsigned char*)SvGROW(RETVAL, out_len + i + 1) + out_len;
+ out_len += i;
+ if (has_tmp_block) {
+ Copy(tmp_block, out_data, blen, unsigned char);
+ out_data += blen;
+ }
+ rv = cbc_encrypt(in_data+in_data_start, out_data, (unsigned long)in_data_len, &self->state);
+ if (rv != CRYPT_OK) {
+ SvREFCNT_dec(RETVAL);
+ croak("FATAL: cbc_encrypt failed: %s", error_to_string(rv));
+ }
+ } /* in_data_len > 0 */
+ else if (has_tmp_block) {
+ out_data = (unsigned char*)SvGROW(RETVAL, out_len + blen + 1) + out_len;
+ out_len += blen;
+ Copy(tmp_block, out_data, blen, unsigned char);
+ }
}
- } /* padlen > 0 */
+ else if (self->direction == -1) {
+ if (self->padlen == blen) {
+ rv = cbc_decrypt(self->pad, tmp_block, blen, &self->state);
+ if (rv != CRYPT_OK) {
+ SvREFCNT_dec(RETVAL);
+ croak("FATAL: cbc_decrypt failed: %s", error_to_string(rv));
+ }
+ self->padlen = 0;
+ has_tmp_block = 1;
+ } /* padlen == blen */
+ else if (self->padlen > 0) {
+ i = (blen - self->padlen); /* remaining bytes in padding buffer */
+ if (in_data_len >= i) { /* enough data to fill pad */
+ Copy(in_data, self->pad+self->padlen, i, unsigned char);
+ self->padlen += i;
+ in_data_len -= i;
+ in_data_start = i;
+ if (in_data_len>0 || self->padding_mode == 0) {
+ rv = cbc_decrypt(self->pad, tmp_block, blen, &self->state);
+ if (rv != CRYPT_OK) {
+ SvREFCNT_dec(RETVAL);
+ croak("FATAL: cbc_decrypt failed: %s", error_to_string(rv));
+ }
+ self->padlen = 0;
+ has_tmp_block = 1;
+ }
+ }
+ else { /* not enough data to fill pad */
+ Copy(in_data, self->pad+self->padlen, in_data_len, unsigned char);
+ self->padlen += (int)in_data_len;
+ in_data_len = 0;
+ }
+ } /* padlen > 0 */
- i = (unsigned long)(in_data_len % blen);
- if (in_data_len>0 && i>0) { /* save tail of data into pad */
- Copy(in_data+in_data_start+in_data_len-i, self->pad, i, unsigned char);
- self->padlen = i;
- in_data_len -= i;
- }
+ /* here: a/ padlen == 1..16 && in_data_len == 0; b/ padlen == 0 && in_data_len > 0 */
+ if (in_data_len>0) {
+ i = (unsigned long)(in_data_len % blen);
+ if (i>0) { /* save tail of data into pad */
+ Copy(in_data+in_data_start+in_data_len-i, self->pad, i, unsigned char);
+ self->padlen = i;
+ in_data_len -= i;
+ }
+ }
- if (in_data_len > 0) {
- i = (unsigned long)(has_tmp_block ? in_data_len + blen : in_data_len);
- RETVAL = NEWSV(0, i);
- SvPOK_only(RETVAL);
- SvCUR_set(RETVAL, i);
- out_data = (unsigned char *)SvPVX(RETVAL);
- if (has_tmp_block) {
- Copy(tmp_block, out_data, blen, unsigned char);
- out_data += blen;
+ if (in_data_len>0) {
+ if (self->padlen == 0 && self->padding_mode !=0) {
+ /* in case of padding keep full pad if no more data */
+ Copy(in_data+in_data_start+in_data_len-blen, self->pad, blen, unsigned char);
+ self->padlen = blen;
+ in_data_len -= blen;
+ }
+ i = (unsigned long)(has_tmp_block ? in_data_len + blen : in_data_len);
+ if (i > 0) {
+ out_data = (unsigned char*)SvGROW(RETVAL, out_len + i + 1) + out_len;
+ out_len += i;
+ if (has_tmp_block) {
+ Copy(tmp_block, out_data, blen, unsigned char);
+ out_data += blen;
+ }
+ rv = cbc_decrypt(in_data+in_data_start, out_data, (unsigned long)in_data_len, &self->state);
+ if (rv != CRYPT_OK) {
+ SvREFCNT_dec(RETVAL);
+ croak("FATAL: cbc_decrypt failed: %s", error_to_string(rv));
+ }
+ }
+ } /* in_data_len>0 */
+ else if (has_tmp_block) {
+ out_data = (unsigned char*)SvGROW(RETVAL, out_len + blen + 1) + out_len;
+ out_len += blen;
+ Copy(tmp_block, out_data, blen, unsigned char);
+ }
}
- rv = cbc_encrypt(in_data+in_data_start, out_data, (unsigned long)in_data_len, &self->state);
- if (rv != CRYPT_OK) {
+ else {
SvREFCNT_dec(RETVAL);
- croak("FATAL: cbc_encrypt failed: %s", error_to_string(rv));
+ croak("FATAL: call start_decryt or start_encrpyt first (%d)", self->direction);
}
- } /* in_data_len>0 */
- else if (has_tmp_block) {
- RETVAL = newSVpvn((char*)tmp_block, blen);
}
- else {
- RETVAL = newSVpvn("", 0);
- }
- }
- }
- OUTPUT:
- RETVAL
-
-SV *
-_finish_enc(Crypt::Mode::CBC self)
- CODE:
- {
- unsigned char tmp_block[MAXBLOCKSIZE];
- int rv, blen, i, j;
-
- blen = (&self->state)->blocklen;
- if (self->padlen<0 || self->padlen>=blen) croak("FATAL: invalid padlen");
-
- if (self->padding_mode == 1) { /* pkcs5|7 padding */
- i = blen - self->padlen;
- if (i == 0) i = blen;
- for(j=self->padlen; j<blen; j++) self->pad[j] = (unsigned char)i;
- rv = cbc_encrypt(self->pad, tmp_block, blen, &self->state);
- if (rv != CRYPT_OK) croak("FATAL: cbc_encrypt failed: %s", error_to_string(rv));
- }
- else if (self->padding_mode == 2) { /* oneandzeroes padding */
- self->pad[self->padlen] = 0x80;
- for(j=self->padlen+1; j<blen; j++) self->pad[j] = 0;
- rv = cbc_encrypt(self->pad, tmp_block, blen, &self->state);
- if (rv != CRYPT_OK) croak("FATAL: cbc_encrypt failed: %s", error_to_string(rv));
- }
- else {
- if (self->padlen>0) croak("FATAL: cbc_encrypt, input data length not multiple of %d", blen);
- blen = 0;
}
-
- self->direction = 0;
- RETVAL = newSVpvn((char*)tmp_block, blen);
+ if (out_len > 0) SvCUR_set(RETVAL, out_len);
}
OUTPUT:
RETVAL
SV *
-_decrypt(Crypt::Mode::CBC self, SV * data)
+finish(Crypt::Mode::CBC self)
CODE:
{
- int rv, has_tmp_block, blen;
- unsigned long i;
- STRLEN in_data_len, in_data_start;
- unsigned char *in_data, *out_data, tmp_block[MAXBLOCKSIZE];
-
- if (self->direction != -1) croak("FATAL: decrypt error, call start_decryt first (%d)", self->direction);
+ unsigned char tmp_block[MAXBLOCKSIZE], ch;
+ int i, j, rv, blen = (&self->state)->blocklen;
- blen = (&self->state)->blocklen;
- in_data_start = 0;
- has_tmp_block = 0;
- in_data = (unsigned char *)SvPVbyte(data, in_data_len);
- if (in_data_len == 0) {
- RETVAL = newSVpvn("", 0);
+ if (self->direction == 1) {
+ if (self->padlen<0 || self->padlen>=blen) croak("FATAL: invalid padlen");
+ if (self->padding_mode == 1) { /* pkcs5|7 padding */
+ i = blen - self->padlen;
+ if (i == 0) i = blen;
+ for(j=self->padlen; j<blen; j++) self->pad[j] = (unsigned char)i;
+ rv = cbc_encrypt(self->pad, tmp_block, blen, &self->state);
+ if (rv != CRYPT_OK) croak("FATAL: cbc_encrypt failed: %s", error_to_string(rv));
+ }
+ else if (self->padding_mode == 2) { /* oneandzeroes padding */
+ self->pad[self->padlen] = 0x80;
+ for(j=self->padlen+1; j<blen; j++) self->pad[j] = 0;
+ rv = cbc_encrypt(self->pad, tmp_block, blen, &self->state);
+ if (rv != CRYPT_OK) croak("FATAL: cbc_encrypt failed: %s", error_to_string(rv));
+ }
+ else {
+ if (self->padlen>0) croak("FATAL: cbc_encrypt, input data length not multiple of %d", blen);
+ blen = 0;
+ }
}
- else {
-
- if (self->padlen == blen) {
+ else if (self->direction == -1) {
+ if (self->padlen > 0) {
+ if (self->padlen != blen) croak("FATAL: cipher text length has to be multiple of %d (%d)", blen, self->padlen);
rv = cbc_decrypt(self->pad, tmp_block, blen, &self->state);
if (rv != CRYPT_OK) croak("FATAL: cbc_decrypt failed: %s", error_to_string(rv));
- self->padlen = 0;
- has_tmp_block = 1;
- } /* padlen == blen */
- else if (self->padlen > 0) {
- i = (blen - self->padlen); /* remaining bytes in padding buffer */
- if (in_data_len >= i) { /* enough data to fill pad */
- Copy(in_data, self->pad+self->padlen, i, unsigned char);
- self->padlen += i;
- in_data_len -= i;
- in_data_start = i;
- if (in_data_len>0 || self->padding_mode == 0) {
- rv = cbc_decrypt(self->pad, tmp_block, blen, &self->state);
- if (rv != CRYPT_OK) croak("FATAL: cbc_decrypt failed: %s", error_to_string(rv));
- self->padlen = 0;
- has_tmp_block = 1;
- }
- }
- else { /* not enough data to fill pad */
- Copy(in_data, self->pad+self->padlen, in_data_len, unsigned char);
- self->padlen += (int)in_data_len;
- in_data_len = 0;
- }
- } /* padlen > 0 */
-
- /* here: a/ padlen == 1..16 && in_data_len == 0; b/ padlen == 0 && in_data_len > 0 */
- if (in_data_len>0) {
- i = (unsigned long)(in_data_len % blen);
- if (i>0) { /* save tail of data into pad */
- Copy(in_data+in_data_start+in_data_len-i, self->pad, i, unsigned char);
- self->padlen = i;
- in_data_len -= i;
- }
- }
-
- if (in_data_len>0) {
- if (self->padlen == 0 && self->padding_mode !=0) {
- /* in case of padding keep full pad if no more data */
- Copy(in_data+in_data_start+in_data_len-blen, self->pad, blen, unsigned char);
- self->padlen = blen;
- in_data_len -= blen;
+ if (self->padding_mode == 0) { /* no padding */
+ /* we already have blen */
}
- i = (unsigned long)(has_tmp_block ? in_data_len + blen : in_data_len);
- if (i == 0) {
- RETVAL = newSVpvn("", 0);
+ else if (self->padding_mode == 1) { /* pkcs5|7 padding */
+ ch = tmp_block[blen-1];
+ blen = blen - (ch > blen ? blen : ch);
}
- else {
- RETVAL = NEWSV(0, i);
- SvPOK_only(RETVAL);
- SvCUR_set(RETVAL, i);
- out_data = (unsigned char *)SvPVX(RETVAL);
- if (has_tmp_block) {
- Copy(tmp_block, out_data, blen, unsigned char);
- out_data += blen;
- }
- rv = cbc_decrypt(in_data+in_data_start, out_data, (unsigned long)in_data_len, &self->state);
- if (rv != CRYPT_OK) {
- SvREFCNT_dec(RETVAL);
- croak("FATAL: cbc_decrypt failed: %s", error_to_string(rv));
- }
+ else if (self->padding_mode == 2) { /* oneandzeroes padding */
+ while ((unsigned char)tmp_block[blen - 1] == 0x00) blen--;
+ if ((unsigned char)tmp_block[blen - 1] == 0x80) blen--;
+ if (blen < 0) blen = 0;
}
- } /* in_data_len>0 */
- else if (has_tmp_block) {
- RETVAL = newSVpvn((char*)tmp_block, blen);
}
else {
- RETVAL = newSVpvn("", 0);
+ blen = 0;
}
}
-
- }
- OUTPUT:
- RETVAL
-
-SV *
-_finish_dec(Crypt::Mode::CBC self)
- CODE:
- {
- unsigned char tmp_block[MAXBLOCKSIZE];
- unsigned char i;
- int rv, rv_len, blen;
-
- rv_len = 0;
- if (self->padlen > 0) {
- blen = (&self->state)->blocklen;
- if (self->padlen != blen) croak("FATAL: cipher text length has to be multiple of %d (%d)", blen, self->padlen);
- rv = cbc_decrypt(self->pad, tmp_block, blen, &self->state);
- if (rv != CRYPT_OK) croak("FATAL: cbc_decrypt failed: %s", error_to_string(rv));
- if (self->padding_mode == 0) { /* no padding */
- rv_len = blen;
- }
- else if (self->padding_mode == 1) { /* pkcs5|7 padding */
- i = tmp_block[blen-1];
- rv_len = blen - (i>blen ? blen : i);
- }
- else if (self->padding_mode == 2) { /* oneandzeroes padding */
- rv_len = blen;
- while ((unsigned char)tmp_block[rv_len-1] == 0x00) rv_len--;
- if ((unsigned char)tmp_block[rv_len-1] == 0x80) rv_len--;
- if (rv_len<0) rv_len = 0;
- }
+ else {
+ XSRETURN_UNDEF;
}
self->direction = 0;
- RETVAL = newSVpvn((char*)tmp_block, rv_len);
+ RETVAL = newSVpvn((char*)tmp_block, blen);
}
OUTPUT:
RETVAL
diff --git a/inc/CryptX_Mode_CFB.xs.inc b/inc/CryptX_Mode_CFB.xs.inc
index 23f7bb72..283ebf9d 100644
--- a/inc/CryptX_Mode_CFB.xs.inc
+++ b/inc/CryptX_Mode_CFB.xs.inc
@@ -1,16 +1,18 @@
MODULE = CryptX PACKAGE = Crypt::Mode::CFB
+PROTOTYPES: DISABLE
+
### BEWARE - GENERATED FILE, DO NOT EDIT MANUALLY!
Crypt::Mode::CFB
-_new(char * cipher_name, int rounds=0)
+new(Class, char * cipher_name, int rounds=0)
CODE:
{
Newz(0, RETVAL, 1, struct cfb_struct);
if (!RETVAL) croak("FATAL: Newz failed");
RETVAL->direction = 0;
RETVAL->cipher_rounds = rounds;
- RETVAL->cipher_id = find_cipher(cipher_name);
+ RETVAL->cipher_id = _find_cipher(cipher_name);
if (RETVAL->cipher_id == -1) {
Safefree(RETVAL);
croak("FATAL: find_cipfer failed for '%s'", cipher_name);
@@ -24,16 +26,11 @@ DESTROY(Crypt::Mode::CFB self)
CODE:
Safefree(self);
-int
-_get_dir(Crypt::Mode::CFB self)
- CODE:
- RETVAL = self->direction;
- OUTPUT:
- RETVAL
-
void
-_start(Crypt::Mode::CFB self, int dir, SV * key, SV * iv)
- CODE:
+start_decrypt(Crypt::Mode::CFB self, SV * key, SV * iv)
+ ALIAS:
+ start_encrypt = 1
+ PPCODE:
{
STRLEN k_len=0;
unsigned char *k=NULL;
@@ -55,52 +52,51 @@ _start(Crypt::Mode::CFB self, int dir, SV * key, SV * iv)
croak("FATAL: cfb_start failed: %s", error_to_string(rv));
}
- self->direction = dir;
+ self->direction = ix == 1 ? 1 : -1;
+ XPUSHs(ST(0)); /* return self */
}
SV *
-_crypt(Crypt::Mode::CFB self, SV * data)
+add(Crypt::Mode::CFB self, ...)
CODE:
{
- int rv;
- STRLEN in_data_len;
+ int rv, j;
+ STRLEN in_data_len, out_len = 0;
unsigned char *in_data, *out_data;
- in_data = (unsigned char *)SvPVbyte(data, in_data_len);
- if (in_data_len == 0) {
- RETVAL = newSVpvn("", 0);
- }
- else {
- RETVAL = NEWSV(0, in_data_len);
- SvPOK_only(RETVAL);
- SvCUR_set(RETVAL, in_data_len);
- out_data = (unsigned char *)SvPVX(RETVAL);
-
- if (self->direction == 1) {
- rv = cfb_encrypt(in_data, out_data, (unsigned long)in_data_len, &self->state);
- if (rv != CRYPT_OK) {
- SvREFCNT_dec(RETVAL);
- croak("FATAL: cfb_encrypt failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn("", 0);
+ for (j = 1; j < items; j++) {
+ in_data = (unsigned char *)SvPVbyte(ST(j), in_data_len);
+ if (in_data_len > 0) {
+ out_data = (unsigned char*)SvGROW(RETVAL, out_len + in_data_len + 1) + out_len;
+ out_len += in_data_len;
+ if (self->direction == 1) {
+ rv = cfb_encrypt(in_data, out_data, (unsigned long)in_data_len, &self->state);
+ if (rv != CRYPT_OK) {
+ SvREFCNT_dec(RETVAL);
+ croak("FATAL: cfb_encrypt failed: %s", error_to_string(rv));
+ }
}
- }
- else if (self->direction == -1) {
- rv = cfb_decrypt(in_data, out_data, (unsigned long)in_data_len, &self->state);
- if (rv != CRYPT_OK) {
+ else if (self->direction == -1) {
+ rv = cfb_decrypt(in_data, out_data, (unsigned long)in_data_len, &self->state);
+ if (rv != CRYPT_OK) {
+ SvREFCNT_dec(RETVAL);
+ croak("FATAL: cfb_decrypt failed: %s", error_to_string(rv));
+ }
+ }
+ else {
SvREFCNT_dec(RETVAL);
- croak("FATAL: cfb_decrypt failed: %s", error_to_string(rv));
+ croak("FATAL: cfb_crypt failed: call start_encrypt or start_decrypt first");
}
}
- else {
- SvREFCNT_dec(RETVAL);
- croak("FATAL: cfb_crypt failed: call start_encrypt or start_decrypt first");
- }
}
+ if (out_len > 0) SvCUR_set(RETVAL, out_len);
}
OUTPUT:
RETVAL
SV *
-_finish(Crypt::Mode::CFB self)
+finish(Crypt::Mode::CFB self)
CODE:
self->direction = 0;
RETVAL = newSVpvn("", 0);
diff --git a/inc/CryptX_Mode_CTR.xs.inc b/inc/CryptX_Mode_CTR.xs.inc
index 877186b2..baeb661a 100644
--- a/inc/CryptX_Mode_CTR.xs.inc
+++ b/inc/CryptX_Mode_CTR.xs.inc
@@ -1,16 +1,18 @@
MODULE = CryptX PACKAGE = Crypt::Mode::CTR
+PROTOTYPES: DISABLE
+
### BEWARE - GENERATED FILE, DO NOT EDIT MANUALLY!
Crypt::Mode::CTR
-_new(char * cipher_name, int ctr_mode=0, int ctr_width=0, int rounds=0)
+new(Class, char * cipher_name, int ctr_mode=0, int ctr_width=0, int rounds=0)
CODE:
{
Newz(0, RETVAL, 1, struct ctr_struct);
if (!RETVAL) croak("FATAL: Newz failed");
RETVAL->direction = 0;
RETVAL->cipher_rounds = rounds;
- RETVAL->cipher_id = find_cipher(cipher_name);
+ RETVAL->cipher_id = _find_cipher(cipher_name);
if (RETVAL->cipher_id == -1) {
Safefree(RETVAL);
croak("FATAL: find_cipfer failed for '%s'", cipher_name);
@@ -29,16 +31,11 @@ DESTROY(Crypt::Mode::CTR self)
CODE:
Safefree(self);
-int
-_get_dir(Crypt::Mode::CTR self)
- CODE:
- RETVAL = self->direction;
- OUTPUT:
- RETVAL
-
void
-_start(Crypt::Mode::CTR self, int dir, SV * key, SV * iv)
- CODE:
+start_decrypt(Crypt::Mode::CTR self, SV * key, SV * iv)
+ ALIAS:
+ start_encrypt = 1
+ PPCODE:
{
STRLEN k_len=0;
unsigned char *k=NULL;
@@ -60,52 +57,51 @@ _start(Crypt::Mode::CTR self, int dir, SV * key, SV * iv)
croak("FATAL: ctr_start failed: %s", error_to_string(rv));
}
- self->direction = dir;
+ self->direction = ix == 1 ? 1 : -1;
+ XPUSHs(ST(0)); /* return self */
}
SV *
-_crypt(Crypt::Mode::CTR self, SV * data)
+add(Crypt::Mode::CTR self, ...)
CODE:
{
- int rv;
- STRLEN in_data_len;
+ int rv, j;
+ STRLEN in_data_len, out_len = 0;
unsigned char *in_data, *out_data;
- in_data = (unsigned char *)SvPVbyte(data, in_data_len);
- if (in_data_len == 0) {
- RETVAL = newSVpvn("", 0);
- }
- else {
- RETVAL = NEWSV(0, in_data_len);
- SvPOK_only(RETVAL);
- SvCUR_set(RETVAL, in_data_len);
- out_data = (unsigned char *)SvPVX(RETVAL);
-
- if (self->direction == 1) {
- rv = ctr_encrypt(in_data, out_data, (unsigned long)in_data_len, &self->state);
- if (rv != CRYPT_OK) {
- SvREFCNT_dec(RETVAL);
- croak("FATAL: ctr_encrypt failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn("", 0);
+ for (j = 1; j < items; j++) {
+ in_data = (unsigned char *)SvPVbyte(ST(j), in_data_len);
+ if (in_data_len > 0) {
+ out_data = (unsigned char*)SvGROW(RETVAL, out_len + in_data_len + 1) + out_len;
+ out_len += in_data_len;
+ if (self->direction == 1) {
+ rv = ctr_encrypt(in_data, out_data, (unsigned long)in_data_len, &self->state);
+ if (rv != CRYPT_OK) {
+ SvREFCNT_dec(RETVAL);
+ croak("FATAL: ctr_encrypt failed: %s", error_to_string(rv));
+ }
}
- }
- else if (self->direction == -1) {
- rv = ctr_decrypt(in_data, out_data, (unsigned long)in_data_len, &self->state);
- if (rv != CRYPT_OK) {
+ else if (self->direction == -1) {
+ rv = ctr_decrypt(in_data, out_data, (unsigned long)in_data_len, &self->state);
+ if (rv != CRYPT_OK) {
+ SvREFCNT_dec(RETVAL);
+ croak("FATAL: ctr_decrypt failed: %s", error_to_string(rv));
+ }
+ }
+ else {
SvREFCNT_dec(RETVAL);
- croak("FATAL: ctr_decrypt failed: %s", error_to_string(rv));
+ croak("FATAL: ctr_crypt failed: call start_encrypt or start_decrypt first");
}
}
- else {
- SvREFCNT_dec(RETVAL);
- croak("FATAL: ctr_crypt failed: call start_encrypt or start_decrypt first");
- }
}
+ if (out_len > 0) SvCUR_set(RETVAL, out_len);
}
OUTPUT:
RETVAL
SV *
-_finish(Crypt::Mode::CTR self)
+finish(Crypt::Mode::CTR self)
CODE:
self->direction = 0;
RETVAL = newSVpvn("", 0);
diff --git a/inc/CryptX_Mode_ECB.xs.inc b/inc/CryptX_Mode_ECB.xs.inc
index 1b2c4f2e..8d34adbe 100644
--- a/inc/CryptX_Mode_ECB.xs.inc
+++ b/inc/CryptX_Mode_ECB.xs.inc
@@ -1,9 +1,11 @@
MODULE = CryptX PACKAGE = Crypt::Mode::ECB
+PROTOTYPES: DISABLE
+
### BEWARE - GENERATED FILE, DO NOT EDIT MANUALLY!
Crypt::Mode::ECB
-_new(char * cipher_name, int padding=1, int rounds=0)
+new(Class, char * cipher_name, int padding=1, int rounds=0)
CODE:
{
Newz(0, RETVAL, 1, struct ecb_struct);
@@ -12,7 +14,7 @@ _new(char * cipher_name, int padding=1, int rounds=0)
RETVAL->padlen = 0;
RETVAL->direction = 0;
RETVAL->cipher_rounds = rounds;
- RETVAL->cipher_id = find_cipher(cipher_name);
+ RETVAL->cipher_id = _find_cipher(cipher_name);
if (RETVAL->cipher_id == -1) {
Safefree(RETVAL);
croak("FATAL: find_cipfer failed for '%s'", cipher_name);
@@ -26,16 +28,11 @@ DESTROY(Crypt::Mode::ECB self)
CODE:
Safefree(self);
-int
-_get_dir(Crypt::Mode::ECB self)
- CODE:
- RETVAL = self->direction;
- OUTPUT:
- RETVAL
-
void
-_start(Crypt::Mode::ECB self, int dir, SV * key)
- CODE:
+start_decrypt(Crypt::Mode::ECB self, SV * key)
+ ALIAS:
+ start_encrypt = 1
+ PPCODE:
{
int rv;
STRLEN k_len=0;
@@ -49,243 +46,215 @@ _start(Crypt::Mode::ECB self, int dir, SV * key)
croak("FATAL: ecb_start failed: %s", error_to_string(rv));
}
- self->direction = dir;
+ self->direction = ix == 1 ? 1 : -1;
self->padlen = 0;
+ XPUSHs(ST(0)); /* return self */
}
SV *
-_encrypt(Crypt::Mode::ECB self, SV * data)
+add(Crypt::Mode::ECB self, ...)
CODE:
{
- int rv, has_tmp_block, blen;
+ int rv, has_tmp_block, blen, j;
unsigned long i;
-
- STRLEN in_data_len, in_data_start;
+ STRLEN in_data_len, in_data_start, out_len = 0;
unsigned char *in_data, *out_data, tmp_block[MAXBLOCKSIZE];
- if (self->direction != 1) croak("FATAL: encrypt error, call start_encrypt first (%d)", self->direction);
+ RETVAL = newSVpvn("", 0);
+ for (j = 1; j < items; j++) {
+ in_data = (unsigned char *)SvPVbyte(ST(j), in_data_len);
+ blen = (&self->state)->blocklen;
+ in_data_start = 0;
+ has_tmp_block = 0;
+ if (in_data_len > 0) {
+ if (self->direction == 1) {
+ /* handle non-empty self->pad buffer */
+ if (self->padlen > 0) {
+ i = (blen - self->padlen);
+ if (in_data_len >= i) { /* enough data to fill pad */
+ Copy(in_data, self->pad+self->padlen, i, unsigned char);
+ in_data_len -= i;
+ in_data_start = i;
+ rv = ecb_encrypt(self->pad, tmp_block, blen, &self->state);
+ if (rv != CRYPT_OK) {
+ SvREFCNT_dec(RETVAL);
+ croak("FATAL: ecb_encrypt failed: %s", error_to_string(rv));
+ }
+ self->padlen = 0;
+ has_tmp_block = 1;
+ }
+ else { /* not enough data to fill pad */
+ Copy(in_data, self->pad+self->padlen, in_data_len, unsigned char);
+ self->padlen += (int)in_data_len;
+ in_data_len = 0;
+ }
+ }
- blen = (&self->state)->blocklen;
- in_data_start = 0;
- has_tmp_block = 0;
- in_data = (unsigned char *)SvPVbyte(data, in_data_len);
- if (in_data_len == 0) {
- RETVAL = newSVpvn("", 0);
- }
- else {
- if (self->padlen > 0) {
- i = (blen - self->padlen);
- if (in_data_len >= i) { /* enough data to fill pad */
- Copy(in_data, self->pad+self->padlen, i, unsigned char);
- in_data_len -= i;
- in_data_start = i;
- rv = ecb_encrypt(self->pad, tmp_block, blen, &self->state);
- if (rv != CRYPT_OK) croak("FATAL: ecb_encrypt failed: %s", error_to_string(rv));
- self->padlen = 0;
- has_tmp_block = 1;
- }
- else { /* not enough data to fill pad */
- Copy(in_data, self->pad+self->padlen, in_data_len, unsigned char);
- self->padlen += (int)in_data_len;
- in_data_len = 0;
+ i = (unsigned long)(in_data_len % blen);
+ if (in_data_len > 0 && i > 0) { /* save tail of data into pad */
+ Copy(in_data + in_data_start + in_data_len - i, self->pad, i, unsigned char);
+ self->padlen = i;
+ in_data_len -= i;
+ }
+
+ if (in_data_len > 0) {
+ i = (unsigned long)(has_tmp_block ? in_data_len + blen : in_data_len);
+ out_data = (unsigned char*)SvGROW(RETVAL, out_len + i + 1) + out_len;
+ out_len += i;
+ if (has_tmp_block) {
+ Copy(tmp_block, out_data, blen, unsigned char);
+ out_data += blen;
+ }
+ rv = ecb_encrypt(in_data+in_data_start, out_data, (unsigned long)in_data_len, &self->state);
+ if (rv != CRYPT_OK) {
+ SvREFCNT_dec(RETVAL);
+ croak("FATAL: ecb_encrypt failed: %s", error_to_string(rv));
+ }
+ } /* in_data_len > 0 */
+ else if (has_tmp_block) {
+ out_data = (unsigned char*)SvGROW(RETVAL, out_len + blen + 1) + out_len;
+ out_len += blen;
+ Copy(tmp_block, out_data, blen, unsigned char);
+ }
}
- } /* padlen > 0 */
+ else if (self->direction == -1) {
+ if (self->padlen == blen) {
+ rv = ecb_decrypt(self->pad, tmp_block, blen, &self->state);
+ if (rv != CRYPT_OK) {
+ SvREFCNT_dec(RETVAL);
+ croak("FATAL: ecb_decrypt failed: %s", error_to_string(rv));
+ }
+ self->padlen = 0;
+ has_tmp_block = 1;
+ } /* padlen == blen */
+ else if (self->padlen > 0) {
+ i = (blen - self->padlen); /* remaining bytes in padding buffer */
+ if (in_data_len >= i) { /* enough data to fill pad */
+ Copy(in_data, self->pad+self->padlen, i, unsigned char);
+ self->padlen += i;
+ in_data_len -= i;
+ in_data_start = i;
+ if (in_data_len>0 || self->padding_mode == 0) {
+ rv = ecb_decrypt(self->pad, tmp_block, blen, &self->state);
+ if (rv != CRYPT_OK) {
+ SvREFCNT_dec(RETVAL);
+ croak("FATAL: ecb_decrypt failed: %s", error_to_string(rv));
+ }
+ self->padlen = 0;
+ has_tmp_block = 1;
+ }
+ }
+ else { /* not enough data to fill pad */
+ Copy(in_data, self->pad+self->padlen, in_data_len, unsigned char);
+ self->padlen += (int)in_data_len;
+ in_data_len = 0;
+ }
+ } /* padlen > 0 */
- i = (unsigned long)(in_data_len % blen);
- if (in_data_len>0 && i>0) { /* save tail of data into pad */
- Copy(in_data+in_data_start+in_data_len-i, self->pad, i, unsigned char);
- self->padlen = i;
- in_data_len -= i;
- }
+ /* here: a/ padlen == 1..16 && in_data_len == 0; b/ padlen == 0 && in_data_len > 0 */
+ if (in_data_len>0) {
+ i = (unsigned long)(in_data_len % blen);
+ if (i>0) { /* save tail of data into pad */
+ Copy(in_data+in_data_start+in_data_len-i, self->pad, i, unsigned char);
+ self->padlen = i;
+ in_data_len -= i;
+ }
+ }
- if (in_data_len > 0) {
- i = (unsigned long)(has_tmp_block ? in_data_len + blen : in_data_len);
- RETVAL = NEWSV(0, i);
- SvPOK_only(RETVAL);
- SvCUR_set(RETVAL, i);
- out_data = (unsigned char *)SvPVX(RETVAL);
- if (has_tmp_block) {
- Copy(tmp_block, out_data, blen, unsigned char);
- out_data += blen;
+ if (in_data_len>0) {
+ if (self->padlen == 0 && self->padding_mode !=0) {
+ /* in case of padding keep full pad if no more data */
+ Copy(in_data+in_data_start+in_data_len-blen, self->pad, blen, unsigned char);
+ self->padlen = blen;
+ in_data_len -= blen;
+ }
+ i = (unsigned long)(has_tmp_block ? in_data_len + blen : in_data_len);
+ if (i > 0) {
+ out_data = (unsigned char*)SvGROW(RETVAL, out_len + i + 1) + out_len;
+ out_len += i;
+ if (has_tmp_block) {
+ Copy(tmp_block, out_data, blen, unsigned char);
+ out_data += blen;
+ }
+ rv = ecb_decrypt(in_data+in_data_start, out_data, (unsigned long)in_data_len, &self->state);
+ if (rv != CRYPT_OK) {
+ SvREFCNT_dec(RETVAL);
+ croak("FATAL: ecb_decrypt failed: %s", error_to_string(rv));
+ }
+ }
+ } /* in_data_len>0 */
+ else if (has_tmp_block) {
+ out_data = (unsigned char*)SvGROW(RETVAL, out_len + blen + 1) + out_len;
+ out_len += blen;
+ Copy(tmp_block, out_data, blen, unsigned char);
+ }
}
- rv = ecb_encrypt(in_data+in_data_start, out_data, (unsigned long)in_data_len, &self->state);
- if (rv != CRYPT_OK) {
+ else {
SvREFCNT_dec(RETVAL);
- croak("FATAL: ecb_encrypt failed: %s", error_to_string(rv));
+ croak("FATAL: call start_decryt or start_encrpyt first (%d)", self->direction);
}
- } /* in_data_len>0 */
- else if (has_tmp_block) {
- RETVAL = newSVpvn((char*)tmp_block, blen);
}
- else {
- RETVAL = newSVpvn("", 0);
- }
- }
- }
- OUTPUT:
- RETVAL
-
-SV *
-_finish_enc(Crypt::Mode::ECB self)
- CODE:
- {
- unsigned char tmp_block[MAXBLOCKSIZE];
- int rv, blen, i, j;
-
- blen = (&self->state)->blocklen;
- if (self->padlen<0 || self->padlen>=blen) croak("FATAL: invalid padlen");
-
- if (self->padding_mode == 1) { /* pkcs5|7 padding */
- i = blen - self->padlen;
- if (i == 0) i = blen;
- for(j=self->padlen; j<blen; j++) self->pad[j] = (unsigned char)i;
- rv = ecb_encrypt(self->pad, tmp_block, blen, &self->state);
- if (rv != CRYPT_OK) croak("FATAL: ecb_encrypt failed: %s", error_to_string(rv));
- }
- else if (self->padding_mode == 2) { /* oneandzeroes padding */
- self->pad[self->padlen] = 0x80;
- for(j=self->padlen+1; j<blen; j++) self->pad[j] = 0;
- rv = ecb_encrypt(self->pad, tmp_block, blen, &self->state);
- if (rv != CRYPT_OK) croak("FATAL: ecb_encrypt failed: %s", error_to_string(rv));
- }
- else {
- if (self->padlen>0) croak("FATAL: ecb_encrypt, input data length not multiple of %d", blen);
- blen = 0;
}
-
- self->direction = 0;
- RETVAL = newSVpvn((char*)tmp_block, blen);
+ if (out_len > 0) SvCUR_set(RETVAL, out_len);
}
OUTPUT:
RETVAL
SV *
-_decrypt(Crypt::Mode::ECB self, SV * data)
+finish(Crypt::Mode::ECB self)
CODE:
{
- int rv, has_tmp_block, blen;
- unsigned long i;
- STRLEN in_data_len, in_data_start;
- unsigned char *in_data, *out_data, tmp_block[MAXBLOCKSIZE];
-
- if (self->direction != -1) croak("FATAL: decrypt error, call start_decryt first (%d)", self->direction);
+ unsigned char tmp_block[MAXBLOCKSIZE], ch;
+ int i, j, rv, blen = (&self->state)->blocklen;
- blen = (&self->state)->blocklen;
- in_data_start = 0;
- has_tmp_block = 0;
- in_data = (unsigned char *)SvPVbyte(data, in_data_len);
- if (in_data_len == 0) {
- RETVAL = newSVpvn("", 0);
+ if (self->direction == 1) {
+ if (self->padlen<0 || self->padlen>=blen) croak("FATAL: invalid padlen");
+ if (self->padding_mode == 1) { /* pkcs5|7 padding */
+ i = blen - self->padlen;
+ if (i == 0) i = blen;
+ for(j=self->padlen; j<blen; j++) self->pad[j] = (unsigned char)i;
+ rv = ecb_encrypt(self->pad, tmp_block, blen, &self->state);
+ if (rv != CRYPT_OK) croak("FATAL: ecb_encrypt failed: %s", error_to_string(rv));
+ }
+ else if (self->padding_mode == 2) { /* oneandzeroes padding */
+ self->pad[self->padlen] = 0x80;
+ for(j=self->padlen+1; j<blen; j++) self->pad[j] = 0;
+ rv = ecb_encrypt(self->pad, tmp_block, blen, &self->state);
+ if (rv != CRYPT_OK) croak("FATAL: ecb_encrypt failed: %s", error_to_string(rv));
+ }
+ else {
+ if (self->padlen>0) croak("FATAL: ecb_encrypt, input data length not multiple of %d", blen);
+ blen = 0;
+ }
}
- else {
-
- if (self->padlen == blen) {
+ else if (self->direction == -1) {
+ if (self->padlen > 0) {
+ if (self->padlen != blen) croak("FATAL: cipher text length has to be multiple of %d (%d)", blen, self->padlen);
rv = ecb_decrypt(self->pad, tmp_block, blen, &self->state);
if (rv != CRYPT_OK) croak("FATAL: ecb_decrypt failed: %s", error_to_string(rv));
- self->padlen = 0;
- has_tmp_block = 1;
- } /* padlen == blen */
- else if (self->padlen > 0) {
- i = (blen - self->padlen); /* remaining bytes in padding buffer */
- if (in_data_len >= i) { /* enough data to fill pad */
- Copy(in_data, self->pad+self->padlen, i, unsigned char);
- self->padlen += i;
- in_data_len -= i;
- in_data_start = i;
- if (in_data_len>0 || self->padding_mode == 0) {
- rv = ecb_decrypt(self->pad, tmp_block, blen, &self->state);
- if (rv != CRYPT_OK) croak("FATAL: ecb_decrypt failed: %s", error_to_string(rv));
- self->padlen = 0;
- has_tmp_block = 1;
- }
- }
- else { /* not enough data to fill pad */
- Copy(in_data, self->pad+self->padlen, in_data_len, unsigned char);
- self->padlen += (int)in_data_len;
- in_data_len = 0;
- }
- } /* padlen > 0 */
-
- /* here: a/ padlen == 1..16 && in_data_len == 0; b/ padlen == 0 && in_data_len > 0 */
- if (in_data_len>0) {
- i = (unsigned long)(in_data_len % blen);
- if (i>0) { /* save tail of data into pad */
- Copy(in_data+in_data_start+in_data_len-i, self->pad, i, unsigned char);
- self->padlen = i;
- in_data_len -= i;
- }
- }
-
- if (in_data_len>0) {
- if (self->padlen == 0 && self->padding_mode !=0) {
- /* in case of padding keep full pad if no more data */
- Copy(in_data+in_data_start+in_data_len-blen, self->pad, blen, unsigned char);
- self->padlen = blen;
- in_data_len -= blen;
+ if (self->padding_mode == 0) { /* no padding */
+ /* we already have blen */
}
- i = (unsigned long)(has_tmp_block ? in_data_len + blen : in_data_len);
- if (i == 0) {
- RETVAL = newSVpvn("", 0);
+ else if (self->padding_mode == 1) { /* pkcs5|7 padding */
+ ch = tmp_block[blen-1];
+ blen = blen - (ch > blen ? blen : ch);
}
- else {
- RETVAL = NEWSV(0, i);
- SvPOK_only(RETVAL);
- SvCUR_set(RETVAL, i);
- out_data = (unsigned char *)SvPVX(RETVAL);
- if (has_tmp_block) {
- Copy(tmp_block, out_data, blen, unsigned char);
- out_data += blen;
- }
- rv = ecb_decrypt(in_data+in_data_start, out_data, (unsigned long)in_data_len, &self->state);
- if (rv != CRYPT_OK) {
- SvREFCNT_dec(RETVAL);
- croak("FATAL: ecb_decrypt failed: %s", error_to_string(rv));
- }
+ else if (self->padding_mode == 2) { /* oneandzeroes padding */
+ while ((unsigned char)tmp_block[blen - 1] == 0x00) blen--;
+ if ((unsigned char)tmp_block[blen - 1] == 0x80) blen--;
+ if (blen < 0) blen = 0;
}
- } /* in_data_len>0 */
- else if (has_tmp_block) {
- RETVAL = newSVpvn((char*)tmp_block, blen);
}
else {
- RETVAL = newSVpvn("", 0);
+ blen = 0;
}
}
-
- }
- OUTPUT:
- RETVAL
-
-SV *
-_finish_dec(Crypt::Mode::ECB self)
- CODE:
- {
- unsigned char tmp_block[MAXBLOCKSIZE];
- unsigned char i;
- int rv, rv_len, blen;
-
- rv_len = 0;
- if (self->padlen > 0) {
- blen = (&self->state)->blocklen;
- if (self->padlen != blen) croak("FATAL: cipher text length has to be multiple of %d (%d)", blen, self->padlen);
- rv = ecb_decrypt(self->pad, tmp_block, blen, &self->state);
- if (rv != CRYPT_OK) croak("FATAL: ecb_decrypt failed: %s", error_to_string(rv));
- if (self->padding_mode == 0) { /* no padding */
- rv_len = blen;
- }
- else if (self->padding_mode == 1) { /* pkcs5|7 padding */
- i = tmp_block[blen-1];
- rv_len = blen - (i>blen ? blen : i);
- }
- else if (self->padding_mode == 2) { /* oneandzeroes padding */
- rv_len = blen;
- while ((unsigned char)tmp_block[rv_len-1] == 0x00) rv_len--;
- if ((unsigned char)tmp_block[rv_len-1] == 0x80) rv_len--;
- if (rv_len<0) rv_len = 0;
- }
+ else {
+ XSRETURN_UNDEF;
}
self->direction = 0;
- RETVAL = newSVpvn((char*)tmp_block, rv_len);
+ RETVAL = newSVpvn((char*)tmp_block, blen);
}
OUTPUT:
RETVAL
diff --git a/inc/CryptX_Mode_OFB.xs.inc b/inc/CryptX_Mode_OFB.xs.inc
index 1acd3a94..1a3447b3 100644
--- a/inc/CryptX_Mode_OFB.xs.inc
+++ b/inc/CryptX_Mode_OFB.xs.inc
@@ -1,16 +1,18 @@
MODULE = CryptX PACKAGE = Crypt::Mode::OFB
+PROTOTYPES: DISABLE
+
### BEWARE - GENERATED FILE, DO NOT EDIT MANUALLY!
Crypt::Mode::OFB
-_new(char * cipher_name, int rounds=0)
+new(Class, char * cipher_name, int rounds=0)
CODE:
{
Newz(0, RETVAL, 1, struct ofb_struct);
if (!RETVAL) croak("FATAL: Newz failed");
RETVAL->direction = 0;
RETVAL->cipher_rounds = rounds;
- RETVAL->cipher_id = find_cipher(cipher_name);
+ RETVAL->cipher_id = _find_cipher(cipher_name);
if (RETVAL->cipher_id == -1) {
Safefree(RETVAL);
croak("FATAL: find_cipfer failed for '%s'", cipher_name);
@@ -24,16 +26,11 @@ DESTROY(Crypt::Mode::OFB self)
CODE:
Safefree(self);
-int
-_get_dir(Crypt::Mode::OFB self)
- CODE:
- RETVAL = self->direction;
- OUTPUT:
- RETVAL
-
void
-_start(Crypt::Mode::OFB self, int dir, SV * key, SV * iv)
- CODE:
+start_decrypt(Crypt::Mode::OFB self, SV * key, SV * iv)
+ ALIAS:
+ start_encrypt = 1
+ PPCODE:
{
STRLEN k_len=0;
unsigned char *k=NULL;
@@ -55,52 +52,51 @@ _start(Crypt::Mode::OFB self, int dir, SV * key, SV * iv)
croak("FATAL: ofb_start failed: %s", error_to_string(rv));
}
- self->direction = dir;
+ self->direction = ix == 1 ? 1 : -1;
+ XPUSHs(ST(0)); /* return self */
}
SV *
-_crypt(Crypt::Mode::OFB self, SV * data)
+add(Crypt::Mode::OFB self, ...)
CODE:
{
- int rv;
- STRLEN in_data_len;
+ int rv, j;
+ STRLEN in_data_len, out_len = 0;
unsigned char *in_data, *out_data;
- in_data = (unsigned char *)SvPVbyte(data, in_data_len);
- if (in_data_len == 0) {
- RETVAL = newSVpvn("", 0);
- }
- else {
- RETVAL = NEWSV(0, in_data_len);
- SvPOK_only(RETVAL);
- SvCUR_set(RETVAL, in_data_len);
- out_data = (unsigned char *)SvPVX(RETVAL);
-
- if (self->direction == 1) {
- rv = ofb_encrypt(in_data, out_data, (unsigned long)in_data_len, &self->state);
- if (rv != CRYPT_OK) {
- SvREFCNT_dec(RETVAL);
- croak("FATAL: ofb_encrypt failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn("", 0);
+ for (j = 1; j < items; j++) {
+ in_data = (unsigned char *)SvPVbyte(ST(j), in_data_len);
+ if (in_data_len > 0) {
+ out_data = (unsigned char*)SvGROW(RETVAL, out_len + in_data_len + 1) + out_len;
+ out_len += in_data_len;
+ if (self->direction == 1) {
+ rv = ofb_encrypt(in_data, out_data, (unsigned long)in_data_len, &self->state);
+ if (rv != CRYPT_OK) {
+ SvREFCNT_dec(RETVAL);
+ croak("FATAL: ofb_encrypt failed: %s", error_to_string(rv));
+ }
}
- }
- else if (self->direction == -1) {
- rv = ofb_decrypt(in_data, out_data, (unsigned long)in_data_len, &self->state);
- if (rv != CRYPT_OK) {
+ else if (self->direction == -1) {
+ rv = ofb_decrypt(in_data, out_data, (unsigned long)in_data_len, &self->state);
+ if (rv != CRYPT_OK) {
+ SvREFCNT_dec(RETVAL);
+ croak("FATAL: ofb_decrypt failed: %s", error_to_string(rv));
+ }
+ }
+ else {
SvREFCNT_dec(RETVAL);
- croak("FATAL: ofb_decrypt failed: %s", error_to_string(rv));
+ croak("FATAL: ofb_crypt failed: call start_encrypt or start_decrypt first");
}
}
- else {
- SvREFCNT_dec(RETVAL);
- croak("FATAL: ofb_crypt failed: call start_encrypt or start_decrypt first");
- }
}
+ if (out_len > 0) SvCUR_set(RETVAL, out_len);
}
OUTPUT:
RETVAL
SV *
-_finish(Crypt::Mode::OFB self)
+finish(Crypt::Mode::OFB self)
CODE:
self->direction = 0;
RETVAL = newSVpvn("", 0);
diff --git a/inc/CryptX_PK_DH.xs.inc b/inc/CryptX_PK_DH.xs.inc
index 0898e805..4040800f 100644
--- a/inc/CryptX_PK_DH.xs.inc
+++ b/inc/CryptX_PK_DH.xs.inc
@@ -1,7 +1,9 @@
MODULE = CryptX PACKAGE = Crypt::PK::DH
+PROTOTYPES: DISABLE
+
Crypt::PK::DH
-_new()
+_new(Class)
CODE:
{
int rv;
@@ -208,7 +210,7 @@ key2hash(Crypt::PK::DH self)
not_used = hv_store(rv_hash, "size", 4, newSViv(dh_get_groupsize(&self->key)), 0);
/* type */
not_used = hv_store(rv_hash, "type", 4, newSViv(self->key.type), 0);
- if (not_used) not_used = NULL; /* just silence the warning: variable 'not_used' set but not used */
+ LTC_UNUSED_PARAM(not_used);
RETVAL = newRV_noinc((SV*)rv_hash);
OUTPUT:
RETVAL
diff --git a/inc/CryptX_PK_DSA.xs.inc b/inc/CryptX_PK_DSA.xs.inc
index aebb53a3..d1673f4e 100644
--- a/inc/CryptX_PK_DSA.xs.inc
+++ b/inc/CryptX_PK_DSA.xs.inc
@@ -1,7 +1,9 @@
MODULE = CryptX PACKAGE = Crypt::PK::DSA
+PROTOTYPES: DISABLE
+
Crypt::PK::DSA
-_new()
+_new(Class)
CODE:
{
int rv;
@@ -229,7 +231,7 @@ key2hash(Crypt::PK::DSA self)
not_used = hv_store(rv_hash, "size", 4, newSViv(qsize), 0);
/* type */
not_used = hv_store(rv_hash, "type", 4, newSViv(self->key.type), 0);
- if (not_used) not_used = NULL; /* just silence the warning: variable 'not_used' set but not used */
+ LTC_UNUSED_PARAM(not_used);
RETVAL = newRV_noinc((SV*)rv_hash);
OUTPUT:
RETVAL
@@ -261,7 +263,7 @@ export_key_der(Crypt::PK::DSA self, char * type)
RETVAL
SV *
-_encrypt(Crypt::PK::DSA self, SV * data, char * hash_name)
+encrypt(Crypt::PK::DSA self, SV * data, const char * hash_name = "SHA1")
CODE:
{
int rv, hash_id;
@@ -272,7 +274,7 @@ _encrypt(Crypt::PK::DSA self, SV * data, char * hash_name)
data_ptr = (unsigned char *)SvPVbyte(data, data_len);
- hash_id = find_hash(hash_name);
+ hash_id = _find_hash(hash_name);
if (hash_id == -1) croak("FATAL: find_hash failed for '%s'", hash_name);
rv = dsa_encrypt_key(data_ptr, (unsigned long)data_len, buffer, &buffer_len,
&self->pstate, self->pindex,
@@ -284,7 +286,7 @@ _encrypt(Crypt::PK::DSA self, SV * data, char * hash_name)
RETVAL
SV *
-_decrypt(Crypt::PK::DSA self, SV * data)
+decrypt(Crypt::PK::DSA self, SV * data)
CODE:
{
int rv;
@@ -303,17 +305,25 @@ _decrypt(Crypt::PK::DSA self, SV * data)
RETVAL
SV *
-_sign(Crypt::PK::DSA self, SV * data)
+sign_hash(Crypt::PK::DSA self, SV * data, const char * hash_name = "SHA1")
+ ALIAS:
+ sign_message = 1
CODE:
{
- int rv;
- unsigned char *data_ptr=NULL;
- STRLEN data_len=0;
- unsigned char buffer[1024];
- unsigned long buffer_len = 1024;
+ int rv, id;
+ unsigned char buffer[1024], tmp[MAXBLOCKSIZE], *data_ptr = NULL;
+ unsigned long tmp_len = MAXBLOCKSIZE, buffer_len = 1024;
+ STRLEN data_len = 0;
data_ptr = (unsigned char *)SvPVbyte(data, data_len);
-
+ if (ix == 1) {
+ id = _find_hash(hash_name);
+ if (id == -1) croak("FATAL: find_hash failed for '%s'", hash_name);
+ rv = hash_memory(id, data_ptr, (unsigned long)data_len, tmp, &tmp_len);
+ if (rv != CRYPT_OK) croak("FATAL: hash_memory failed: %s", error_to_string(rv));
+ data_ptr = tmp;
+ data_len = tmp_len;
+ }
rv = dsa_sign_hash(data_ptr, (unsigned long)data_len, buffer, &buffer_len,
&self->pstate, self->pindex,
&self->key);
@@ -324,18 +334,26 @@ _sign(Crypt::PK::DSA self, SV * data)
RETVAL
int
-_verify(Crypt::PK::DSA self, SV * sig, SV * data)
+verify_hash(Crypt::PK::DSA self, SV * sig, SV * data, const char * hash_name = "SHA1")
+ ALIAS:
+ verify_message = 1
CODE:
{
- int rv, stat;
- unsigned char *data_ptr=NULL;
- STRLEN data_len=0;
- unsigned char *sig_ptr=NULL;
- STRLEN sig_len=0;
+ int rv, stat, id;
+ unsigned char tmp[MAXBLOCKSIZE], *data_ptr = NULL, *sig_ptr = NULL;
+ unsigned long tmp_len = MAXBLOCKSIZE;
+ STRLEN data_len = 0, sig_len = 0;
data_ptr = (unsigned char *)SvPVbyte(data, data_len);
sig_ptr = (unsigned char *)SvPVbyte(sig, sig_len);
-
+ if (ix == 1) {
+ id = _find_hash(hash_name);
+ if (id == -1) croak("FATAL: find_hash failed for '%s'", hash_name);
+ rv = hash_memory(id, data_ptr, (unsigned long)data_len, tmp, &tmp_len);
+ if (rv != CRYPT_OK) croak("FATAL: hash_memory failed: %s", error_to_string(rv));
+ data_ptr = tmp;
+ data_len = tmp_len;
+ }
RETVAL = 1;
stat = 0;
rv = dsa_verify_hash(sig_ptr, (unsigned long)sig_len, data_ptr, (unsigned long)data_len, &stat, &self->key);
diff --git a/inc/CryptX_PK_ECC.xs.inc b/inc/CryptX_PK_ECC.xs.inc
index 239376f2..751b7d83 100644
--- a/inc/CryptX_PK_ECC.xs.inc
+++ b/inc/CryptX_PK_ECC.xs.inc
@@ -1,7 +1,9 @@
MODULE = CryptX PACKAGE = Crypt::PK::ECC
+PROTOTYPES: DISABLE
+
Crypt::PK::ECC
-_new()
+_new(Class)
CODE:
{
int rv;
@@ -9,7 +11,6 @@ _new()
if (!RETVAL) croak("FATAL: Newz failed");
RETVAL->pindex = find_prng("chacha20");
RETVAL->key.type = -1;
- ecc_dp_init(&RETVAL->dp);
if (RETVAL->pindex == -1) {
Safefree(RETVAL);
croak("FATAL: find_prng('chacha20') failed");
@@ -29,10 +30,11 @@ generate_key(Crypt::PK::ECC self, SV *curve)
{
int rv;
/* setup dp structure */
- _ecc_set_dp_from_SV(&self->dp, curve); /* croaks on error */
+ rv = _ecc_set_dp_from_SV(&self->key, curve); /* croaks on error */
+ if (rv != CRYPT_OK) croak("FATAL: ecc_set_dp failed: %s", error_to_string(rv));
/* gen the key */
- rv = ecc_make_key_ex(&self->pstate, self->pindex, &self->key, &self->dp);
- if (rv != CRYPT_OK) croak("FATAL: ecc_make_key_ex failed: %s", error_to_string(rv));
+ rv = ecc_generate_key(&self->pstate, self->pindex, &self->key);
+ if (rv != CRYPT_OK) croak("FATAL: ecc_generate_key failed: %s", error_to_string(rv));
XPUSHs(ST(0)); /* return self */
}
@@ -45,9 +47,9 @@ _import(Crypt::PK::ECC self, SV * key_data)
STRLEN data_len=0;
data = (unsigned char *)SvPVbyte(key_data, data_len);
- _ecc_free_key(&self->key, &self->dp);
- rv = ecc_import_full(data, (unsigned long)data_len, &self->key, &self->dp);
- if (rv != CRYPT_OK) croak("FATAL: ecc_import_full failed: %s", error_to_string(rv));
+ if (self->key.type != -1) { ecc_free(&self->key); self->key.type = -1; }
+ rv = ecc_import_openssl(data, (unsigned long)data_len, &self->key);
+ if (rv != CRYPT_OK) croak("FATAL: ecc_import_openssl failed: %s", error_to_string(rv));
XPUSHs(ST(0)); /* return self */
}
@@ -63,14 +65,14 @@ _import_pkcs8(Crypt::PK::ECC self, SV * key_data, SV * passwd)
if (SvOK(passwd)) {
pwd = (unsigned char *)SvPVbyte(passwd, pwd_len);
}
- _ecc_free_key(&self->key, &self->dp);
- rv = ecc_import_pkcs8(data, (unsigned long)data_len, pwd, (unsigned long)pwd_len, &self->key, &self->dp);
+ if (self->key.type != -1) { ecc_free(&self->key); self->key.type = -1; }
+ rv = ecc_import_pkcs8(data, (unsigned long)data_len, pwd, (unsigned long)pwd_len, &self->key);
if (rv != CRYPT_OK) croak("FATAL: ecc_import_pkcs8 failed: %s", error_to_string(rv));
XPUSHs(ST(0)); /* return self */
}
void
-import_key_raw(Crypt::PK::ECC self, SV * key_data, SV * curve)
+_import_x509(Crypt::PK::ECC self, SV * key_data)
PPCODE:
{
int rv;
@@ -78,12 +80,29 @@ import_key_raw(Crypt::PK::ECC self, SV * key_data, SV * curve)
STRLEN data_len=0;
data = (unsigned char *)SvPVbyte(key_data, data_len);
- _ecc_free_key(&self->key, &self->dp);
+ if (self->key.type != -1) { ecc_free(&self->key); self->key.type = -1; }
+ rv = ecc_import_x509(data, (unsigned long)data_len, &self->key);
+ if (rv != CRYPT_OK) croak("FATAL: ecc_import_x509 failed: %s", error_to_string(rv));
+ XPUSHs(ST(0)); /* return self */
+ }
- _ecc_set_dp_from_SV(&self->dp, curve); /* croaks on error */
+void
+import_key_raw(Crypt::PK::ECC self, SV * key_data, SV * curve)
+ PPCODE:
+ {
+ int rv, type;
+ unsigned char *data=NULL;
+ STRLEN data_len=0;
- rv = ecc_import_raw(data, (unsigned long)data_len, &self->key, &self->dp);
- if (rv != CRYPT_OK) croak("FATAL: ecc_import_raw failed: %s", error_to_string(rv));
+ data = (unsigned char *)SvPVbyte(key_data, data_len);
+ if (self->key.type != -1) { ecc_free(&self->key); self->key.type = -1; }
+ /* setup dp structure */
+ rv = _ecc_set_dp_from_SV(&self->key, curve); /* croaks on error */
+ if (rv != CRYPT_OK) croak("FATAL: ecc_set_dp failed: %s", error_to_string(rv));
+ /* import key */
+ type = (data_len == (STRLEN)ecc_get_size(&self->key)) ? PK_PRIVATE : PK_PUBLIC;
+ rv = ecc_set_key(data, (unsigned long)data_len, type, &self->key);
+ if (rv != CRYPT_OK) croak("FATAL: ecc_set_key failed: %s", error_to_string(rv));
XPUSHs(ST(0)); /* return self */
}
@@ -151,61 +170,55 @@ key2hash(Crypt::PK::ECC self)
not_used = hv_store(rv_hash, "pub_y", 5, newSVpv("", 0), 0);
}
/* curve_... */
- if (self->key.dp) {
- not_used = hv_store(rv_hash, "curve_cofactor", 14, newSViv(self->key.dp->cofactor), 0);
- /* prepend leading zero if we have odd number of hexadecimal digits */
- strncpy(buf, self->key.dp->prime, 20000); str_add_leading_zero(buf, 20000, 0);
- not_used = hv_store(rv_hash, "curve_prime", 11, newSVpv(buf, strlen(buf)), 0);
- strncpy(buf, self->key.dp->A, 20000); str_add_leading_zero(buf, 20000, 0);
- not_used = hv_store(rv_hash, "curve_A", 7, newSVpv(buf, strlen(buf)), 0);
- strncpy(buf, self->key.dp->B, 20000); str_add_leading_zero(buf, 20000, 0);
- not_used = hv_store(rv_hash, "curve_B", 7, newSVpv(buf, strlen(buf)), 0);
- strncpy(buf, self->key.dp->order, 20000); str_add_leading_zero(buf, 20000, 0);
- not_used = hv_store(rv_hash, "curve_order", 11, newSVpv(buf, strlen(buf)), 0);
- strncpy(buf, self->key.dp->Gx, 20000); str_add_leading_zero(buf, 20000, 0);
- not_used = hv_store(rv_hash, "curve_Gx", 8, newSVpv(buf, strlen(buf)), 0);
- strncpy(buf, self->key.dp->Gy, 20000); str_add_leading_zero(buf, 20000, 0);
- not_used = hv_store(rv_hash, "curve_Gy", 8, newSVpv(buf, strlen(buf)), 0);
- /* OLD approach
- not_used = hv_store(rv_hash, "curve_prime", 11, newSVpv(self->key.dp->prime, strlen(self->key.dp->prime)), 0);
- not_used = hv_store(rv_hash, "curve_A", 7, newSVpv(self->key.dp->A, strlen(self->key.dp->A)), 0);
- not_used = hv_store(rv_hash, "curve_B", 7, newSVpv(self->key.dp->B, strlen(self->key.dp->B)), 0);
- not_used = hv_store(rv_hash, "curve_order", 11, newSVpv(self->key.dp->order, strlen(self->key.dp->order)), 0);
- not_used = hv_store(rv_hash, "curve_Gx", 8, newSVpv(self->key.dp->Gx, strlen(self->key.dp->Gx)), 0);
- not_used = hv_store(rv_hash, "curve_Gy", 8, newSVpv(self->key.dp->Gy, strlen(self->key.dp->Gy)), 0);
- */
- {
- mp_int p_num;
- mp_init(&p_num);
- mp_read_radix(&p_num, self->key.dp->prime, 16);
- not_used = hv_store(rv_hash, "curve_bytes", 11, newSViv(mp_unsigned_bin_size(&p_num)), 0);
- not_used = hv_store(rv_hash, "curve_bits", 10, newSViv(mp_count_bits(&p_num)), 0);
- mp_clear(&p_num);
- }
- {
- unsigned long i;
- SV *name;
- char *name_ptr;
- STRLEN name_len;
-
- name = newSVpv(self->key.dp->name, strlen(self->key.dp->name));
- name_ptr = SvPV(name, name_len);
- for (i=0; i<name_len && name_ptr[i]>0; i++) name_ptr[i] = toLOWER(name_ptr[i]);
- not_used = hv_store(rv_hash, "curve_name", 10, name, 0);
- }
- if (self->key.dp->oid.OIDlen > 0) {
+ {
+ not_used = hv_store(rv_hash, "curve_cofactor", 14, newSViv(self->key.dp.cofactor), 0);
+ mp_tohex_with_leading_zero(self->key.dp.prime, buf, 20000, 0);
+ not_used = hv_store(rv_hash, "curve_prime", 11, newSVpv(buf, strlen(buf)), 0);
+ mp_tohex_with_leading_zero(self->key.dp.A, buf, 20000, 0);
+ not_used = hv_store(rv_hash, "curve_A", 7, newSVpv(buf, strlen(buf)), 0);
+ mp_tohex_with_leading_zero(self->key.dp.B, buf, 20000, 0);
+ not_used = hv_store(rv_hash, "curve_B", 7, newSVpv(buf, strlen(buf)), 0);
+ mp_tohex_with_leading_zero(self->key.dp.order, buf, 20000, 0);
+ not_used = hv_store(rv_hash, "curve_order", 11, newSVpv(buf, strlen(buf)), 0);
+ mp_tohex_with_leading_zero(self->key.dp.base.x, buf, 20000, 0);
+ not_used = hv_store(rv_hash, "curve_Gx", 8, newSVpv(buf, strlen(buf)), 0);
+ mp_tohex_with_leading_zero(self->key.dp.base.y, buf, 20000, 0);
+ not_used = hv_store(rv_hash, "curve_Gy", 8, newSVpv(buf, strlen(buf)), 0);
+ not_used = hv_store(rv_hash, "curve_bytes", 11, newSViv(mp_unsigned_bin_size(self->key.dp.prime)), 0);
+ not_used = hv_store(rv_hash, "curve_bits", 10, newSViv(mp_count_bits(self->key.dp.prime)), 0);
+
+ if (self->key.dp.oidlen > 0) {
unsigned long i;
+ HV *h;
+ SV **pref, *cname;
+ char *cname_ptr, *oid_ptr;
+ STRLEN cname_len;
+
+ /* OID -> "curve_oid" */
SV *oid = newSVpv("", 0);
- for(i = 0; i < self->key.dp->oid.OIDlen - 1; i++) sv_catpvf(oid, "%lu.", self->key.dp->oid.OID[i]);
- sv_catpvf(oid, "%lu", self->key.dp->oid.OID[i]);
+ for(i = 0; i < self->key.dp.oidlen - 1; i++) sv_catpvf(oid, "%lu.", self->key.dp.oid[i]);
+ sv_catpvf(oid, "%lu", self->key.dp.oid[i]);
+ oid_ptr = SvPVX(oid);
not_used = hv_store(rv_hash, "curve_oid", 9, oid, 0);
+
+ /* curve name -> "curve_name" */
+ if ((h = get_hv("Crypt::PK::ECC::curve2ltc", 0)) != NULL) {
+ pref = hv_fetch(h, oid_ptr, (U32)strlen(oid_ptr), 0);
+ if (pref) {
+ cname_ptr = SvPV(*pref, cname_len);
+ cname = newSVpv(cname_ptr, cname_len);
+ cname_ptr = SvPVX(cname);
+ for (i=0; i<cname_len && cname_ptr[i]>0; i++) cname_ptr[i] = toLOWER(cname_ptr[i]);
+ not_used = hv_store(rv_hash, "curve_name", 10, cname, 0);
+ }
+ }
}
}
/* size */
not_used = hv_store(rv_hash, "size", 4, newSViv(esize), 0);
/* type */
not_used = hv_store(rv_hash, "type", 4, newSViv(self->key.type), 0);
- if (not_used) not_used = NULL; /* just silence the warning: variable 'not_used' set but not used */
+ LTC_UNUSED_PARAM(not_used);
RETVAL = newRV_noinc((SV*)rv_hash);
OUTPUT:
RETVAL
@@ -218,25 +231,35 @@ export_key_der(Crypt::PK::ECC self, char * type)
unsigned char out[4096];
unsigned long int out_len = 4096;
- RETVAL = newSVpvn(NULL, 0); /* undef */
+ if (self->key.type == -1) croak("FATAL: export_key_der no key");
if (strnEQ(type, "private_short", 16)) {
- rv = ecc_export_full(out, &out_len, PK_PRIVATE|PK_CURVEOID, &self->key);
- if (rv != CRYPT_OK) croak("FATAL: ecc_export(PK_PRIVATE|PK_CURVEOID) failed: %s", error_to_string(rv));
+ rv = ecc_export_openssl(out, &out_len, PK_PRIVATE|PK_CURVEOID, &self->key);
+ if (rv != CRYPT_OK) croak("FATAL: ecc_export_openssl(PK_PRIVATE|PK_CURVEOID) failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn((char*)out, out_len);
+ }
+ else if (strnEQ(type, "private_compressed", 16)) {
+ rv = ecc_export_openssl(out, &out_len, PK_PRIVATE|PK_CURVEOID|PK_COMPRESSED, &self->key);
+ if (rv != CRYPT_OK) croak("FATAL: ecc_export_openssl(PK_PRIVATE|PK_CURVEOID|PK_COMPRESSED) failed: %s", error_to_string(rv));
RETVAL = newSVpvn((char*)out, out_len);
}
else if (strnEQ(type, "private", 7)) {
- rv = ecc_export_full(out, &out_len, PK_PRIVATE, &self->key);
- if (rv != CRYPT_OK) croak("FATAL: ecc_export(PK_PRIVATE) failed: %s", error_to_string(rv));
+ rv = ecc_export_openssl(out, &out_len, PK_PRIVATE, &self->key);
+ if (rv != CRYPT_OK) croak("FATAL: ecc_export_openssl(PK_PRIVATE) failed: %s", error_to_string(rv));
+ RETVAL = newSVpvn((char*)out, out_len);
+ }
+ else if (strnEQ(type, "public_compressed", 15)) {
+ rv = ecc_export_openssl(out, &out_len, PK_PUBLIC|PK_CURVEOID|PK_COMPRESSED, &self->key);
+ if (rv != CRYPT_OK) croak("FATAL: ecc_export_openssl(PK_PUBLIC|PK_CURVEOID|PK_COMPRESSED) failed: %s", error_to_string(rv));
RETVAL = newSVpvn((char*)out, out_len);
}
else if (strnEQ(type, "public_short", 15)) {
- rv = ecc_export_full(out, &out_len, PK_PUBLIC|PK_CURVEOID, &self->key);
- if (rv != CRYPT_OK) croak("FATAL: ecc_export(PK_PUBLIC|PK_CURVEOID) failed: %s", error_to_string(rv));
+ rv = ecc_export_openssl(out, &out_len, PK_PUBLIC|PK_CURVEOID, &self->key);
+ if (rv != CRYPT_OK) croak("FATAL: ecc_export_openssl(PK_PUBLIC|PK_CURVEOID) failed: %s", error_to_string(rv));
RETVAL = newSVpvn((char*)out, out_len);
}
else if (strnEQ(type, "public", 6)) {
- rv = ecc_export_full(out, &out_len, PK_PUBLIC, &self->key);
- if (rv != CRYPT_OK) croak("FATAL: ecc_export(PK_PUBLIC) failed: %s", error_to_string(rv));
+ rv = ecc_export_openssl(out, &out_len, PK_PUBLIC, &self->key);
+ if (rv != CRYPT_OK) croak("FATAL: ecc_export_openssl(PK_PUBLIC) failed: %s", error_to_string(rv));
RETVAL = newSVpvn((char*)out, out_len);
}
else {
@@ -254,20 +277,20 @@ export_key_raw(Crypt::PK::ECC self, char * type)
unsigned char out[4096];
unsigned long int out_len = sizeof(out);
- RETVAL = newSVpvn(NULL, 0); /* undef */
+ if (self->key.type == -1) croak("FATAL: export_key_der no key");
if (strnEQ(type, "private", 7)) {
- rv = ecc_export_raw(out, &out_len, PK_PRIVATE, &self->key);
- if (rv != CRYPT_OK) croak("FATAL: ecc_export_raw(private) failed: %s", error_to_string(rv));
+ rv = ecc_get_key(out, &out_len, PK_PRIVATE, &self->key);
+ if (rv != CRYPT_OK) croak("FATAL: ecc_get_key(private) failed: %s", error_to_string(rv));
RETVAL = newSVpvn((char*)out, out_len);
}
else if (strnEQ(type, "public_compressed", 17)) {
- rv = ecc_export_raw(out, &out_len, PK_PUBLIC|PK_COMPRESSED, &self->key);
- if (rv != CRYPT_OK) croak("FATAL: ecc_export_raw(public_compressed) failed: %s", error_to_string(rv));
+ rv = ecc_get_key(out, &out_len, PK_PUBLIC|PK_COMPRESSED, &self->key);
+ if (rv != CRYPT_OK) croak("FATAL: ecc_get_key(public_compressed) failed: %s", error_to_string(rv));
RETVAL = newSVpvn((char*)out, out_len);
}
else if (strnEQ(type, "public", 6)) {
- rv = ecc_export_raw(out, &out_len, PK_PUBLIC, &self->key);
- if (rv != CRYPT_OK) croak("FATAL: ecc_export_raw(public) failed: %s", error_to_string(rv));
+ rv = ecc_get_key(out, &out_len, PK_PUBLIC, &self->key);
+ if (rv != CRYPT_OK) croak("FATAL: ecc_get_key(public) failed: %s", error_to_string(rv));
RETVAL = newSVpvn((char*)out, out_len);
}
else {
@@ -278,7 +301,7 @@ export_key_raw(Crypt::PK::ECC self, char * type)
RETVAL
SV *
-_encrypt(Crypt::PK::ECC self, SV * data, char * hash_name)
+encrypt(Crypt::PK::ECC self, SV * data, const char * hash_name = "SHA1")
CODE:
{
int rv, hash_id;
@@ -289,7 +312,7 @@ _encrypt(Crypt::PK::ECC self, SV * data, char * hash_name)
data_ptr = (unsigned char *)SvPVbyte(data, data_len);
- hash_id = find_hash(hash_name);
+ hash_id = _find_hash(hash_name);
if (hash_id == -1) croak("FATAL: find_hash failed for '%s'", hash_name);
rv = ecc_encrypt_key(data_ptr, (unsigned long)data_len, buffer, &buffer_len,
&self->pstate, self->pindex,
@@ -301,7 +324,7 @@ _encrypt(Crypt::PK::ECC self, SV * data, char * hash_name)
RETVAL
SV *
-_decrypt(Crypt::PK::ECC self, SV * data)
+decrypt(Crypt::PK::ECC self, SV * data)
CODE:
{
int rv;
@@ -320,20 +343,28 @@ _decrypt(Crypt::PK::ECC self, SV * data)
RETVAL
SV *
-_sign(Crypt::PK::ECC self, SV * data)
+sign_hash(Crypt::PK::ECC self, SV * data, const char * hash_name = "SHA1")
ALIAS:
- _sign_rfc7518 = 1
+ sign_hash_rfc7518 = 3
+ sign_message = 1
+ sign_message_rfc7518 = 2
CODE:
{
- int rv;
- unsigned char *data_ptr=NULL;
- STRLEN data_len=0;
- unsigned char buffer[1024];
- unsigned long buffer_len = 1024;
+ int rv, id;
+ unsigned char buffer[1024], tmp[MAXBLOCKSIZE], *data_ptr = NULL;
+ unsigned long tmp_len = MAXBLOCKSIZE, buffer_len = 1024;
+ STRLEN data_len = 0;
data_ptr = (unsigned char *)SvPVbyte(data, data_len);
-
- if (ix == 1) {
+ if (ix == 1 || ix == 2) {
+ id = _find_hash(hash_name);
+ if (id == -1) croak("FATAL: find_hash failed for '%s'", hash_name);
+ rv = hash_memory(id, data_ptr, (unsigned long)data_len, tmp, &tmp_len);
+ if (rv != CRYPT_OK) croak("FATAL: hash_memory failed: %s", error_to_string(rv));
+ data_ptr = tmp;
+ data_len = tmp_len;
+ }
+ if (ix == 2 || ix == 3) {
rv = ecc_sign_hash_rfc7518(data_ptr, (unsigned long)data_len, buffer, &buffer_len,
&self->pstate, self->pindex,
&self->key);
@@ -350,23 +381,31 @@ _sign(Crypt::PK::ECC self, SV * data)
RETVAL
int
-_verify(Crypt::PK::ECC self, SV * sig, SV * data)
+verify_hash(Crypt::PK::ECC self, SV * sig, SV * data, const char * hash_name = "SHA1")
ALIAS:
- _verify_rfc7518 = 1
+ verify_hash_rfc7518 = 3
+ verify_message = 1
+ verify_message_rfc7518 = 2
CODE:
{
- int rv, stat;
- unsigned char *data_ptr=NULL;
- STRLEN data_len=0;
- unsigned char *sig_ptr=NULL;
- STRLEN sig_len=0;
+ int rv, stat, id;
+ unsigned char tmp[MAXBLOCKSIZE], *data_ptr = NULL, *sig_ptr = NULL;
+ unsigned long tmp_len = MAXBLOCKSIZE;
+ STRLEN data_len = 0, sig_len = 0;
data_ptr = (unsigned char *)SvPVbyte(data, data_len);
sig_ptr = (unsigned char *)SvPVbyte(sig, sig_len);
-
+ if (ix == 1 || ix == 2) {
+ id = _find_hash(hash_name);
+ if (id == -1) croak("FATAL: find_hash failed for '%s'", hash_name);
+ rv = hash_memory(id, data_ptr, (unsigned long)data_len, tmp, &tmp_len);
+ if (rv != CRYPT_OK) croak("FATAL: hash_memory failed: %s", error_to_string(rv));
+ data_ptr = tmp;
+ data_len = tmp_len;
+ }
RETVAL = 1;
stat = 0;
- if (ix == 1) {
+ if (ix == 2 || ix == 3) {
rv = ecc_verify_hash_rfc7518(sig_ptr, (unsigned long)sig_len, data_ptr, (unsigned long)data_len, &stat, &self->key);
}
else {
@@ -395,6 +434,6 @@ shared_secret(Crypt::PK::ECC self, Crypt::PK::ECC pubkey)
void
DESTROY(Crypt::PK::ECC self)
CODE:
- _ecc_free_key(&self->key, &self->dp);
+ if (self->key.type != -1) { ecc_free(&self->key); self->key.type = -1; }
Safefree(self);
diff --git a/inc/CryptX_PK_RSA.xs.inc b/inc/CryptX_PK_RSA.xs.inc
index 0c0cf852..ef33f109 100644
--- a/inc/CryptX_PK_RSA.xs.inc
+++ b/inc/CryptX_PK_RSA.xs.inc
@@ -1,7 +1,9 @@
MODULE = CryptX PACKAGE = Crypt::PK::RSA
+PROTOTYPES: DISABLE
+
Crypt::PK::RSA
-_new()
+_new(Class)
CODE:
{
int rv;
@@ -261,7 +263,7 @@ key2hash(Crypt::PK::RSA self)
not_used = hv_store(rv_hash, "size", 4, newSViv(nsize), 0);
/* type */
not_used = hv_store(rv_hash, "type", 4, newSViv(self->key.type), 0);
- if (not_used) not_used = NULL; /* just silence the warning: variable 'not_used' set but not used */
+ LTC_UNUSED_PARAM(not_used);
RETVAL = newRV_noinc((SV*)rv_hash);
OUTPUT:
RETVAL
@@ -293,7 +295,7 @@ export_key_der(Crypt::PK::RSA self, char * type)
RETVAL
SV *
-_encrypt(Crypt::PK::RSA self, SV * data, char * padding, char * oaep_hash, SV * oaep_lparam)
+encrypt(Crypt::PK::RSA self, SV * data, const char * padding = "oaep", const char * oaep_hash = "SHA1", SV * oaep_lparam = NULL)
CODE:
{
int rv, hash_id;
@@ -308,9 +310,9 @@ _encrypt(Crypt::PK::RSA self, SV * data, char * padding, char * oaep_hash, SV *
RETVAL = newSVpvn(NULL, 0); /* undef */
if (strnEQ(padding, "oaep", 4)) {
- hash_id = find_hash(oaep_hash);
+ hash_id = _find_hash(oaep_hash);
if (hash_id == -1) croak("FATAL: find_hash failed for '%s'", oaep_hash);
- lparam_ptr = (unsigned char *)SvPVbyte(oaep_lparam, lparam_len);
+ if (oaep_lparam) lparam_ptr = (unsigned char *)SvPVbyte(oaep_lparam, lparam_len);
rv = rsa_encrypt_key_ex(data_ptr, (unsigned long)data_len, buffer, &buffer_len, lparam_ptr, (unsigned long)lparam_len,
&self->pstate, self->pindex,
hash_id, LTC_PKCS_1_OAEP, &self->key);
@@ -338,7 +340,7 @@ _encrypt(Crypt::PK::RSA self, SV * data, char * padding, char * oaep_hash, SV *
RETVAL
SV *
-_decrypt(Crypt::PK::RSA self, SV * data, char * padding, char * oaep_hash, SV * oaep_lparam)
+decrypt(Crypt::PK::RSA self, SV * data, const char * padding = "oaep", const char * oaep_hash = "SHA1", SV * oaep_lparam = NULL)
CODE:
{
int rv, hash_id, stat;
@@ -353,9 +355,9 @@ _decrypt(Crypt::PK::RSA self, SV * data, char * padding, char * oaep_hash, SV *
RETVAL = newSVpvn(NULL, 0); /* undef */
if (strnEQ(padding, "oaep", 4)) {
- hash_id = find_hash(oaep_hash);
+ hash_id = _find_hash(oaep_hash);
if (hash_id == -1) croak("FATAL: find_hash failed for '%s'", oaep_hash);
- lparam_ptr = (unsigned char *)SvPVbyte(oaep_lparam, lparam_len);
+ if (oaep_lparam) lparam_ptr = (unsigned char *)SvPVbyte(oaep_lparam, lparam_len);
rv = rsa_decrypt_key_ex(data_ptr, (unsigned long)data_len, buffer, &buffer_len, lparam_ptr, (unsigned long)lparam_len,
hash_id, LTC_PKCS_1_OAEP, &stat, &self->key);
if (rv != CRYPT_OK) croak("FATAL: rsa_decrypt_key_ex failed: %s", error_to_string(rv));
@@ -383,20 +385,27 @@ _decrypt(Crypt::PK::RSA self, SV * data, char * padding, char * oaep_hash, SV *
RETVAL
SV *
-_sign(Crypt::PK::RSA self, SV * data, char * padding, char * hash_name=NULL, unsigned long saltlen=12)
+sign_hash(Crypt::PK::RSA self, SV * data, const char * hash_name = "SHA1", const char * padding = "pss", unsigned long saltlen=12)
+ ALIAS:
+ sign_message = 1
CODE:
{
int rv, hash_id;
- unsigned char *data_ptr=NULL;
- STRLEN data_len=0;
- unsigned char buffer[1024];
- unsigned long buffer_len = 1024;
+ unsigned char buffer[1024], tmp[MAXBLOCKSIZE], *data_ptr = NULL;
+ unsigned long tmp_len = MAXBLOCKSIZE, buffer_len = 1024;
+ STRLEN data_len = 0;
data_ptr = (unsigned char *)SvPVbyte(data, data_len);
-
- RETVAL = newSVpvn(NULL, 0); /* undef */
+ if (ix == 1) {
+ hash_id = _find_hash(hash_name);
+ if (hash_id == -1) croak("FATAL: find_hash failed for '%s'", hash_name);
+ rv = hash_memory(hash_id, data_ptr, (unsigned long)data_len, tmp, &tmp_len);
+ if (rv != CRYPT_OK) croak("FATAL: hash_memory failed: %s", error_to_string(rv));
+ data_ptr = tmp;
+ data_len = tmp_len;
+ }
if (strnEQ(padding, "pss", 3)) {
- hash_id = find_hash(hash_name);
+ hash_id = _find_hash(hash_name);
if (hash_id == -1) croak("FATAL: find_hash failed for '%s'", hash_name);
rv = rsa_sign_hash_ex(data_ptr, (unsigned long)data_len, buffer, &buffer_len, LTC_PKCS_1_PSS,
&self->pstate, self->pindex,
@@ -405,7 +414,7 @@ _sign(Crypt::PK::RSA self, SV * data, char * padding, char * hash_name=NULL, uns
RETVAL = newSVpvn((char*)buffer, buffer_len);
}
else if (strnEQ(padding, "v1.5", 4)) {
- hash_id = find_hash(hash_name);
+ hash_id = _find_hash(hash_name);
if (hash_id == -1) croak("FATAL: find_hash failed for '%s'", hash_name);
rv = rsa_sign_hash_ex(data_ptr, (unsigned long)data_len, buffer, &buffer_len, LTC_PKCS_1_V1_5,
&self->pstate, self->pindex,
@@ -427,31 +436,37 @@ _sign(Crypt::PK::RSA self, SV * data, char * padding, char * hash_name=NULL, uns
RETVAL
int
-_verify(Crypt::PK::RSA self, SV * sig, SV * data, char * padding, char * hash_name=NULL, unsigned long saltlen=12)
+verify_hash(Crypt::PK::RSA self, SV * sig, SV * data, const char * hash_name = "SHA1", const char * padding = "pss", unsigned long saltlen = 12)
+ ALIAS:
+ verify_message = 1
CODE:
{
int rv, hash_id, stat;
- unsigned char *data_ptr=NULL;
- STRLEN data_len=0;
- unsigned char *sig_ptr=NULL;
- STRLEN sig_len=0;
- unsigned char buffer[1024];
- unsigned long i, buffer_len = 1024;
+ unsigned char tmp[MAXBLOCKSIZE], buffer[1024], *data_ptr = NULL, *sig_ptr = NULL;
+ unsigned long i, tmp_len = MAXBLOCKSIZE, buffer_len = 1024;
+ STRLEN data_len = 0, sig_len = 0;
data_ptr = (unsigned char *)SvPVbyte(data, data_len);
sig_ptr = (unsigned char *)SvPVbyte(sig, sig_len);
-
+ if (ix == 1) {
+ hash_id = _find_hash(hash_name);
+ if (hash_id == -1) croak("FATAL: find_hash failed for '%s'", hash_name);
+ rv = hash_memory(hash_id, data_ptr, (unsigned long)data_len, tmp, &tmp_len);
+ if (rv != CRYPT_OK) croak("FATAL: hash_memory failed: %s", error_to_string(rv));
+ data_ptr = tmp;
+ data_len = tmp_len;
+ }
RETVAL = 1;
stat = 0;
if (strnEQ(padding, "pss", 3)) {
- hash_id = find_hash(hash_name);
+ hash_id = _find_hash(hash_name);
if (hash_id == -1) croak("FATAL: find_hash failed for '%s'", hash_name);
rv = rsa_verify_hash_ex(sig_ptr, (unsigned long)sig_len, data_ptr, (unsigned long)data_len, LTC_PKCS_1_PSS,
hash_id, saltlen, &stat, &self->key);
if (rv != CRYPT_OK || stat != 1) RETVAL = 0;
}
else if (strnEQ(padding, "v1.5", 4)) {
- hash_id = find_hash(hash_name);
+ hash_id = _find_hash(hash_name);
if (hash_id == -1) croak("FATAL: find_hash failed for '%s'", hash_name);
rv = rsa_verify_hash_ex(sig_ptr, (unsigned long)sig_len, data_ptr, (unsigned long)data_len, LTC_PKCS_1_V1_5,
hash_id, 0, &stat, &self->key);
diff --git a/inc/CryptX_PRNG.xs.inc b/inc/CryptX_PRNG.xs.inc
index 192f1f6e..93453119 100644
--- a/inc/CryptX_PRNG.xs.inc
+++ b/inc/CryptX_PRNG.xs.inc
@@ -1,23 +1,35 @@
MODULE = CryptX PACKAGE = Crypt::PRNG
+PROTOTYPES: DISABLE
+
Crypt::PRNG
-_new(IV curpid, char * prng_name, SV * entropy=&PL_sv_undef)
+new(char * class, ...)
CODE:
{
- int rv, id;
+ IV curpid = (IV)PerlProc_getpid();
+ int rv, id, idx;
unsigned char *ent=NULL;
STRLEN ent_len=0;
unsigned char entropy_buf[40];
+ char *prng_name = (char *)"ChaCha20";
+ SV *entropy = &PL_sv_undef;
+
+ /* we need to handle:
+ Crypt::PRNG->new('RC4');
+ Crypt::Cipher::RC4->new();
+ */
+ idx = strcmp("Crypt::PRNG", class) == 0 ? 1 : 0;
+ if (idx + 1 <= items) prng_name = SvPVX(ST(idx));
+ if (idx + 2 <= items) entropy = ST(idx + 1);
Newz(0, RETVAL, 1, struct prng_struct);
if (!RETVAL) croak("FATAL: Newz failed");
- id = find_prng(prng_name);
+ id = _find_prng(prng_name);
if (id == -1) {
Safefree(RETVAL);
croak("FATAL: find_prng failed for '%s'", prng_name);
}
- RETVAL->id = id;
RETVAL->last_pid = curpid;
RETVAL->desc = &prng_descriptor[id];
@@ -58,9 +70,7 @@ _new(IV curpid, char * prng_name, SV * entropy=&PL_sv_undef)
void
DESTROY(Crypt::PRNG self)
CODE:
- {
Safefree(self);
- }
void
add_entropy(Crypt::PRNG self, SV * entropy=&PL_sv_undef)
@@ -85,37 +95,89 @@ add_entropy(Crypt::PRNG self, SV * entropy=&PL_sv_undef)
}
SV *
-_bytes(Crypt::PRNG self, IV curpid, STRLEN output_len)
+bytes(Crypt::PRNG self, unsigned long output_len)
+ ALIAS:
+ bytes_hex = 1
+ bytes_b64 = 2
+ bytes_b64u = 3
CODE:
{
- int rv_len;
- unsigned char *rdata;
+ IV curpid = (IV)PerlProc_getpid();
+ int rv_len, rv;
+ unsigned long len;
+ unsigned char *rdata, *tmp;
unsigned char entropy_buf[40];
- if (self->last_pid != curpid) {
- if (rng_get_bytes(entropy_buf, 40, NULL) != 40) croak("FATAL: rng_get_bytes failed");
- self->desc->add_entropy(entropy_buf, 40, &self->state);
- self->desc->ready(&self->state);
- self->last_pid = curpid;
+ if (output_len == 0) {
+ RETVAL = newSVpvn("", 0);
}
-
- RETVAL = NEWSV(0, output_len);
- SvPOK_only(RETVAL);
- SvCUR_set(RETVAL, output_len);
- rdata = (unsigned char *)SvPVX(RETVAL);
- rv_len = (self->desc->read)(rdata, (unsigned long)output_len, &self->state);
- if ((UV)rv_len != output_len) {
- SvREFCNT_dec(RETVAL);
- croak("FATAL: PRNG_read failed");
+ else {
+ if (self->last_pid != curpid) {
+ if (rng_get_bytes(entropy_buf, 40, NULL) != 40) croak("FATAL: rng_get_bytes failed");
+ self->desc->add_entropy(entropy_buf, 40, &self->state);
+ self->desc->ready(&self->state);
+ self->last_pid = curpid;
+ }
+ if (ix == 1) {
+ /* HEX */
+ Newz(0, tmp, output_len, unsigned char);
+ if (tmp == NULL) croak("FATAL: Newz failed");
+ rv_len = (self->desc->read)(tmp, (unsigned long)output_len, &self->state);
+ if ((UV)rv_len != output_len) croak("FATAL: PRNG_read failed");
+ RETVAL = NEWSV(0, output_len * 2); /* avoid zero! */
+ SvPOK_only(RETVAL);
+ SvCUR_set(RETVAL, output_len * 2);
+ rdata = (unsigned char *)SvPVX(RETVAL);
+ len = output_len * 2;
+ rv = _base16_encode(tmp, output_len, rdata, &len);
+ Safefree(tmp);
+ if (rv != CRYPT_OK) {
+ SvREFCNT_dec(RETVAL);
+ croak("FATAL: base16_encode failed");
+ }
+ }
+ else if (ix == 2 || ix == 3) {
+ /* BASE64 or BASE64URL */
+ Newz(0, tmp, output_len, unsigned char);
+ if (tmp == NULL) croak("FATAL: Newz failed");
+ rv_len = (self->desc->read)(tmp, (unsigned long)output_len, &self->state);
+ if ((UV)rv_len != output_len) croak("FATAL: PRNG_read failed");
+ RETVAL = NEWSV(0, output_len * 2); /* avoid zero! */
+ SvPOK_only(RETVAL);
+ SvCUR_set(RETVAL, output_len * 2);
+ rdata = (unsigned char *)SvPVX(RETVAL);
+ len = output_len * 2;
+ rv = ix == 3 ? base64url_encode(tmp, output_len, rdata, &len) :
+ base64_encode(tmp, output_len, rdata, &len);
+ SvCUR_set(RETVAL, len);
+ Safefree(tmp);
+ if (rv != CRYPT_OK) {
+ SvREFCNT_dec(RETVAL);
+ croak(ix == 3 ? "FATAL: base64url_encode failed" : "FATAL: base64_encode failed");
+ }
+ }
+ else {
+ /* RAW BYTES */
+ RETVAL = NEWSV(0, output_len); /* avoid zero! */
+ SvPOK_only(RETVAL);
+ SvCUR_set(RETVAL, output_len);
+ rdata = (unsigned char *)SvPVX(RETVAL);
+ rv_len = (self->desc->read)(rdata, (unsigned long)output_len, &self->state);
+ if ((UV)rv_len != output_len) {
+ SvREFCNT_dec(RETVAL);
+ croak("FATAL: PRNG_read failed");
+ }
+ }
}
}
OUTPUT:
RETVAL
UV
-_int32(Crypt::PRNG self, IV curpid)
+int32(Crypt::PRNG self)
CODE:
{
+ IV curpid = (IV)PerlProc_getpid();
int i;
unsigned char rdata[4];
unsigned char entropy_buf[40];
@@ -135,14 +197,14 @@ _int32(Crypt::PRNG self, IV curpid)
RETVAL
NV
-_double(Crypt::PRNG self, IV curpid, ...)
+double(Crypt::PRNG self, SV * limit_sv = NULL)
CODE:
{
+ IV curpid = (IV)PerlProc_getpid();
int i;
unsigned long a, b; /* 32bit is enough */
unsigned char rdata[7]; /* for double we need 53 bits */
unsigned char entropy_buf[40];
- NV limit;
if (self->last_pid != curpid) {
if (rng_get_bytes(entropy_buf, 40, NULL) != 40) croak("FATAL: rng_get_bytes failed");
@@ -156,8 +218,8 @@ _double(Crypt::PRNG self, IV curpid, ...)
a = (((unsigned long)(rdata[0])<<16) + ((unsigned long)(rdata[1])<<8) + ((unsigned long)(rdata[2]))) & 0x1FFFFF; /* 21 bits */
b = ((unsigned long)(rdata[3])<<24) + ((unsigned long)(rdata[4])<<16) + ((unsigned long)(rdata[5])<<8) + ((unsigned long)(rdata[6])); /* 32 bits */
RETVAL = ( (NV)a * 4294967296.0 + (NV)b ) / 9007199254740992.0; /* (a * 2^32 + b) / 2^53 */
- if (items>2 && SvOK(ST(2))) {
- limit = SvNV(ST(2));
+ if (limit_sv && SvOK(limit_sv)) {
+ NV limit = SvNV(limit_sv);
if (limit > 0 || limit < 0) RETVAL = RETVAL * limit;
}
}
diff --git a/inc/CryptX_Stream_ChaCha.xs.inc b/inc/CryptX_Stream_ChaCha.xs.inc
index 4b71a090..e1287b64 100644
--- a/inc/CryptX_Stream_ChaCha.xs.inc
+++ b/inc/CryptX_Stream_ChaCha.xs.inc
@@ -1,5 +1,7 @@
MODULE = CryptX PACKAGE = Crypt::Stream::ChaCha
+PROTOTYPES: DISABLE
+
Crypt::Stream::ChaCha
new(Class, SV * key, SV * nonce, UV counter = 0, int rounds = 20)
CODE:
@@ -13,24 +15,24 @@ new(Class, SV * key, SV * nonce, UV counter = 0, int rounds = 20)
k = (unsigned char *) SvPVbyte(key, k_len);
iv = (unsigned char *) SvPVbyte(nonce, iv_len);
- Newz(0, RETVAL, 1, struct chacha_struct);
+ Newz(0, RETVAL, 1, chacha_state);
if (!RETVAL) croak("FATAL: Newz failed");
- rv = chacha_setup(&RETVAL->state, k, (unsigned long)k_len, rounds);
+ rv = chacha_setup(RETVAL, k, (unsigned long)k_len, rounds);
if (rv != CRYPT_OK) {
Safefree(RETVAL);
croak("FATAL: chacha_setup failed: %s", error_to_string(rv));
}
if (iv_len == 12) {
- rv = chacha_ivctr32(&RETVAL->state, iv, (unsigned long)iv_len, (ulong32)counter);
+ rv = chacha_ivctr32(RETVAL, iv, (unsigned long)iv_len, (ulong32)counter);
if (rv != CRYPT_OK) {
Safefree(RETVAL);
croak("FATAL: chacha_ivctr32 failed: %s", error_to_string(rv));
}
}
else if (iv_len == 8) {
- rv = chacha_ivctr64(&RETVAL->state, iv, (unsigned long)iv_len, (ulong64)counter);
+ rv = chacha_ivctr64(RETVAL, iv, (unsigned long)iv_len, (ulong64)counter);
if (rv != CRYPT_OK) {
Safefree(RETVAL);
croak("FATAL: chacha_ivctr64 failed: %s", error_to_string(rv));
@@ -47,15 +49,15 @@ new(Class, SV * key, SV * nonce, UV counter = 0, int rounds = 20)
void
DESTROY(Crypt::Stream::ChaCha self)
CODE:
- chacha_done(&self->state);
+ chacha_done(self);
Safefree(self);
Crypt::Stream::ChaCha
clone(Crypt::Stream::ChaCha self)
CODE:
- Newz(0, RETVAL, 1, struct chacha_struct);
+ Newz(0, RETVAL, 1, chacha_state);
if (!RETVAL) croak("FATAL: Newz failed");
- Copy(&self->state, &RETVAL->state, 1, struct chacha_struct);
+ Copy(self, RETVAL, 1, chacha_state);
OUTPUT:
RETVAL
@@ -66,14 +68,19 @@ keystream(Crypt::Stream::ChaCha self, STRLEN out_len)
int rv;
unsigned char *out_data;
- RETVAL = NEWSV(0, out_len);
- SvPOK_only(RETVAL);
- SvCUR_set(RETVAL, out_len);
- out_data = (unsigned char *)SvPVX(RETVAL);
- rv = chacha_keystream(&self->state, out_data, (unsigned long)out_len);
- if (rv != CRYPT_OK) {
- SvREFCNT_dec(RETVAL);
- croak("FATAL: chacha_keystream failed: %s", error_to_string(rv));
+ if (out_len == 0) {
+ RETVAL = newSVpvn("", 0);
+ }
+ else {
+ RETVAL = NEWSV(0, out_len); /* avoid zero! */
+ SvPOK_only(RETVAL);
+ SvCUR_set(RETVAL, out_len);
+ out_data = (unsigned char *)SvPVX(RETVAL);
+ rv = chacha_keystream(self, out_data, (unsigned long)out_len);
+ if (rv != CRYPT_OK) {
+ SvREFCNT_dec(RETVAL);
+ croak("FATAL: chacha_keystream failed: %s", error_to_string(rv));
+ }
}
}
OUTPUT:
@@ -92,11 +99,11 @@ crypt(Crypt::Stream::ChaCha self, SV * data)
RETVAL = newSVpvn("", 0);
}
else {
- RETVAL = NEWSV(0, in_data_len);
+ RETVAL = NEWSV(0, in_data_len); /* avoid zero! */
SvPOK_only(RETVAL);
SvCUR_set(RETVAL, in_data_len);
out_data = (unsigned char *)SvPVX(RETVAL);
- rv = chacha_crypt(&self->state, in_data, (unsigned long)in_data_len, out_data);
+ rv = chacha_crypt(self, in_data, (unsigned long)in_data_len, out_data);
if (rv != CRYPT_OK) {
SvREFCNT_dec(RETVAL);
croak("FATAL: chacha_crypt failed: %s", error_to_string(rv));
diff --git a/inc/CryptX_Stream_RC4.xs.inc b/inc/CryptX_Stream_RC4.xs.inc
index 09a56147..eb48b90e 100644
--- a/inc/CryptX_Stream_RC4.xs.inc
+++ b/inc/CryptX_Stream_RC4.xs.inc
@@ -1,5 +1,7 @@
MODULE = CryptX PACKAGE = Crypt::Stream::RC4
+PROTOTYPES: DISABLE
+
Crypt::Stream::RC4
new(Class, SV * key)
CODE:
@@ -11,10 +13,10 @@ new(Class, SV * key)
if (!SvPOK(key)) croak("FATAL: key must be string/buffer scalar");
k = (unsigned char *) SvPVbyte(key, k_len);
- Newz(0, RETVAL, 1, struct rc4_struct);
+ Newz(0, RETVAL, 1, rc4_state);
if (!RETVAL) croak("FATAL: Newz failed");
- rv = rc4_stream_setup(&RETVAL->state, k, (unsigned long)k_len);
+ rv = rc4_stream_setup(RETVAL, k, (unsigned long)k_len);
if (rv != CRYPT_OK) {
Safefree(RETVAL);
croak("FATAL: rc4_stream_setup failed: %s", error_to_string(rv));
@@ -26,15 +28,15 @@ new(Class, SV * key)
void
DESTROY(Crypt::Stream::RC4 self)
CODE:
- rc4_stream_done(&self->state);
+ rc4_stream_done(self);
Safefree(self);
Crypt::Stream::RC4
clone(Crypt::Stream::RC4 self)
CODE:
- Newz(0, RETVAL, 1, struct rc4_struct);
+ Newz(0, RETVAL, 1, rc4_state);
if (!RETVAL) croak("FATAL: Newz failed");
- Copy(&self->state, &RETVAL->state, 1, struct rc4_struct);
+ Copy(self, RETVAL, 1, rc4_state);
OUTPUT:
RETVAL
@@ -45,14 +47,19 @@ keystream(Crypt::Stream::RC4 self, STRLEN out_len)
int rv;
unsigned char *out_data;
- RETVAL = NEWSV(0, out_len);
- SvPOK_only(RETVAL);
- SvCUR_set(RETVAL, out_len);
- out_data = (unsigned char *)SvPVX(RETVAL);
- rv = rc4_stream_keystream(&self->state, out_data, (unsigned long)out_len);
- if (rv != CRYPT_OK) {
- SvREFCNT_dec(RETVAL);
- croak("FATAL: rc4_stream_keystream failed: %s", error_to_string(rv));
+ if (out_len == 0) {
+ RETVAL = newSVpvn("", 0);
+ }
+ else {
+ RETVAL = NEWSV(0, out_len); /* avoid zero! */
+ SvPOK_only(RETVAL);
+ SvCUR_set(RETVAL, out_len);
+ out_data = (unsigned char *)SvPVX(RETVAL);
+ rv = rc4_stream_keystream(self, out_data, (unsigned long)out_len);
+ if (rv != CRYPT_OK) {
+ SvREFCNT_dec(RETVAL);
+ croak("FATAL: rc4_stream_keystream failed: %s", error_to_string(rv));
+ }
}
}
OUTPUT:
@@ -71,11 +78,11 @@ crypt(Crypt::Stream::RC4 self, SV * data)
RETVAL = newSVpvn("", 0);
}
else {
- RETVAL = NEWSV(0, in_data_len);
+ RETVAL = NEWSV(0, in_data_len); /* avoid zero! */
SvPOK_only(RETVAL);
SvCUR_set(RETVAL, in_data_len);
out_data = (unsigned char *)SvPVX(RETVAL);
- rv = rc4_stream_crypt(&self->state, in_data, (unsigned long)in_data_len, out_data);
+ rv = rc4_stream_crypt(self, in_data, (unsigned long)in_data_len, out_data);
if (rv != CRYPT_OK) {
SvREFCNT_dec(RETVAL);
croak("FATAL: rc4_stream_crypt failed: %s", error_to_string(rv));
diff --git a/inc/CryptX_Stream_Rabbit.xs.inc b/inc/CryptX_Stream_Rabbit.xs.inc
index 6ef18249..fe083bc4 100644
--- a/inc/CryptX_Stream_Rabbit.xs.inc
+++ b/inc/CryptX_Stream_Rabbit.xs.inc
@@ -1,5 +1,7 @@
MODULE = CryptX PACKAGE = Crypt::Stream::Rabbit
+PROTOTYPES: DISABLE
+
Crypt::Stream::Rabbit
new(Class, SV * key, SV * nonce=&PL_sv_undef)
CODE:
@@ -11,10 +13,10 @@ new(Class, SV * key, SV * nonce=&PL_sv_undef)
if (!SvPOK(key)) croak("FATAL: key must be string/buffer scalar");
k = (unsigned char *)SvPVbyte(key, k_len);
- Newz(0, RETVAL, 1, struct rabbit_struct);
+ Newz(0, RETVAL, 1, rabbit_state);
if (!RETVAL) croak("FATAL: Newz failed");
- rv = rabbit_setup(&RETVAL->state, k, (unsigned long)k_len);
+ rv = rabbit_setup(RETVAL, k, (unsigned long)k_len);
if (rv != CRYPT_OK) {
Safefree(RETVAL);
croak("FATAL: rabbit_setup failed: %s", error_to_string(rv));
@@ -23,7 +25,7 @@ new(Class, SV * key, SV * nonce=&PL_sv_undef)
if (SvOK(nonce)) {
if (!SvPOK(nonce)) croak("FATAL: nonce must be string/buffer scalar");
iv = (unsigned char *)SvPVbyte(nonce, iv_len);
- rv = rabbit_setiv(&RETVAL->state, iv, (unsigned long)iv_len);
+ rv = rabbit_setiv(RETVAL, iv, (unsigned long)iv_len);
if (rv != CRYPT_OK) {
Safefree(RETVAL);
croak("FATAL: rabbit_setiv failed: %s", error_to_string(rv));
@@ -37,15 +39,15 @@ new(Class, SV * key, SV * nonce=&PL_sv_undef)
void
DESTROY(Crypt::Stream::Rabbit self)
CODE:
- rabbit_done(&self->state);
+ rabbit_done(self);
Safefree(self);
Crypt::Stream::Rabbit
clone(Crypt::Stream::Rabbit self)
CODE:
- Newz(0, RETVAL, 1, struct rabbit_struct);
+ Newz(0, RETVAL, 1, rabbit_state);
if (!RETVAL) croak("FATAL: Newz failed");
- Copy(&self->state, &RETVAL->state, 1, struct rabbit_struct);
+ Copy(self, RETVAL, 1, rabbit_state);
OUTPUT:
RETVAL
@@ -56,14 +58,19 @@ keystream(Crypt::Stream::Rabbit self, STRLEN out_len)
int rv;
unsigned char *out_data;
- RETVAL = NEWSV(0, out_len);
- SvPOK_only(RETVAL);
- SvCUR_set(RETVAL, out_len);
- out_data = (unsigned char *)SvPVX(RETVAL);
- rv = rabbit_keystream(&self->state, out_data, (unsigned long)out_len);
- if (rv != CRYPT_OK) {
- SvREFCNT_dec(RETVAL);
- croak("FATAL: rabbit_keystream failed: %s", error_to_string(rv));
+ if (out_len == 0) {
+ RETVAL = newSVpvn("", 0);
+ }
+ else {
+ RETVAL = NEWSV(0, out_len); /* avoid zero! */
+ SvPOK_only(RETVAL);
+ SvCUR_set(RETVAL, out_len);
+ out_data = (unsigned char *)SvPVX(RETVAL);
+ rv = rabbit_keystream(self, out_data, (unsigned long)out_len);
+ if (rv != CRYPT_OK) {
+ SvREFCNT_dec(RETVAL);
+ croak("FATAL: rabbit_keystream failed: %s", error_to_string(rv));
+ }
}
}
OUTPUT:
@@ -82,11 +89,11 @@ crypt(Crypt::Stream::Rabbit self, SV * data)
RETVAL = newSVpvn("", 0);
}
else {
- RETVAL = NEWSV(0, in_data_len);
+ RETVAL = NEWSV(0, in_data_len); /* avoid zero! */
SvPOK_only(RETVAL);
SvCUR_set(RETVAL, in_data_len);
out_data = (unsigned char *)SvPVX(RETVAL);
- rv = rabbit_crypt(&self->state, in_data, (unsigned long)in_data_len, out_data);
+ rv = rabbit_crypt(self, in_data, (unsigned long)in_data_len, out_data);
if (rv != CRYPT_OK) {
SvREFCNT_dec(RETVAL);
croak("FATAL: rabbit_crypt failed: %s", error_to_string(rv));
diff --git a/inc/CryptX_Stream_Salsa20.xs.inc b/inc/CryptX_Stream_Salsa20.xs.inc
index 7430c3dc..65c0d580 100644
--- a/inc/CryptX_Stream_Salsa20.xs.inc
+++ b/inc/CryptX_Stream_Salsa20.xs.inc
@@ -1,5 +1,7 @@
MODULE = CryptX PACKAGE = Crypt::Stream::Salsa20
+PROTOTYPES: DISABLE
+
Crypt::Stream::Salsa20
new(Class, SV * key, SV * nonce, UV counter = 0, int rounds = 20)
CODE:
@@ -13,16 +15,16 @@ new(Class, SV * key, SV * nonce, UV counter = 0, int rounds = 20)
k = (unsigned char *)SvPVbyte(key, k_len);
iv = (unsigned char *)SvPVbyte(nonce, iv_len);
- Newz(0, RETVAL, 1, struct salsa20_struct);
+ Newz(0, RETVAL, 1, salsa20_state);
if (!RETVAL) croak("FATAL: Newz failed");
- rv = salsa20_setup(&RETVAL->state, k, (unsigned long)k_len, rounds);
+ rv = salsa20_setup(RETVAL, k, (unsigned long)k_len, rounds);
if (rv != CRYPT_OK) {
Safefree(RETVAL);
croak("FATAL: salsa20_setup failed: %s", error_to_string(rv));
}
- rv = salsa20_ivctr64(&RETVAL->state, iv, (unsigned long)iv_len, (ulong64)counter);
+ rv = salsa20_ivctr64(RETVAL, iv, (unsigned long)iv_len, (ulong64)counter);
if (rv != CRYPT_OK) {
Safefree(RETVAL);
croak("FATAL: salsa20_ivctr64 failed: %s", error_to_string(rv));
@@ -34,15 +36,15 @@ new(Class, SV * key, SV * nonce, UV counter = 0, int rounds = 20)
void
DESTROY(Crypt::Stream::Salsa20 self)
CODE:
- salsa20_done(&self->state);
+ salsa20_done(self);
Safefree(self);
Crypt::Stream::Salsa20
clone(Crypt::Stream::Salsa20 self)
CODE:
- Newz(0, RETVAL, 1, struct salsa20_struct);
+ Newz(0, RETVAL, 1, salsa20_state);
if (!RETVAL) croak("FATAL: Newz failed");
- Copy(&self->state, &RETVAL->state, 1, struct salsa20_struct);
+ Copy(self, RETVAL, 1, salsa20_state);
OUTPUT:
RETVAL
@@ -53,14 +55,19 @@ keystream(Crypt::Stream::Salsa20 self, STRLEN out_len)
int rv;
unsigned char *out_data;
- RETVAL = NEWSV(0, out_len);
- SvPOK_only(RETVAL);
- SvCUR_set(RETVAL, out_len);
- out_data = (unsigned char *)SvPVX(RETVAL);
- rv = salsa20_keystream(&self->state, out_data, (unsigned long)out_len);
- if (rv != CRYPT_OK) {
- SvREFCNT_dec(RETVAL);
- croak("FATAL: salsa20_keystream failed: %s", error_to_string(rv));
+ if (out_len == 0) {
+ RETVAL = newSVpvn("", 0);
+ }
+ else {
+ RETVAL = NEWSV(0, out_len); /* avoid zero! */
+ SvPOK_only(RETVAL);
+ SvCUR_set(RETVAL, out_len);
+ out_data = (unsigned char *)SvPVX(RETVAL);
+ rv = salsa20_keystream(self, out_data, (unsigned long)out_len);
+ if (rv != CRYPT_OK) {
+ SvREFCNT_dec(RETVAL);
+ croak("FATAL: salsa20_keystream failed: %s", error_to_string(rv));
+ }
}
}
OUTPUT:
@@ -79,11 +86,11 @@ crypt(Crypt::Stream::Salsa20 self, SV * data)
RETVAL = newSVpvn("", 0);
}
else {
- RETVAL = NEWSV(0, in_data_len);
+ RETVAL = NEWSV(0, in_data_len); /* avoid zero! */
SvPOK_only(RETVAL);
SvCUR_set(RETVAL, in_data_len);
out_data = (unsigned char *)SvPVX(RETVAL);
- rv = salsa20_crypt(&self->state, in_data, (unsigned long)in_data_len, out_data);
+ rv = salsa20_crypt(self, in_data, (unsigned long)in_data_len, out_data);
if (rv != CRYPT_OK) {
SvREFCNT_dec(RETVAL);
croak("FATAL: salsa20_crypt failed: %s", error_to_string(rv));
diff --git a/inc/CryptX_Stream_Sober128.xs.inc b/inc/CryptX_Stream_Sober128.xs.inc
index 7802bb16..5e03ba4f 100644
--- a/inc/CryptX_Stream_Sober128.xs.inc
+++ b/inc/CryptX_Stream_Sober128.xs.inc
@@ -1,5 +1,7 @@
MODULE = CryptX PACKAGE = Crypt::Stream::Sober128
+PROTOTYPES: DISABLE
+
Crypt::Stream::Sober128
new(Class, SV * key, SV * nonce)
CODE:
@@ -13,16 +15,16 @@ new(Class, SV * key, SV * nonce)
k = (unsigned char *) SvPVbyte(key, k_len);
iv = (unsigned char *) SvPVbyte(nonce, iv_len);
- Newz(0, RETVAL, 1, struct sober128_struct);
+ Newz(0, RETVAL, 1, sober128_state);
if (!RETVAL) croak("FATAL: Newz failed");
- rv = sober128_stream_setup(&RETVAL->state, k, (unsigned long)k_len);
+ rv = sober128_stream_setup(RETVAL, k, (unsigned long)k_len);
if (rv != CRYPT_OK) {
Safefree(RETVAL);
croak("FATAL: sober128_stream_setup failed: %s", error_to_string(rv));
}
- rv = sober128_stream_setiv(&RETVAL->state, iv, (unsigned long)iv_len);
+ rv = sober128_stream_setiv(RETVAL, iv, (unsigned long)iv_len);
if (rv != CRYPT_OK) {
Safefree(RETVAL);
croak("FATAL: sober128_stream_setiv failed: %s", error_to_string(rv));
@@ -34,15 +36,15 @@ new(Class, SV * key, SV * nonce)
void
DESTROY(Crypt::Stream::Sober128 self)
CODE:
- sober128_stream_done(&self->state);
+ sober128_stream_done(self);
Safefree(self);
Crypt::Stream::Sober128
clone(Crypt::Stream::Sober128 self)
CODE:
- Newz(0, RETVAL, 1, struct sober128_struct);
+ Newz(0, RETVAL, 1, sober128_state);
if (!RETVAL) croak("FATAL: Newz failed");
- Copy(&self->state, &RETVAL->state, 1, struct sober128_struct);
+ Copy(self, RETVAL, 1, sober128_state);
OUTPUT:
RETVAL
@@ -53,14 +55,19 @@ keystream(Crypt::Stream::Sober128 self, STRLEN out_len)
int rv;
unsigned char *out_data;
- RETVAL = NEWSV(0, out_len);
- SvPOK_only(RETVAL);
- SvCUR_set(RETVAL, out_len);
- out_data = (unsigned char *)SvPVX(RETVAL);
- rv = sober128_stream_keystream(&self->state, out_data, (unsigned long)out_len);
- if (rv != CRYPT_OK) {
- SvREFCNT_dec(RETVAL);
- croak("FATAL: sober128_stream_keystream failed: %s", error_to_string(rv));
+ if (out_len == 0) {
+ RETVAL = newSVpvn("", 0);
+ }
+ else {
+ RETVAL = NEWSV(0, out_len); /* avoid zero! */
+ SvPOK_only(RETVAL);
+ SvCUR_set(RETVAL, out_len);
+ out_data = (unsigned char *)SvPVX(RETVAL);
+ rv = sober128_stream_keystream(self, out_data, (unsigned long)out_len);
+ if (rv != CRYPT_OK) {
+ SvREFCNT_dec(RETVAL);
+ croak("FATAL: sober128_stream_keystream failed: %s", error_to_string(rv));
+ }
}
}
OUTPUT:
@@ -79,11 +86,11 @@ crypt(Crypt::Stream::Sober128 self, SV * data)
RETVAL = newSVpvn("", 0);
}
else {
- RETVAL = NEWSV(0, in_data_len);
+ RETVAL = NEWSV(0, in_data_len); /* avoid zero! */
SvPOK_only(RETVAL);
SvCUR_set(RETVAL, in_data_len);
out_data = (unsigned char *)SvPVX(RETVAL);
- rv = sober128_stream_crypt(&self->state, in_data, (unsigned long)in_data_len, out_data);
+ rv = sober128_stream_crypt(self, in_data, (unsigned long)in_data_len, out_data);
if (rv != CRYPT_OK) {
SvREFCNT_dec(RETVAL);
croak("FATAL: sober128_stream_crypt failed: %s", error_to_string(rv));
diff --git a/inc/CryptX_Stream_Sosemanuk.xs.inc b/inc/CryptX_Stream_Sosemanuk.xs.inc
index 2f46859d..da5fcfb5 100644
--- a/inc/CryptX_Stream_Sosemanuk.xs.inc
+++ b/inc/CryptX_Stream_Sosemanuk.xs.inc
@@ -1,5 +1,7 @@
MODULE = CryptX PACKAGE = Crypt::Stream::Sosemanuk
+PROTOTYPES: DISABLE
+
Crypt::Stream::Sosemanuk
new(Class, SV * key, SV * nonce=&PL_sv_undef)
CODE:
@@ -11,10 +13,10 @@ new(Class, SV * key, SV * nonce=&PL_sv_undef)
if (!SvPOK(key)) croak("FATAL: key must be string/buffer scalar");
k = (unsigned char *)SvPVbyte(key, k_len);
- Newz(0, RETVAL, 1, struct sosemanuk_struct);
+ Newz(0, RETVAL, 1, sosemanuk_state);
if (!RETVAL) croak("FATAL: Newz failed");
- rv = sosemanuk_setup(&RETVAL->state, k, (unsigned long)k_len);
+ rv = sosemanuk_setup(RETVAL, k, (unsigned long)k_len);
if (rv != CRYPT_OK) {
Safefree(RETVAL);
croak("FATAL: sosemanuk_setup failed: %s", error_to_string(rv));
@@ -23,10 +25,10 @@ new(Class, SV * key, SV * nonce=&PL_sv_undef)
if (SvOK(nonce)) {
if (!SvPOK(nonce)) croak("FATAL: nonce must be string/buffer scalar");
iv = (unsigned char *)SvPVbyte(nonce, iv_len);
- rv = sosemanuk_setiv(&RETVAL->state, iv, (unsigned long)iv_len);
+ rv = sosemanuk_setiv(RETVAL, iv, (unsigned long)iv_len);
}
else {
- rv = sosemanuk_setiv(&RETVAL->state, NULL, 0);
+ rv = sosemanuk_setiv(RETVAL, NULL, 0);
}
if (rv != CRYPT_OK) {
Safefree(RETVAL);
@@ -40,15 +42,15 @@ new(Class, SV * key, SV * nonce=&PL_sv_undef)
void
DESTROY(Crypt::Stream::Sosemanuk self)
CODE:
- sosemanuk_done(&self->state);
+ sosemanuk_done(self);
Safefree(self);
Crypt::Stream::Sosemanuk
clone(Crypt::Stream::Sosemanuk self)
CODE:
- Newz(0, RETVAL, 1, struct sosemanuk_struct);
+ Newz(0, RETVAL, 1, sosemanuk_state);
if (!RETVAL) croak("FATAL: Newz failed");
- Copy(&self->state, &RETVAL->state, 1, struct sosemanuk_struct);
+ Copy(self, RETVAL, 1, sosemanuk_state);
OUTPUT:
RETVAL
@@ -59,14 +61,19 @@ keystream(Crypt::Stream::Sosemanuk self, STRLEN out_len)
int rv;
unsigned char *out_data;
- RETVAL = NEWSV(0, out_len);
- SvPOK_only(RETVAL);
- SvCUR_set(RETVAL, out_len);
- out_data = (unsigned char *)SvPVX(RETVAL);
- rv = sosemanuk_keystream(&self->state, out_data, (unsigned long)out_len);
- if (rv != CRYPT_OK) {
- SvREFCNT_dec(RETVAL);
- croak("FATAL: sosemanuk_keystream failed: %s", error_to_string(rv));
+ if (out_len == 0) {
+ RETVAL = newSVpvn("", 0);
+ }
+ else {
+ RETVAL = NEWSV(0, out_len); /* avoid zero! */
+ SvPOK_only(RETVAL);
+ SvCUR_set(RETVAL, out_len);
+ out_data = (unsigned char *)SvPVX(RETVAL);
+ rv = sosemanuk_keystream(self, out_data, (unsigned long)out_len);
+ if (rv != CRYPT_OK) {
+ SvREFCNT_dec(RETVAL);
+ croak("FATAL: sosemanuk_keystream failed: %s", error_to_string(rv));
+ }
}
}
OUTPUT:
@@ -85,11 +92,11 @@ crypt(Crypt::Stream::Sosemanuk self, SV * data)
RETVAL = newSVpvn("", 0);
}
else {
- RETVAL = NEWSV(0, in_data_len);
+ RETVAL = NEWSV(0, in_data_len); /* avoid zero! */
SvPOK_only(RETVAL);
SvCUR_set(RETVAL, in_data_len);
out_data = (unsigned char *)SvPVX(RETVAL);
- rv = sosemanuk_crypt(&self->state, in_data, (unsigned long)in_data_len, out_data);
+ rv = sosemanuk_crypt(self, in_data, (unsigned long)in_data_len, out_data);
if (rv != CRYPT_OK) {
SvREFCNT_dec(RETVAL);
croak("FATAL: sosemanuk_crypt failed: %s", error_to_string(rv));
diff --git a/lib/Crypt/AuthEnc.pm b/lib/Crypt/AuthEnc.pm
index 78ce6cb1..359f3244 100644
--- a/lib/Crypt/AuthEnc.pm
+++ b/lib/Crypt/AuthEnc.pm
@@ -2,9 +2,9 @@ package Crypt::AuthEnc;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
-sub CLONE_SKIP { 1 } # prevent cloning
+### not used
1;
diff --git a/lib/Crypt/AuthEnc/CCM.pm b/lib/Crypt/AuthEnc/CCM.pm
index 57b60d02..15673c5d 100644
--- a/lib/Crypt/AuthEnc/CCM.pm
+++ b/lib/Crypt/AuthEnc/CCM.pm
@@ -2,9 +2,9 @@ package Crypt::AuthEnc::CCM;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
-use base qw(Crypt::AuthEnc Exporter);
+require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import';
our %EXPORT_TAGS = ( all => [qw( ccm_encrypt_authenticate ccm_decrypt_verify )] );
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw();
@@ -12,50 +12,8 @@ our @EXPORT = qw();
use Carp;
$Carp::Internal{(__PACKAGE__)}++;
use CryptX;
-use Crypt::Cipher;
-
-sub new {
- my $class = shift;
- local $SIG{__DIE__} = \&CryptX::_croak;
- return _new(Crypt::Cipher::_trans_cipher_name(shift), @_);
-}
-
-sub ccm_encrypt_authenticate {
- my $cipher_name = shift;
- my $key = shift;
- my $iv = shift;
- my $adata = shift;
- my $tag_len = shift;
- my $plaintext = shift;
-
- $iv = "" if !defined $iv;
- $adata = "" if !defined $adata;
- $plaintext = "" if !defined $plaintext;
-
- local $SIG{__DIE__} = \&CryptX::_croak;
- my $m = Crypt::AuthEnc::CCM->new($cipher_name, $key, $iv, $adata, $tag_len, length($plaintext));
- my $ct = $m->encrypt_add($plaintext);
- my $tag = $m->encrypt_done();
- return ($ct, $tag);
-}
-
-sub ccm_decrypt_verify {
- my $cipher_name = shift;
- my $key = shift;
- my $iv = shift;
- my $adata = shift;
- my $ciphertext = shift;
- my $tag = shift;
-
- $iv = "" if !defined $iv;
- $adata = "" if !defined $adata;
- $ciphertext = "" if !defined $ciphertext;
-
- local $SIG{__DIE__} = \&CryptX::_croak;
- my $m = Crypt::AuthEnc::CCM->new($cipher_name, $key, $iv, $adata, length($tag), length($ciphertext));
- my $pt = $m->decrypt_add($ciphertext);
- return $m->decrypt_done($tag) ? $pt : undef;
-}
+
+sub CLONE_SKIP { 1 } # prevent cloning
1;
diff --git a/lib/Crypt/AuthEnc/ChaCha20Poly1305.pm b/lib/Crypt/AuthEnc/ChaCha20Poly1305.pm
index fe351023..104e2422 100644
--- a/lib/Crypt/AuthEnc/ChaCha20Poly1305.pm
+++ b/lib/Crypt/AuthEnc/ChaCha20Poly1305.pm
@@ -2,9 +2,9 @@ package Crypt::AuthEnc::ChaCha20Poly1305;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
-use base qw(Crypt::AuthEnc Exporter);
+require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import';
our %EXPORT_TAGS = ( all => [qw( chacha20poly1305_encrypt_authenticate chacha20poly1305_decrypt_verify )] );
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw();
@@ -13,39 +13,7 @@ use Carp;
$Carp::Internal{(__PACKAGE__)}++;
use CryptX;
-sub new {
- my $class = shift;
- local $SIG{__DIE__} = \&CryptX::_croak;
- return _new(@_);
-}
-
-sub chacha20poly1305_encrypt_authenticate {
- my $key = shift;
- my $iv = shift;
- my $adata = shift;
- my $plaintext = shift;
-
- local $SIG{__DIE__} = \&CryptX::_croak;
- my $m = Crypt::AuthEnc::ChaCha20Poly1305->new($key, $iv);
- $m->adata_add(defined $adata ? $adata : ''); #XXX-TODO if no aad we have to pass empty string
- my $ct = $m->encrypt_add($plaintext);
- my $tag = $m->encrypt_done;
- return ($ct, $tag);
-}
-
-sub chacha20poly1305_decrypt_verify {
- my $key = shift;
- my $iv = shift;
- my $adata = shift;
- my $ciphertext = shift;
- my $tag = shift;
-
- local $SIG{__DIE__} = \&CryptX::_croak;
- my $m = Crypt::AuthEnc::ChaCha20Poly1305->new($key, $iv);
- $m->adata_add(defined $adata ? $adata : ''); #XXX-TODO if no aad we have to pass empty string
- my $ct = $m->decrypt_add($ciphertext);
- return $m->decrypt_done($tag) ? $ct : undef;
-}
+sub CLONE_SKIP { 1 } # prevent cloning
1;
diff --git a/lib/Crypt/AuthEnc/EAX.pm b/lib/Crypt/AuthEnc/EAX.pm
index 88552be3..6aad5b6d 100644
--- a/lib/Crypt/AuthEnc/EAX.pm
+++ b/lib/Crypt/AuthEnc/EAX.pm
@@ -2,9 +2,9 @@ package Crypt::AuthEnc::EAX;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
-use base qw(Crypt::AuthEnc Exporter);
+require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import';
our %EXPORT_TAGS = ( all => [qw( eax_encrypt_authenticate eax_decrypt_verify )] );
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw();
@@ -12,58 +12,13 @@ our @EXPORT = qw();
use Carp;
$Carp::Internal{(__PACKAGE__)}++;
use CryptX;
-use Crypt::Cipher;
-
-### the following methods/functions are implemented in XS:
-# - _new
-# - DESTROY
-# - clone
-# - encrypt_add
-# - encrypt_done
-# - decrypt_add
-# - decrypt_done
-# - adata_add
-
-sub new {
- my $class = shift;
- local $SIG{__DIE__} = \&CryptX::_croak;
- return _new(Crypt::Cipher::_trans_cipher_name(shift), @_);
-}
-
-sub eax_encrypt_authenticate {
- my $cipher_name = shift;
- my $key = shift;
- my $iv = shift;
- my $adata = shift;
- my $plaintext = shift;
-
- local $SIG{__DIE__} = \&CryptX::_croak;
- my $m = Crypt::AuthEnc::EAX->new($cipher_name, $key, $iv);
- $m->adata_add($adata) if defined $adata;
- my $ct = $m->encrypt_add($plaintext);
- my $tag = $m->encrypt_done;
- return ($ct, $tag);
-}
-
-sub eax_decrypt_verify {
- my $cipher_name = shift;
- my $key = shift;
- my $iv = shift;
- my $adata = shift;
- my $ciphertext = shift;
- my $tag = shift;
-
- local $SIG{__DIE__} = \&CryptX::_croak;
- my $m = Crypt::AuthEnc::EAX->new($cipher_name, $key, $iv);
- $m->adata_add($adata) if defined $adata;
- my $ct = $m->decrypt_add($ciphertext);
- return $m->decrypt_done($tag) ? $ct : undef;
-}
# obsolete, only for backwards compatibility
sub header_add { goto &adata_add }
sub aad_add { goto &adata_add }
+sub CLONE_SKIP { 1 } # prevent cloning
+
1;
=pod
diff --git a/lib/Crypt/AuthEnc/GCM.pm b/lib/Crypt/AuthEnc/GCM.pm
index aa7ffba6..ba8ae8ba 100644
--- a/lib/Crypt/AuthEnc/GCM.pm
+++ b/lib/Crypt/AuthEnc/GCM.pm
@@ -2,9 +2,9 @@ package Crypt::AuthEnc::GCM;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
-use base qw(Crypt::AuthEnc Exporter);
+require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import';
our %EXPORT_TAGS = ( all => [qw( gcm_encrypt_authenticate gcm_decrypt_verify )] );
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw();
@@ -12,48 +12,8 @@ our @EXPORT = qw();
use Carp;
$Carp::Internal{(__PACKAGE__)}++;
use CryptX;
-use Crypt::Cipher;
-
-sub new {
- my ($class, $cipher, $key, $iv) = @_;
- local $SIG{__DIE__} = \&CryptX::_croak;
- my $self = _new(Crypt::Cipher::_trans_cipher_name($cipher), $key);
- # for backwards compatibility the $iv is optional
- $self->iv_add($iv) if defined $iv;
- return $self;
-}
-
-sub gcm_encrypt_authenticate {
- my $cipher_name = shift;
- my $key = shift;
- my $iv = shift;
- my $adata = shift;
- my $plaintext = shift;
-
- local $SIG{__DIE__} = \&CryptX::_croak;
- my $m = Crypt::AuthEnc::GCM->new($cipher_name, $key);
- $m->iv_add($iv);
- $m->adata_add(defined $adata ? $adata : ''); #XXX-TODO if no aad we have to pass empty string
- my $ct = $m->encrypt_add($plaintext);
- my $tag = $m->encrypt_done;
- return ($ct, $tag);
-}
-
-sub gcm_decrypt_verify {
- my $cipher_name = shift;
- my $key = shift;
- my $iv = shift;
- my $adata = shift;
- my $ciphertext = shift;
- my $tag = shift;
-
- local $SIG{__DIE__} = \&CryptX::_croak;
- my $m = Crypt::AuthEnc::GCM->new($cipher_name, $key);
- $m->iv_add($iv);
- $m->adata_add(defined $adata ? $adata : ''); #XXX-TODO if no aad we have to pass empty string
- my $ct = $m->decrypt_add($ciphertext);
- return $m->decrypt_done($tag) ? $ct : undef;
-}
+
+sub CLONE_SKIP { 1 } # prevent cloning
1;
diff --git a/lib/Crypt/AuthEnc/OCB.pm b/lib/Crypt/AuthEnc/OCB.pm
index 83f3076f..7f515c9b 100644
--- a/lib/Crypt/AuthEnc/OCB.pm
+++ b/lib/Crypt/AuthEnc/OCB.pm
@@ -2,9 +2,9 @@ package Crypt::AuthEnc::OCB;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
-use base qw(Crypt::AuthEnc Exporter);
+require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import';
our %EXPORT_TAGS = ( all => [qw( ocb_encrypt_authenticate ocb_decrypt_verify )] );
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw();
@@ -12,49 +12,13 @@ our @EXPORT = qw();
use Carp;
$Carp::Internal{(__PACKAGE__)}++;
use CryptX;
-use Crypt::Cipher;
-
-sub new {
- my $class = shift;
- local $SIG{__DIE__} = \&CryptX::_croak;
- return _new(Crypt::Cipher::_trans_cipher_name(shift), @_);
-}
-
-sub ocb_encrypt_authenticate {
- my $cipher_name = shift;
- my $key = shift;
- my $nonce = shift;
- my $adata = shift;
- my $tag_len = shift;
- my $plaintext = shift;
-
- local $SIG{__DIE__} = \&CryptX::_croak;
- my $m = Crypt::AuthEnc::OCB->new($cipher_name, $key, $nonce, $tag_len);
- $m->adata_add($adata) if defined $adata;
- my $ct = $m->encrypt_last($plaintext);
- my $tag = $m->encrypt_done;
- return ($ct, $tag);
-}
-
-sub ocb_decrypt_verify {
- my $cipher_name = shift;
- my $key = shift;
- my $nonce = shift;
- my $adata = shift;
- my $ciphertext = shift;
- my $tag = shift;
-
- local $SIG{__DIE__} = \&CryptX::_croak;
- my $m = Crypt::AuthEnc::OCB->new($cipher_name, $key, $nonce, length($tag));
- $m->adata_add($adata) if defined $adata;
- my $ct = $m->decrypt_last($ciphertext);
- return $m->decrypt_done($tag) ? $ct : undef;
-}
# obsolete, only for backwards compatibility
sub aad_add { goto &adata_add }
sub blocksize { return 16 }
+sub CLONE_SKIP { 1 } # prevent cloning
+
1;
=pod
diff --git a/lib/Crypt/Checksum.pm b/lib/Crypt/Checksum.pm
index 2273afed..8d4d8c9c 100644
--- a/lib/Crypt/Checksum.pm
+++ b/lib/Crypt/Checksum.pm
@@ -2,34 +2,57 @@ package Crypt::Checksum;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import';
-our %EXPORT_TAGS = ( all => [qw/
- adler32_data adler32_data_hex adler32_data_int adler32_file adler32_file_hex adler32_file_int
- crc32_data crc32_data_hex crc32_data_int crc32_file crc32_file_hex crc32_file_int
- /] );
+our %EXPORT_TAGS = ( all => [qw/ adler32_data adler32_data_hex adler32_data_int adler32_file adler32_file_hex adler32_file_int
+ crc32_data crc32_data_hex crc32_data_int crc32_file crc32_file_hex crc32_file_int /] );
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw();
use Carp;
$Carp::Internal{(__PACKAGE__)}++;
-use CryptX;
-use Crypt::Checksum::Adler32;
-use Crypt::Checksum::CRC32;
-sub adler32_data { local $SIG{__DIE__} = \&CryptX::_croak; Crypt::Checksum::Adler32->new->add(@_)->digest }
-sub adler32_data_hex { local $SIG{__DIE__} = \&CryptX::_croak; Crypt::Checksum::Adler32->new->add(@_)->hexdigest }
-sub adler32_data_int { local $SIG{__DIE__} = \&CryptX::_croak; unpack("N", Crypt::Checksum::Adler32->new->add(@_)->digest) }
-sub adler32_file { local $SIG{__DIE__} = \&CryptX::_croak; Crypt::Checksum::Adler32->new->addfile(@_)->digest }
-sub adler32_file_hex { local $SIG{__DIE__} = \&CryptX::_croak; Crypt::Checksum::Adler32->new->addfile(@_)->hexdigest }
-sub adler32_file_int { local $SIG{__DIE__} = \&CryptX::_croak; unpack("N", Crypt::Checksum::Adler32->new->addfile(@_)->digest) }
-sub crc32_data { local $SIG{__DIE__} = \&CryptX::_croak; Crypt::Checksum::CRC32->new->add(@_)->digest }
-sub crc32_data_hex { local $SIG{__DIE__} = \&CryptX::_croak; Crypt::Checksum::CRC32->new->add(@_)->hexdigest }
-sub crc32_data_int { local $SIG{__DIE__} = \&CryptX::_croak; unpack("N", Crypt::Checksum::CRC32->new->add(@_)->digest) }
-sub crc32_file { local $SIG{__DIE__} = \&CryptX::_croak; Crypt::Checksum::CRC32->new->addfile(@_)->digest }
-sub crc32_file_hex { local $SIG{__DIE__} = \&CryptX::_croak; Crypt::Checksum::CRC32->new->addfile(@_)->hexdigest }
-sub crc32_file_int { local $SIG{__DIE__} = \&CryptX::_croak; unpack("N", Crypt::Checksum::CRC32->new->addfile(@_)->digest) }
+# obsolete since v0.057, only for backwards compatibility
+use Crypt::Checksum::CRC32;
+use Crypt::Checksum::Adler32;
+sub adler32_data { goto \&Crypt::Checksum::Adler32::adler32_data }
+sub adler32_data_hex { goto \&Crypt::Checksum::Adler32::adler32_data_hex }
+sub adler32_data_int { goto \&Crypt::Checksum::Adler32::adler32_data_int }
+sub adler32_file { goto \&Crypt::Checksum::Adler32::adler32_file }
+sub adler32_file_hex { goto \&Crypt::Checksum::Adler32::adler32_file_hex }
+sub adler32_file_int { goto \&Crypt::Checksum::Adler32::adler32_file_int }
+sub crc32_data { goto \&Crypt::Checksum::CRC32::crc32_data }
+sub crc32_data_hex { goto \&Crypt::Checksum::CRC32::crc32_data_hex }
+sub crc32_data_int { goto \&Crypt::Checksum::CRC32::crc32_data_int }
+sub crc32_file { goto \&Crypt::Checksum::CRC32::crc32_file }
+sub crc32_file_hex { goto \&Crypt::Checksum::CRC32::crc32_file_hex }
+sub crc32_file_int { goto \&Crypt::Checksum::CRC32::crc32_file_int }
+
+sub addfile {
+ my ($self, $file) = @_;
+
+ my $handle;
+ if (ref(\$file) eq 'SCALAR') { #filename
+ open($handle, "<", $file) || croak "FATAL: cannot open '$file': $!";
+ binmode($handle);
+ }
+ else { #handle
+ $handle = $file
+ }
+ croak "FATAL: invalid handle" unless defined $handle;
+
+ my $n;
+ my $buf = "";
+ while (($n = read($handle, $buf, 32*1024))) {
+ $self->add($buf)
+ }
+ croak "FATAL: read failed: $!" unless defined $n;
+
+ return $self;
+}
+
+sub CLONE_SKIP { 1 } # prevent cloning
1;
@@ -37,163 +60,10 @@ sub crc32_file_int { local $SIG{__DIE__} = \&CryptX::_croak; unpack("N", Cr
=head1 NAME
-Crypt::Checksum - functional interface to CRC32 and Adler32 checksums
-
-=head1 SYNOPSIS
-
- use Crypt::Checksum ':all';
-
- # calculate Adler32 checksum from string/buffer
- $checksum_raw = adler32_data($data);
- $checksum_hex = adler32_data_hex($data);
-
- # calculate Adler32 checksum from file
- $checksum_raw = adler32_file('filename.dat');
- $checksum_hex = adler32_file_hex('filename.dat');
-
- # calculate Adler32 checksum from filehandle
- $checksum_raw = adler32_file(*FILEHANDLE);
- $checksum_hex = adler32_file_hex(*FILEHANDLE);
-
- # calculate CRC32 checksum from string/buffer
- $checksum_raw = crc32_data($data);
- $checksum_hex = crc32_data_hex($data);
-
- # calculate CRC32 checksum from file
- $checksum_raw = crc32_file('filename.dat');
- $checksum_hex = crc32_file_hex('filename.dat');
-
- # calculate CRC32 checksum from filehandle
- $checksum_raw = crc32_file(*FILEHANDLE);
- $checksum_hex = crc32_file_hex(*FILEHANDLE);
+Crypt::Checksum - [internal only]
=head1 DESCRIPTION
-Calculating CRC32 and Adler32 checksums (functional interface);
-
-I<Since: CryptX-0.032>
-
-=head1 EXPORT
-
-Nothing is exported by default.
-
-You can export selected functions:
-
- use Crypt::Checksum qw( adler32_data adler32_data_hex adler32_file adler32_file_hex
- crc32_data crc32_data_hex crc32_file crc32_file_hex );
-
-Or all of them at once:
-
- use Crypt::Checksum ':all';
-
-=head1 FUNCTIONS
-
-=head2 adler32_data
-
-Returns checksum as raw octects.
-
- $checksum_raw = adler32_data('data string');
- #or
- $checksum_raw = adler32_data('any data', 'more data', 'even more data');
-
-=head2 adler32_data_hex
-
-Returns checksum as a hexadecimal string.
-
- $checksum_hex = adler32_data_hex('data string');
- #or
- $checksum_hex = adler32_data_hex('any data', 'more data', 'even more data');
-
-=head2 adler32_data_int
-
-Returns checksum as unsigned 32bit integer.
-
- $checksum_hex = adler32_data_int('data string');
- #or
- $checksum_hex = adler32_data_int('any data', 'more data', 'even more data');
-
-=head2 adler32_file
-
-Returns checksum as raw octects.
-
- $checksum_raw = adler32_file('filename.dat');
- #or
- $checksum_raw = adler32_file(*FILEHANDLE);
-
-=head2 adler32_file_hex
-
-Returns checksum as a hexadecimal string.
-
- $checksum_hex = adler32_file_hex('filename.dat');
- #or
- $checksum_hex = adler32_file_hex(*FILEHANDLE);
-
-=head2 adler32_file_int
-
-Returns checksum as unsigned 32bit integer.
-
- $checksum_hex = adler32_file_int('filename.dat');
- #or
- $checksum_hex = adler32_file_int(*FILEHANDLE);
-
-=head2 crc32_data
-
-Returns checksum as raw octects.
-
- $checksum_raw = crc32_data('data string');
- #or
- $checksum_raw = crc32_data('any data', 'more data', 'even more data');
-
-=head2 crc32_data_hex
-
-Returns checksum as a hexadecimal string.
-
- $checksum_hex = crc32_data_hex('data string');
- #or
- $checksum_hex = crc32_data_hex('any data', 'more data', 'even more data');
-
-=head2 crc32_data_int
-
-Returns checksum as unsigned 32bit integer.
-
- $checksum_hex = crc32_data_int('data string');
- #or
- $checksum_hex = crc32_data_int('any data', 'more data', 'even more data');
-
-=head2 crc32_file
-
-Returns checksum as raw octects.
-
- $checksum_raw = crc32_file('filename.dat');
- #or
- $checksum_raw = crc32_file(*FILEHANDLE);
-
-=head2 crc32_file_hex
-
-Returns checksum as a hexadecimal string.
-
- $checksum_hex = crc32_file_hex('filename.dat');
- #or
- $checksum_hex = crc32_file_hex(*FILEHANDLE);
-
-=head2 crc32_file_int
-
-Returns checksum as unsigned 32bit integer.
-
- $checksum_hex = crc32_file_int('filename.dat');
- #or
- $checksum_hex = crc32_file_int(*FILEHANDLE);
-
-=head1 SEE ALSO
-
-=over
-
-=item * L<CryptX|CryptX>, L<Crypt::Checksum::Adler32>, L<Crypt::Checksum::CRC32>
-
-=item * L<https://en.wikipedia.org/wiki/Adler-32>
-
-=item * L<https://en.wikipedia.org/wiki/Cyclic_redundancy_check>
-
-=back
+You are probably looking for L<Crypt::Checksum::CRC32> or L<Crypt::Checksum::Adler32>.
=cut
diff --git a/lib/Crypt/Checksum/Adler32.pm b/lib/Crypt/Checksum/Adler32.pm
index dd2a4952..767d3e30 100644
--- a/lib/Crypt/Checksum/Adler32.pm
+++ b/lib/Crypt/Checksum/Adler32.pm
@@ -2,36 +2,20 @@ package Crypt::Checksum::Adler32;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
+
+use base qw(Crypt::Checksum Exporter);
+our %EXPORT_TAGS = ( all => [qw( adler32_data adler32_data_hex adler32_data_int adler32_file adler32_file_hex adler32_file_int )] );
+our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
+our @EXPORT = qw();
use Carp;
$Carp::Internal{(__PACKAGE__)}++;
use CryptX;
-sub addfile {
- my ($self, $file) = @_;
-
- my $handle;
- if (ref(\$file) eq 'SCALAR') { #filename
- open($handle, "<", $file) || croak "FATAL: cannot open '$file': $!";
- binmode($handle);
- }
- else { #handle
- $handle = $file
- }
- croak "FATAL: invalid handle" unless defined $handle;
-
- my $n;
- my $buf = "";
- while (($n = read($handle, $buf, 32*1024))) {
- $self->add($buf)
- }
- croak "FATAL: read failed: $!" unless defined $n;
-
- return $self;
-}
-
-sub CLONE_SKIP { 1 } # prevent cloning
+sub adler32_file { local $SIG{__DIE__} = \&CryptX::_croak; Crypt::Checksum::Adler32->new->addfile(@_)->digest }
+sub adler32_file_hex { local $SIG{__DIE__} = \&CryptX::_croak; Crypt::Checksum::Adler32->new->addfile(@_)->hexdigest }
+sub adler32_file_int { local $SIG{__DIE__} = \&CryptX::_croak; Crypt::Checksum::Adler32->new->addfile(@_)->intdigest }
1;
@@ -43,20 +27,101 @@ Crypt::Checksum::Adler32 - Compute Adler32 checksum
=head1 SYNOPSIS
+ ### Functional interface:
+ use Crypt::Checksum::Adler32 ':all';
+
+ # calculate Adler32 checksum from string/buffer
+ $checksum_raw = adler32_data($data);
+ $checksum_hex = adler32_data_hex($data);
+ $checksum_int = adler32_data_int($data);
+ # calculate Adler32 checksum from file
+ $checksum_raw = adler32_file('filename.dat');
+ $checksum_hex = adler32_file_hex('filename.dat');
+ $checksum_int = adler32_file_int('filename.dat');
+ # calculate Adler32 checksum from filehandle
+ $checksum_raw = adler32_file(*FILEHANDLE);
+ $checksum_hex = adler32_file_hex(*FILEHANDLE);
+ $checksum_int = adler32_file_int(*FILEHANDLE);
+
+ ### OO interface:
use Crypt::Checksum::Adler32;
$d = Crypt::Checksum::Adler32->new;
$d->add('any data');
+ $d->add('another data');
$d->addfile('filename.dat');
$d->addfile(*FILEHANDLE);
- $checksum_raw = $d->digest; # raw bytes
+ $checksum_raw = $d->digest; # raw 4 bytes
$checksum_hex = $d->hexdigest; # hexadecimal form
+ $checksum_int = $d->intdigest; # 32bit unsigned integer
=head1 DESCRIPTION
-Calculating Adler32 checksums (OO interface);
+Calculating Adler32 checksums.
+
+I<Updated: v0.057>
+
+=head1 EXPORT
+
+Nothing is exported by default.
+
+You can export selected functions:
+
+ use Crypt::Checksum::Adler32 qw(adler32_data adler32_data_hex adler32_data_int adler32_file adler32_file_hex adler32_file_int);
-I<Since: CryptX-0.032>
+Or all of them at once:
+
+ use Crypt::Checksum::Adler32 ':all';
+
+=head1 FUNCTIONS
+
+=head2 adler32_data
+
+Returns checksum as raw octects.
+
+ $checksum_raw = adler32_data('data string');
+ #or
+ $checksum_raw = adler32_data('any data', 'more data', 'even more data');
+
+=head2 adler32_data_hex
+
+Returns checksum as a hexadecimal string.
+
+ $checksum_hex = adler32_data_hex('data string');
+ #or
+ $checksum_hex = adler32_data_hex('any data', 'more data', 'even more data');
+
+=head2 adler32_data_int
+
+Returns checksum as unsigned 32bit integer.
+
+ $checksum_int = adler32_data_int('data string');
+ #or
+ $checksum_int = adler32_data_int('any data', 'more data', 'even more data');
+
+=head2 adler32_file
+
+Returns checksum as raw octects.
+
+ $checksum_raw = adler32_file('filename.dat');
+ #or
+ $checksum_raw = adler32_file(*FILEHANDLE);
+
+=head2 adler32_file_hex
+
+Returns checksum as a hexadecimal string.
+
+ $checksum_hex = adler32_file_hex('filename.dat');
+ #or
+ $checksum_hex = adler32_file_hex(*FILEHANDLE);
+
+=head2 adler32_file_int
+
+Returns checksum as unsigned 32bit integer.
+
+ $checksum_int = adler32_file_int('filename.dat');
+ #or
+ $checksum_int = adler32_file_int(*FILEHANDLE);
=head1 METHODS
@@ -110,11 +175,17 @@ Returns the checksum encoded as a hexadecimal string.
$result_hex = $d->hexdigest();
+=head2 intdigest
+
+Returns the checksum encoded as unsigned 32bit integer.
+
+ $result_int = $d->intdigest();
+
=head1 SEE ALSO
=over
-=item * L<CryptX|CryptX>, L<Crypt::Checksum>
+=item * L<CryptX|CryptX>
=item * L<https://en.wikipedia.org/wiki/Adler-32>
diff --git a/lib/Crypt/Checksum/CRC32.pm b/lib/Crypt/Checksum/CRC32.pm
index fc7f56a3..690ba6a7 100644
--- a/lib/Crypt/Checksum/CRC32.pm
+++ b/lib/Crypt/Checksum/CRC32.pm
@@ -2,36 +2,20 @@ package Crypt::Checksum::CRC32;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
+
+use base qw(Crypt::Checksum Exporter);
+our %EXPORT_TAGS = ( all => [qw( crc32_data crc32_data_hex crc32_data_int crc32_file crc32_file_hex crc32_file_int )] );
+our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
+our @EXPORT = qw();
use Carp;
$Carp::Internal{(__PACKAGE__)}++;
use CryptX;
-sub addfile {
- my ($self, $file) = @_;
-
- my $handle;
- if (ref(\$file) eq 'SCALAR') { #filename
- open($handle, "<", $file) || croak "FATAL: cannot open '$file': $!";
- binmode($handle);
- }
- else { #handle
- $handle = $file
- }
- croak "FATAL: invalid handle" unless defined $handle;
-
- my $n;
- my $buf = "";
- while (($n = read($handle, $buf, 32*1024))) {
- $self->add($buf)
- }
- croak "FATAL: read failed: $!" unless defined $n;
-
- return $self;
-}
-
-sub CLONE_SKIP { 1 } # prevent cloning
+sub crc32_file { local $SIG{__DIE__} = \&CryptX::_croak; Crypt::Checksum::CRC32->new->addfile(@_)->digest }
+sub crc32_file_hex { local $SIG{__DIE__} = \&CryptX::_croak; Crypt::Checksum::CRC32->new->addfile(@_)->hexdigest }
+sub crc32_file_int { local $SIG{__DIE__} = \&CryptX::_croak; Crypt::Checksum::CRC32->new->addfile(@_)->intdigest }
1;
@@ -43,20 +27,101 @@ Crypt::Checksum::CRC32 - Compute CRC32 checksum
=head1 SYNOPSIS
+ ### Functional interface:
+ use Crypt::Checksum::CRC32 ':all';
+
+ # calculate CRC32 checksum from string/buffer
+ $checksum_raw = crc32_data($data);
+ $checksum_hex = crc32_data_hex($data);
+ $checksum_int = crc32_data_int($data);
+ # calculate CRC32 checksum from file
+ $checksum_raw = crc32_file('filename.dat');
+ $checksum_hex = crc32_file_hex('filename.dat');
+ $checksum_int = crc32_file_int('filename.dat');
+ # calculate CRC32 checksum from filehandle
+ $checksum_raw = crc32_file(*FILEHANDLE);
+ $checksum_hex = crc32_file_hex(*FILEHANDLE);
+ $checksum_int = crc32_file_int(*FILEHANDLE);
+
+ ### OO interface:
use Crypt::Checksum::CRC32;
$d = Crypt::Checksum::CRC32->new;
$d->add('any data');
+ $d->add('another data');
$d->addfile('filename.dat');
$d->addfile(*FILEHANDLE);
- $checksum_raw = $d->digest; # raw bytes
+ $checksum_raw = $d->digest; # raw 4 bytes
$checksum_hex = $d->hexdigest; # hexadecimal form
+ $checksum_int = $d->intdigest; # 32bit unsigned integer
=head1 DESCRIPTION
-Calculating CRC32 checksums (OO interface);
+Calculating CRC32 checksums.
+
+I<Updated: v0.057>
+
+=head1 EXPORT
+
+Nothing is exported by default.
+
+You can export selected functions:
+
+ use Crypt::Checksum::CRC32 qw(crc32_data crc32_data_hex crc32_data_int crc32_file crc32_file_hex crc32_file_int);
-I<Since: CryptX-0.032>
+Or all of them at once:
+
+ use Crypt::Checksum::CRC32 ':all';
+
+=head1 FUNCTIONS
+
+=head2 crc32_data
+
+Returns checksum as raw octects.
+
+ $checksum_raw = crc32_data('data string');
+ #or
+ $checksum_raw = crc32_data('any data', 'more data', 'even more data');
+
+=head2 crc32_data_hex
+
+Returns checksum as a hexadecimal string.
+
+ $checksum_hex = crc32_data_hex('data string');
+ #or
+ $checksum_hex = crc32_data_hex('any data', 'more data', 'even more data');
+
+=head2 crc32_data_int
+
+Returns checksum as unsigned 32bit integer.
+
+ $checksum_int = crc32_data_int('data string');
+ #or
+ $checksum_int = crc32_data_int('any data', 'more data', 'even more data');
+
+=head2 crc32_file
+
+Returns checksum as raw octects.
+
+ $checksum_raw = crc32_file('filename.dat');
+ #or
+ $checksum_raw = crc32_file(*FILEHANDLE);
+
+=head2 crc32_file_hex
+
+Returns checksum as a hexadecimal string.
+
+ $checksum_hex = crc32_file_hex('filename.dat');
+ #or
+ $checksum_hex = crc32_file_hex(*FILEHANDLE);
+
+=head2 crc32_file_int
+
+Returns checksum as unsigned 32bit integer.
+
+ $checksum_int = crc32_file_int('filename.dat');
+ #or
+ $checksum_int = crc32_file_int(*FILEHANDLE);
=head1 METHODS
@@ -110,11 +175,17 @@ Returns the checksum encoded as a hexadecimal string.
$result_hex = $d->hexdigest();
+=head2 intdigest
+
+Returns the checksum encoded as unsigned 32bit integer.
+
+ $result_int = $d->intdigest();
+
=head1 SEE ALSO
=over
-=item * L<CryptX|CryptX>, L<Crypt::Checksum>
+=item * L<CryptX|CryptX>
=item * L<https://en.wikipedia.org/wiki/Cyclic_redundancy_check>
diff --git a/lib/Crypt/Cipher.pm b/lib/Crypt/Cipher.pm
index 609c32a6..a2179364 100644
--- a/lib/Crypt/Cipher.pm
+++ b/lib/Crypt/Cipher.pm
@@ -2,91 +2,23 @@ package Crypt::Cipher;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use Carp;
$Carp::Internal{(__PACKAGE__)}++;
use CryptX;
### the following methods/functions are implemented in XS:
-# - _new
+# - new
# - DESTROY
-# - _keysize
-# - _max_keysize
-# - _min_keysize
-# - _blocksize
-# - _default_rounds
-# - encrypt
+# - blocksize
# - decrypt
-#functions, not methods:
-# - _block_length_by_name
-# - _min_key_length_by_name
-# - _max_key_length_by_name
-# - _default_rounds_by_name
-
-sub _trans_cipher_name {
- my $name = shift || "";
- my %trans = (
- DES_EDE => '3des',
- SAFERP => 'safer+',
- SAFER_K128 => 'safer-k128',
- SAFER_K64 => 'safer-k64',
- SAFER_SK128 => 'safer-sk128',
- SAFER_SK64 => 'safer-sk64',
- );
- $name =~ s/^Crypt::Cipher:://;
- return $trans{uc($name)} if defined $trans{uc($name)};
- return lc($name);
-}
-
-### METHODS
-
-sub new {
- my $pkg = shift;
- my $cipher_name = $pkg eq __PACKAGE__ ? _trans_cipher_name(shift) : _trans_cipher_name($pkg);
- local $SIG{__DIE__} = \&CryptX::_croak;
- return _new($cipher_name, @_);
-}
-
-sub blocksize {
- my $self = shift;
- return $self->_blocksize if ref($self);
- $self = _trans_cipher_name(shift) if $self eq __PACKAGE__;
- local $SIG{__DIE__} = \&CryptX::_croak;
- return _block_length_by_name(_trans_cipher_name($self));
-}
-
-sub max_keysize
-{
- my $self = shift;
- return unless defined $self;
- return $self->_max_keysize if ref($self);
- $self = _trans_cipher_name(shift) if $self eq __PACKAGE__;
- local $SIG{__DIE__} = \&CryptX::_croak;
- return _max_key_length_by_name(_trans_cipher_name($self));
-}
-
-sub min_keysize {
- my $self = shift;
- return unless defined $self;
- return $self->_min_keysize if ref($self);
- $self = _trans_cipher_name(shift) if $self eq __PACKAGE__;
- local $SIG{__DIE__} = \&CryptX::_croak;
- return _min_key_length_by_name(_trans_cipher_name($self));
-}
-
-sub keysize {
- goto &max_keysize;
-}
-
-sub default_rounds {
- my $self = shift;
- return unless defined $self;
- return $self->_default_rounds if ref($self);
- $self = _trans_cipher_name(shift) if $self eq __PACKAGE__;
- local $SIG{__DIE__} = \&CryptX::_croak;
- return _default_rounds_by_name(_trans_cipher_name($self));
-}
+# - default_rounds
+# - encrypt
+# - max_keysize
+# - min_keysize
+
+sub keysize { goto \&max_keysize; } # for Crypt::CBC compatibility
sub CLONE_SKIP { 1 } # prevent cloning
diff --git a/lib/Crypt/Cipher/AES.pm b/lib/Crypt/Cipher/AES.pm
index 870c5c15..d5c894fc 100644
--- a/lib/Crypt/Cipher/AES.pm
+++ b/lib/Crypt/Cipher/AES.pm
@@ -4,16 +4,15 @@ package Crypt::Cipher::AES;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
-use CryptX;
-use base 'Crypt::Cipher';
+use base qw(Crypt::Cipher);
-sub blocksize { Crypt::Cipher::blocksize(__PACKAGE__) }
-sub keysize { Crypt::Cipher::keysize(__PACKAGE__) }
-sub max_keysize { Crypt::Cipher::max_keysize(__PACKAGE__) }
-sub min_keysize { Crypt::Cipher::min_keysize(__PACKAGE__) }
-sub default_rounds { Crypt::Cipher::default_rounds(__PACKAGE__) }
+sub blocksize { Crypt::Cipher::blocksize('AES') }
+sub keysize { Crypt::Cipher::keysize('AES') }
+sub max_keysize { Crypt::Cipher::max_keysize('AES') }
+sub min_keysize { Crypt::Cipher::min_keysize('AES') }
+sub default_rounds { Crypt::Cipher::default_rounds('AES') }
1;
diff --git a/lib/Crypt/Cipher/Anubis.pm b/lib/Crypt/Cipher/Anubis.pm
index 61ca00f3..8156c69a 100644
--- a/lib/Crypt/Cipher/Anubis.pm
+++ b/lib/Crypt/Cipher/Anubis.pm
@@ -4,16 +4,15 @@ package Crypt::Cipher::Anubis;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
-use CryptX;
-use base 'Crypt::Cipher';
+use base qw(Crypt::Cipher);
-sub blocksize { Crypt::Cipher::blocksize(__PACKAGE__) }
-sub keysize { Crypt::Cipher::keysize(__PACKAGE__) }
-sub max_keysize { Crypt::Cipher::max_keysize(__PACKAGE__) }
-sub min_keysize { Crypt::Cipher::min_keysize(__PACKAGE__) }
-sub default_rounds { Crypt::Cipher::default_rounds(__PACKAGE__) }
+sub blocksize { Crypt::Cipher::blocksize('Anubis') }
+sub keysize { Crypt::Cipher::keysize('Anubis') }
+sub max_keysize { Crypt::Cipher::max_keysize('Anubis') }
+sub min_keysize { Crypt::Cipher::min_keysize('Anubis') }
+sub default_rounds { Crypt::Cipher::default_rounds('Anubis') }
1;
diff --git a/lib/Crypt/Cipher/Blowfish.pm b/lib/Crypt/Cipher/Blowfish.pm
index 279cc6cb..a17dee47 100644
--- a/lib/Crypt/Cipher/Blowfish.pm
+++ b/lib/Crypt/Cipher/Blowfish.pm
@@ -4,16 +4,15 @@ package Crypt::Cipher::Blowfish;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
-use CryptX;
-use base 'Crypt::Cipher';
+use base qw(Crypt::Cipher);
-sub blocksize { Crypt::Cipher::blocksize(__PACKAGE__) }
-sub keysize { Crypt::Cipher::keysize(__PACKAGE__) }
-sub max_keysize { Crypt::Cipher::max_keysize(__PACKAGE__) }
-sub min_keysize { Crypt::Cipher::min_keysize(__PACKAGE__) }
-sub default_rounds { Crypt::Cipher::default_rounds(__PACKAGE__) }
+sub blocksize { Crypt::Cipher::blocksize('Blowfish') }
+sub keysize { Crypt::Cipher::keysize('Blowfish') }
+sub max_keysize { Crypt::Cipher::max_keysize('Blowfish') }
+sub min_keysize { Crypt::Cipher::min_keysize('Blowfish') }
+sub default_rounds { Crypt::Cipher::default_rounds('Blowfish') }
1;
diff --git a/lib/Crypt/Cipher/CAST5.pm b/lib/Crypt/Cipher/CAST5.pm
index edc17834..b7f14fe9 100644
--- a/lib/Crypt/Cipher/CAST5.pm
+++ b/lib/Crypt/Cipher/CAST5.pm
@@ -4,16 +4,15 @@ package Crypt::Cipher::CAST5;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
-use CryptX;
-use base 'Crypt::Cipher';
+use base qw(Crypt::Cipher);
-sub blocksize { Crypt::Cipher::blocksize(__PACKAGE__) }
-sub keysize { Crypt::Cipher::keysize(__PACKAGE__) }
-sub max_keysize { Crypt::Cipher::max_keysize(__PACKAGE__) }
-sub min_keysize { Crypt::Cipher::min_keysize(__PACKAGE__) }
-sub default_rounds { Crypt::Cipher::default_rounds(__PACKAGE__) }
+sub blocksize { Crypt::Cipher::blocksize('CAST5') }
+sub keysize { Crypt::Cipher::keysize('CAST5') }
+sub max_keysize { Crypt::Cipher::max_keysize('CAST5') }
+sub min_keysize { Crypt::Cipher::min_keysize('CAST5') }
+sub default_rounds { Crypt::Cipher::default_rounds('CAST5') }
1;
diff --git a/lib/Crypt/Cipher/Camellia.pm b/lib/Crypt/Cipher/Camellia.pm
index c83daa47..1dde5412 100644
--- a/lib/Crypt/Cipher/Camellia.pm
+++ b/lib/Crypt/Cipher/Camellia.pm
@@ -4,16 +4,15 @@ package Crypt::Cipher::Camellia;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
-use CryptX;
-use base 'Crypt::Cipher';
+use base qw(Crypt::Cipher);
-sub blocksize { Crypt::Cipher::blocksize(__PACKAGE__) }
-sub keysize { Crypt::Cipher::keysize(__PACKAGE__) }
-sub max_keysize { Crypt::Cipher::max_keysize(__PACKAGE__) }
-sub min_keysize { Crypt::Cipher::min_keysize(__PACKAGE__) }
-sub default_rounds { Crypt::Cipher::default_rounds(__PACKAGE__) }
+sub blocksize { Crypt::Cipher::blocksize('Camellia') }
+sub keysize { Crypt::Cipher::keysize('Camellia') }
+sub max_keysize { Crypt::Cipher::max_keysize('Camellia') }
+sub min_keysize { Crypt::Cipher::min_keysize('Camellia') }
+sub default_rounds { Crypt::Cipher::default_rounds('Camellia') }
1;
diff --git a/lib/Crypt/Cipher/DES.pm b/lib/Crypt/Cipher/DES.pm
index 389fb5c3..1e28dfbe 100644
--- a/lib/Crypt/Cipher/DES.pm
+++ b/lib/Crypt/Cipher/DES.pm
@@ -4,16 +4,15 @@ package Crypt::Cipher::DES;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
-use CryptX;
-use base 'Crypt::Cipher';
+use base qw(Crypt::Cipher);
-sub blocksize { Crypt::Cipher::blocksize(__PACKAGE__) }
-sub keysize { Crypt::Cipher::keysize(__PACKAGE__) }
-sub max_keysize { Crypt::Cipher::max_keysize(__PACKAGE__) }
-sub min_keysize { Crypt::Cipher::min_keysize(__PACKAGE__) }
-sub default_rounds { Crypt::Cipher::default_rounds(__PACKAGE__) }
+sub blocksize { Crypt::Cipher::blocksize('DES') }
+sub keysize { Crypt::Cipher::keysize('DES') }
+sub max_keysize { Crypt::Cipher::max_keysize('DES') }
+sub min_keysize { Crypt::Cipher::min_keysize('DES') }
+sub default_rounds { Crypt::Cipher::default_rounds('DES') }
1;
diff --git a/lib/Crypt/Cipher/DES_EDE.pm b/lib/Crypt/Cipher/DES_EDE.pm
index 83501c70..d100e44c 100644
--- a/lib/Crypt/Cipher/DES_EDE.pm
+++ b/lib/Crypt/Cipher/DES_EDE.pm
@@ -4,16 +4,15 @@ package Crypt::Cipher::DES_EDE;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
-use CryptX;
-use base 'Crypt::Cipher';
+use base qw(Crypt::Cipher);
-sub blocksize { Crypt::Cipher::blocksize(__PACKAGE__) }
-sub keysize { Crypt::Cipher::keysize(__PACKAGE__) }
-sub max_keysize { Crypt::Cipher::max_keysize(__PACKAGE__) }
-sub min_keysize { Crypt::Cipher::min_keysize(__PACKAGE__) }
-sub default_rounds { Crypt::Cipher::default_rounds(__PACKAGE__) }
+sub blocksize { Crypt::Cipher::blocksize('DES_EDE') }
+sub keysize { Crypt::Cipher::keysize('DES_EDE') }
+sub max_keysize { Crypt::Cipher::max_keysize('DES_EDE') }
+sub min_keysize { Crypt::Cipher::min_keysize('DES_EDE') }
+sub default_rounds { Crypt::Cipher::default_rounds('DES_EDE') }
1;
diff --git a/lib/Crypt/Cipher/IDEA.pm b/lib/Crypt/Cipher/IDEA.pm
index 9d78e930..2c1226f3 100644
--- a/lib/Crypt/Cipher/IDEA.pm
+++ b/lib/Crypt/Cipher/IDEA.pm
@@ -4,16 +4,15 @@ package Crypt::Cipher::IDEA;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
-use CryptX;
-use base 'Crypt::Cipher';
+use base qw(Crypt::Cipher);
-sub blocksize { Crypt::Cipher::blocksize(__PACKAGE__) }
-sub keysize { Crypt::Cipher::keysize(__PACKAGE__) }
-sub max_keysize { Crypt::Cipher::max_keysize(__PACKAGE__) }
-sub min_keysize { Crypt::Cipher::min_keysize(__PACKAGE__) }
-sub default_rounds { Crypt::Cipher::default_rounds(__PACKAGE__) }
+sub blocksize { Crypt::Cipher::blocksize('IDEA') }
+sub keysize { Crypt::Cipher::keysize('IDEA') }
+sub max_keysize { Crypt::Cipher::max_keysize('IDEA') }
+sub min_keysize { Crypt::Cipher::min_keysize('IDEA') }
+sub default_rounds { Crypt::Cipher::default_rounds('IDEA') }
1;
diff --git a/lib/Crypt/Cipher/KASUMI.pm b/lib/Crypt/Cipher/KASUMI.pm
index c8e0f9d8..dd4c6dba 100644
--- a/lib/Crypt/Cipher/KASUMI.pm
+++ b/lib/Crypt/Cipher/KASUMI.pm
@@ -4,16 +4,15 @@ package Crypt::Cipher::KASUMI;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
-use CryptX;
-use base 'Crypt::Cipher';
+use base qw(Crypt::Cipher);
-sub blocksize { Crypt::Cipher::blocksize(__PACKAGE__) }
-sub keysize { Crypt::Cipher::keysize(__PACKAGE__) }
-sub max_keysize { Crypt::Cipher::max_keysize(__PACKAGE__) }
-sub min_keysize { Crypt::Cipher::min_keysize(__PACKAGE__) }
-sub default_rounds { Crypt::Cipher::default_rounds(__PACKAGE__) }
+sub blocksize { Crypt::Cipher::blocksize('KASUMI') }
+sub keysize { Crypt::Cipher::keysize('KASUMI') }
+sub max_keysize { Crypt::Cipher::max_keysize('KASUMI') }
+sub min_keysize { Crypt::Cipher::min_keysize('KASUMI') }
+sub default_rounds { Crypt::Cipher::default_rounds('KASUMI') }
1;
diff --git a/lib/Crypt/Cipher/Khazad.pm b/lib/Crypt/Cipher/Khazad.pm
index 1b5626b1..501235b0 100644
--- a/lib/Crypt/Cipher/Khazad.pm
+++ b/lib/Crypt/Cipher/Khazad.pm
@@ -4,16 +4,15 @@ package Crypt::Cipher::Khazad;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
-use CryptX;
-use base 'Crypt::Cipher';
+use base qw(Crypt::Cipher);
-sub blocksize { Crypt::Cipher::blocksize(__PACKAGE__) }
-sub keysize { Crypt::Cipher::keysize(__PACKAGE__) }
-sub max_keysize { Crypt::Cipher::max_keysize(__PACKAGE__) }
-sub min_keysize { Crypt::Cipher::min_keysize(__PACKAGE__) }
-sub default_rounds { Crypt::Cipher::default_rounds(__PACKAGE__) }
+sub blocksize { Crypt::Cipher::blocksize('Khazad') }
+sub keysize { Crypt::Cipher::keysize('Khazad') }
+sub max_keysize { Crypt::Cipher::max_keysize('Khazad') }
+sub min_keysize { Crypt::Cipher::min_keysize('Khazad') }
+sub default_rounds { Crypt::Cipher::default_rounds('Khazad') }
1;
diff --git a/lib/Crypt/Cipher/MULTI2.pm b/lib/Crypt/Cipher/MULTI2.pm
index ebb66f8f..7b588aae 100644
--- a/lib/Crypt/Cipher/MULTI2.pm
+++ b/lib/Crypt/Cipher/MULTI2.pm
@@ -4,16 +4,15 @@ package Crypt::Cipher::MULTI2;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
-use CryptX;
-use base 'Crypt::Cipher';
+use base qw(Crypt::Cipher);
-sub blocksize { Crypt::Cipher::blocksize(__PACKAGE__) }
-sub keysize { Crypt::Cipher::keysize(__PACKAGE__) }
-sub max_keysize { Crypt::Cipher::max_keysize(__PACKAGE__) }
-sub min_keysize { Crypt::Cipher::min_keysize(__PACKAGE__) }
-sub default_rounds { Crypt::Cipher::default_rounds(__PACKAGE__) }
+sub blocksize { Crypt::Cipher::blocksize('MULTI2') }
+sub keysize { Crypt::Cipher::keysize('MULTI2') }
+sub max_keysize { Crypt::Cipher::max_keysize('MULTI2') }
+sub min_keysize { Crypt::Cipher::min_keysize('MULTI2') }
+sub default_rounds { Crypt::Cipher::default_rounds('MULTI2') }
1;
diff --git a/lib/Crypt/Cipher/Noekeon.pm b/lib/Crypt/Cipher/Noekeon.pm
index 58cedc0d..d1efa638 100644
--- a/lib/Crypt/Cipher/Noekeon.pm
+++ b/lib/Crypt/Cipher/Noekeon.pm
@@ -4,16 +4,15 @@ package Crypt::Cipher::Noekeon;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
-use CryptX;
-use base 'Crypt::Cipher';
+use base qw(Crypt::Cipher);
-sub blocksize { Crypt::Cipher::blocksize(__PACKAGE__) }
-sub keysize { Crypt::Cipher::keysize(__PACKAGE__) }
-sub max_keysize { Crypt::Cipher::max_keysize(__PACKAGE__) }
-sub min_keysize { Crypt::Cipher::min_keysize(__PACKAGE__) }
-sub default_rounds { Crypt::Cipher::default_rounds(__PACKAGE__) }
+sub blocksize { Crypt::Cipher::blocksize('Noekeon') }
+sub keysize { Crypt::Cipher::keysize('Noekeon') }
+sub max_keysize { Crypt::Cipher::max_keysize('Noekeon') }
+sub min_keysize { Crypt::Cipher::min_keysize('Noekeon') }
+sub default_rounds { Crypt::Cipher::default_rounds('Noekeon') }
1;
diff --git a/lib/Crypt/Cipher/RC2.pm b/lib/Crypt/Cipher/RC2.pm
index 3727085d..da63d348 100644
--- a/lib/Crypt/Cipher/RC2.pm
+++ b/lib/Crypt/Cipher/RC2.pm
@@ -4,16 +4,15 @@ package Crypt::Cipher::RC2;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
-use CryptX;
-use base 'Crypt::Cipher';
+use base qw(Crypt::Cipher);
-sub blocksize { Crypt::Cipher::blocksize(__PACKAGE__) }
-sub keysize { Crypt::Cipher::keysize(__PACKAGE__) }
-sub max_keysize { Crypt::Cipher::max_keysize(__PACKAGE__) }
-sub min_keysize { Crypt::Cipher::min_keysize(__PACKAGE__) }
-sub default_rounds { Crypt::Cipher::default_rounds(__PACKAGE__) }
+sub blocksize { Crypt::Cipher::blocksize('RC2') }
+sub keysize { Crypt::Cipher::keysize('RC2') }
+sub max_keysize { Crypt::Cipher::max_keysize('RC2') }
+sub min_keysize { Crypt::Cipher::min_keysize('RC2') }
+sub default_rounds { Crypt::Cipher::default_rounds('RC2') }
1;
diff --git a/lib/Crypt/Cipher/RC5.pm b/lib/Crypt/Cipher/RC5.pm
index 5e29a8e0..06f81862 100644
--- a/lib/Crypt/Cipher/RC5.pm
+++ b/lib/Crypt/Cipher/RC5.pm
@@ -4,16 +4,15 @@ package Crypt::Cipher::RC5;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
-use CryptX;
-use base 'Crypt::Cipher';
+use base qw(Crypt::Cipher);
-sub blocksize { Crypt::Cipher::blocksize(__PACKAGE__) }
-sub keysize { Crypt::Cipher::keysize(__PACKAGE__) }
-sub max_keysize { Crypt::Cipher::max_keysize(__PACKAGE__) }
-sub min_keysize { Crypt::Cipher::min_keysize(__PACKAGE__) }
-sub default_rounds { Crypt::Cipher::default_rounds(__PACKAGE__) }
+sub blocksize { Crypt::Cipher::blocksize('RC5') }
+sub keysize { Crypt::Cipher::keysize('RC5') }
+sub max_keysize { Crypt::Cipher::max_keysize('RC5') }
+sub min_keysize { Crypt::Cipher::min_keysize('RC5') }
+sub default_rounds { Crypt::Cipher::default_rounds('RC5') }
1;
diff --git a/lib/Crypt/Cipher/RC6.pm b/lib/Crypt/Cipher/RC6.pm
index 05da0dc0..e662a67a 100644
--- a/lib/Crypt/Cipher/RC6.pm
+++ b/lib/Crypt/Cipher/RC6.pm
@@ -4,16 +4,15 @@ package Crypt::Cipher::RC6;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
-use CryptX;
-use base 'Crypt::Cipher';
+use base qw(Crypt::Cipher);
-sub blocksize { Crypt::Cipher::blocksize(__PACKAGE__) }
-sub keysize { Crypt::Cipher::keysize(__PACKAGE__) }
-sub max_keysize { Crypt::Cipher::max_keysize(__PACKAGE__) }
-sub min_keysize { Crypt::Cipher::min_keysize(__PACKAGE__) }
-sub default_rounds { Crypt::Cipher::default_rounds(__PACKAGE__) }
+sub blocksize { Crypt::Cipher::blocksize('RC6') }
+sub keysize { Crypt::Cipher::keysize('RC6') }
+sub max_keysize { Crypt::Cipher::max_keysize('RC6') }
+sub min_keysize { Crypt::Cipher::min_keysize('RC6') }
+sub default_rounds { Crypt::Cipher::default_rounds('RC6') }
1;
diff --git a/lib/Crypt/Cipher/SAFERP.pm b/lib/Crypt/Cipher/SAFERP.pm
index 878ff0c2..8c5b3f51 100644
--- a/lib/Crypt/Cipher/SAFERP.pm
+++ b/lib/Crypt/Cipher/SAFERP.pm
@@ -4,16 +4,15 @@ package Crypt::Cipher::SAFERP;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
-use CryptX;
-use base 'Crypt::Cipher';
+use base qw(Crypt::Cipher);
-sub blocksize { Crypt::Cipher::blocksize(__PACKAGE__) }
-sub keysize { Crypt::Cipher::keysize(__PACKAGE__) }
-sub max_keysize { Crypt::Cipher::max_keysize(__PACKAGE__) }
-sub min_keysize { Crypt::Cipher::min_keysize(__PACKAGE__) }
-sub default_rounds { Crypt::Cipher::default_rounds(__PACKAGE__) }
+sub blocksize { Crypt::Cipher::blocksize('SAFERP') }
+sub keysize { Crypt::Cipher::keysize('SAFERP') }
+sub max_keysize { Crypt::Cipher::max_keysize('SAFERP') }
+sub min_keysize { Crypt::Cipher::min_keysize('SAFERP') }
+sub default_rounds { Crypt::Cipher::default_rounds('SAFERP') }
1;
diff --git a/lib/Crypt/Cipher/SAFER_K128.pm b/lib/Crypt/Cipher/SAFER_K128.pm
index 8eaf4af5..c1be436a 100644
--- a/lib/Crypt/Cipher/SAFER_K128.pm
+++ b/lib/Crypt/Cipher/SAFER_K128.pm
@@ -4,16 +4,15 @@ package Crypt::Cipher::SAFER_K128;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
-use CryptX;
-use base 'Crypt::Cipher';
+use base qw(Crypt::Cipher);
-sub blocksize { Crypt::Cipher::blocksize(__PACKAGE__) }
-sub keysize { Crypt::Cipher::keysize(__PACKAGE__) }
-sub max_keysize { Crypt::Cipher::max_keysize(__PACKAGE__) }
-sub min_keysize { Crypt::Cipher::min_keysize(__PACKAGE__) }
-sub default_rounds { Crypt::Cipher::default_rounds(__PACKAGE__) }
+sub blocksize { Crypt::Cipher::blocksize('SAFER_K128') }
+sub keysize { Crypt::Cipher::keysize('SAFER_K128') }
+sub max_keysize { Crypt::Cipher::max_keysize('SAFER_K128') }
+sub min_keysize { Crypt::Cipher::min_keysize('SAFER_K128') }
+sub default_rounds { Crypt::Cipher::default_rounds('SAFER_K128') }
1;
diff --git a/lib/Crypt/Cipher/SAFER_K64.pm b/lib/Crypt/Cipher/SAFER_K64.pm
index d8862b28..cda042e9 100644
--- a/lib/Crypt/Cipher/SAFER_K64.pm
+++ b/lib/Crypt/Cipher/SAFER_K64.pm
@@ -4,16 +4,15 @@ package Crypt::Cipher::SAFER_K64;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
-use CryptX;
-use base 'Crypt::Cipher';
+use base qw(Crypt::Cipher);
-sub blocksize { Crypt::Cipher::blocksize(__PACKAGE__) }
-sub keysize { Crypt::Cipher::keysize(__PACKAGE__) }
-sub max_keysize { Crypt::Cipher::max_keysize(__PACKAGE__) }
-sub min_keysize { Crypt::Cipher::min_keysize(__PACKAGE__) }
-sub default_rounds { Crypt::Cipher::default_rounds(__PACKAGE__) }
+sub blocksize { Crypt::Cipher::blocksize('SAFER_K64') }
+sub keysize { Crypt::Cipher::keysize('SAFER_K64') }
+sub max_keysize { Crypt::Cipher::max_keysize('SAFER_K64') }
+sub min_keysize { Crypt::Cipher::min_keysize('SAFER_K64') }
+sub default_rounds { Crypt::Cipher::default_rounds('SAFER_K64') }
1;
diff --git a/lib/Crypt/Cipher/SAFER_SK128.pm b/lib/Crypt/Cipher/SAFER_SK128.pm
index a150fe0f..76bd22f6 100644
--- a/lib/Crypt/Cipher/SAFER_SK128.pm
+++ b/lib/Crypt/Cipher/SAFER_SK128.pm
@@ -4,16 +4,15 @@ package Crypt::Cipher::SAFER_SK128;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
-use CryptX;
-use base 'Crypt::Cipher';
+use base qw(Crypt::Cipher);
-sub blocksize { Crypt::Cipher::blocksize(__PACKAGE__) }
-sub keysize { Crypt::Cipher::keysize(__PACKAGE__) }
-sub max_keysize { Crypt::Cipher::max_keysize(__PACKAGE__) }
-sub min_keysize { Crypt::Cipher::min_keysize(__PACKAGE__) }
-sub default_rounds { Crypt::Cipher::default_rounds(__PACKAGE__) }
+sub blocksize { Crypt::Cipher::blocksize('SAFER_SK128') }
+sub keysize { Crypt::Cipher::keysize('SAFER_SK128') }
+sub max_keysize { Crypt::Cipher::max_keysize('SAFER_SK128') }
+sub min_keysize { Crypt::Cipher::min_keysize('SAFER_SK128') }
+sub default_rounds { Crypt::Cipher::default_rounds('SAFER_SK128') }
1;
diff --git a/lib/Crypt/Cipher/SAFER_SK64.pm b/lib/Crypt/Cipher/SAFER_SK64.pm
index 22ddd05d..582eb0fc 100644
--- a/lib/Crypt/Cipher/SAFER_SK64.pm
+++ b/lib/Crypt/Cipher/SAFER_SK64.pm
@@ -4,16 +4,15 @@ package Crypt::Cipher::SAFER_SK64;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
-use CryptX;
-use base 'Crypt::Cipher';
+use base qw(Crypt::Cipher);
-sub blocksize { Crypt::Cipher::blocksize(__PACKAGE__) }
-sub keysize { Crypt::Cipher::keysize(__PACKAGE__) }
-sub max_keysize { Crypt::Cipher::max_keysize(__PACKAGE__) }
-sub min_keysize { Crypt::Cipher::min_keysize(__PACKAGE__) }
-sub default_rounds { Crypt::Cipher::default_rounds(__PACKAGE__) }
+sub blocksize { Crypt::Cipher::blocksize('SAFER_SK64') }
+sub keysize { Crypt::Cipher::keysize('SAFER_SK64') }
+sub max_keysize { Crypt::Cipher::max_keysize('SAFER_SK64') }
+sub min_keysize { Crypt::Cipher::min_keysize('SAFER_SK64') }
+sub default_rounds { Crypt::Cipher::default_rounds('SAFER_SK64') }
1;
diff --git a/lib/Crypt/Cipher/SEED.pm b/lib/Crypt/Cipher/SEED.pm
index 4fc6338a..bea2c9bb 100644
--- a/lib/Crypt/Cipher/SEED.pm
+++ b/lib/Crypt/Cipher/SEED.pm
@@ -4,16 +4,15 @@ package Crypt::Cipher::SEED;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
-use CryptX;
-use base 'Crypt::Cipher';
+use base qw(Crypt::Cipher);
-sub blocksize { Crypt::Cipher::blocksize(__PACKAGE__) }
-sub keysize { Crypt::Cipher::keysize(__PACKAGE__) }
-sub max_keysize { Crypt::Cipher::max_keysize(__PACKAGE__) }
-sub min_keysize { Crypt::Cipher::min_keysize(__PACKAGE__) }
-sub default_rounds { Crypt::Cipher::default_rounds(__PACKAGE__) }
+sub blocksize { Crypt::Cipher::blocksize('SEED') }
+sub keysize { Crypt::Cipher::keysize('SEED') }
+sub max_keysize { Crypt::Cipher::max_keysize('SEED') }
+sub min_keysize { Crypt::Cipher::min_keysize('SEED') }
+sub default_rounds { Crypt::Cipher::default_rounds('SEED') }
1;
diff --git a/lib/Crypt/Cipher/Serpent.pm b/lib/Crypt/Cipher/Serpent.pm
index 21e31094..69e8e8b0 100644
--- a/lib/Crypt/Cipher/Serpent.pm
+++ b/lib/Crypt/Cipher/Serpent.pm
@@ -4,16 +4,15 @@ package Crypt::Cipher::Serpent;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
-use CryptX;
-use base 'Crypt::Cipher';
+use base qw(Crypt::Cipher);
-sub blocksize { Crypt::Cipher::blocksize(__PACKAGE__) }
-sub keysize { Crypt::Cipher::keysize(__PACKAGE__) }
-sub max_keysize { Crypt::Cipher::max_keysize(__PACKAGE__) }
-sub min_keysize { Crypt::Cipher::min_keysize(__PACKAGE__) }
-sub default_rounds { Crypt::Cipher::default_rounds(__PACKAGE__) }
+sub blocksize { Crypt::Cipher::blocksize('Serpent') }
+sub keysize { Crypt::Cipher::keysize('Serpent') }
+sub max_keysize { Crypt::Cipher::max_keysize('Serpent') }
+sub min_keysize { Crypt::Cipher::min_keysize('Serpent') }
+sub default_rounds { Crypt::Cipher::default_rounds('Serpent') }
1;
diff --git a/lib/Crypt/Cipher/Skipjack.pm b/lib/Crypt/Cipher/Skipjack.pm
index bcf6dd4f..3e0db08e 100644
--- a/lib/Crypt/Cipher/Skipjack.pm
+++ b/lib/Crypt/Cipher/Skipjack.pm
@@ -4,16 +4,15 @@ package Crypt::Cipher::Skipjack;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
-use CryptX;
-use base 'Crypt::Cipher';
+use base qw(Crypt::Cipher);
-sub blocksize { Crypt::Cipher::blocksize(__PACKAGE__) }
-sub keysize { Crypt::Cipher::keysize(__PACKAGE__) }
-sub max_keysize { Crypt::Cipher::max_keysize(__PACKAGE__) }
-sub min_keysize { Crypt::Cipher::min_keysize(__PACKAGE__) }
-sub default_rounds { Crypt::Cipher::default_rounds(__PACKAGE__) }
+sub blocksize { Crypt::Cipher::blocksize('Skipjack') }
+sub keysize { Crypt::Cipher::keysize('Skipjack') }
+sub max_keysize { Crypt::Cipher::max_keysize('Skipjack') }
+sub min_keysize { Crypt::Cipher::min_keysize('Skipjack') }
+sub default_rounds { Crypt::Cipher::default_rounds('Skipjack') }
1;
diff --git a/lib/Crypt/Cipher/Twofish.pm b/lib/Crypt/Cipher/Twofish.pm
index fef9f266..4da40110 100644
--- a/lib/Crypt/Cipher/Twofish.pm
+++ b/lib/Crypt/Cipher/Twofish.pm
@@ -4,16 +4,15 @@ package Crypt::Cipher::Twofish;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
-use CryptX;
-use base 'Crypt::Cipher';
+use base qw(Crypt::Cipher);
-sub blocksize { Crypt::Cipher::blocksize(__PACKAGE__) }
-sub keysize { Crypt::Cipher::keysize(__PACKAGE__) }
-sub max_keysize { Crypt::Cipher::max_keysize(__PACKAGE__) }
-sub min_keysize { Crypt::Cipher::min_keysize(__PACKAGE__) }
-sub default_rounds { Crypt::Cipher::default_rounds(__PACKAGE__) }
+sub blocksize { Crypt::Cipher::blocksize('Twofish') }
+sub keysize { Crypt::Cipher::keysize('Twofish') }
+sub max_keysize { Crypt::Cipher::max_keysize('Twofish') }
+sub min_keysize { Crypt::Cipher::min_keysize('Twofish') }
+sub default_rounds { Crypt::Cipher::default_rounds('Twofish') }
1;
diff --git a/lib/Crypt/Cipher/XTEA.pm b/lib/Crypt/Cipher/XTEA.pm
index 1a7fb821..1a630bc6 100644
--- a/lib/Crypt/Cipher/XTEA.pm
+++ b/lib/Crypt/Cipher/XTEA.pm
@@ -4,16 +4,15 @@ package Crypt::Cipher::XTEA;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
-use CryptX;
-use base 'Crypt::Cipher';
+use base qw(Crypt::Cipher);
-sub blocksize { Crypt::Cipher::blocksize(__PACKAGE__) }
-sub keysize { Crypt::Cipher::keysize(__PACKAGE__) }
-sub max_keysize { Crypt::Cipher::max_keysize(__PACKAGE__) }
-sub min_keysize { Crypt::Cipher::min_keysize(__PACKAGE__) }
-sub default_rounds { Crypt::Cipher::default_rounds(__PACKAGE__) }
+sub blocksize { Crypt::Cipher::blocksize('XTEA') }
+sub keysize { Crypt::Cipher::keysize('XTEA') }
+sub max_keysize { Crypt::Cipher::max_keysize('XTEA') }
+sub min_keysize { Crypt::Cipher::min_keysize('XTEA') }
+sub default_rounds { Crypt::Cipher::default_rounds('XTEA') }
1;
diff --git a/lib/Crypt/Digest.pm b/lib/Crypt/Digest.pm
index 3fa01e6d..cb3a32ab 100644
--- a/lib/Crypt/Digest.pm
+++ b/lib/Crypt/Digest.pm
@@ -2,7 +2,7 @@ package Crypt::Digest;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import';
our %EXPORT_TAGS = ( all => [qw( digest_data digest_data_hex digest_data_b64 digest_data_b64u digest_file digest_file_hex digest_file_b64 digest_file_b64u )] );
@@ -14,70 +14,22 @@ $Carp::Internal{(__PACKAGE__)}++;
use CryptX;
### the following methods/functions are implemented in XS:
-# - _new
-# - _hashsize
-# - _hashsize_by_name (function, not method)
+# - new
+# - hashsize
# - clone
# - reset
# - digest
# - hexdigest
# - b64digest
# - add
+# - digest_data
+# - digest_data_hex
+# - digest_data_b64
+# - digest_data_b64u
# - DESTROY
-sub _trans_digest_name {
- my $name = shift || "";
- my %trans = (
- CHAES => 'chc_hash',
- RIPEMD128 => 'rmd128',
- RIPEMD160 => 'rmd160',
- RIPEMD256 => 'rmd256',
- RIPEMD320 => 'rmd320',
- TIGER192 => 'tiger',
- SHA512_224 => 'sha512-224',
- SHA512_256 => 'sha512-256',
- SHA3_224 => 'sha3-224',
- SHA3_256 => 'sha3-256',
- SHA3_384 => 'sha3-384',
- SHA3_512 => 'sha3-512',
- BLAKE2B_160 => 'blake2b-160',
- BLAKE2B_256 => 'blake2b-256',
- BLAKE2B_384 => 'blake2b-384',
- BLAKE2B_512 => 'blake2b-512',
- BLAKE2S_128 => 'blake2s-128',
- BLAKE2S_160 => 'blake2s-160',
- BLAKE2S_224 => 'blake2s-224',
- BLAKE2S_256 => 'blake2s-256',
- );
- $name =~ s/^Crypt::Digest:://i;
- return $trans{uc($name)} if defined $trans{uc($name)};
- return lc($name);
-}
-
### METHODS
-sub new {
- my $pkg = shift;
- unshift @_, ($pkg eq 'Crypt::Digest' ? _trans_digest_name(shift) : _trans_digest_name($pkg));
- local $SIG{__DIE__} = \&CryptX::_croak;
- return _new(@_);
-}
-
-sub hashsize {
- return unless defined $_[0];
-
- if (ref $_[0]) {
- local $SIG{__DIE__} = \&CryptX::_croak;
- return _hashsize(@_);
- }
- else {
- my $pkg = shift;
- unshift @_, ($pkg eq 'Crypt::Digest' ? _trans_digest_name(shift) : _trans_digest_name($pkg));
- local $SIG{__DIE__} = \&CryptX::_croak;
- return _hashsize_by_name(@_);
- }
-}
-
sub addfile {
my ($self, $file) = @_;
@@ -105,11 +57,6 @@ sub CLONE_SKIP { 1 } # prevent cloning
### FUNCTIONS
-sub digest_data { local $SIG{__DIE__} = \&CryptX::_croak; Crypt::Digest->new(shift)->add(@_)->digest }
-sub digest_data_hex { local $SIG{__DIE__} = \&CryptX::_croak; Crypt::Digest->new(shift)->add(@_)->hexdigest }
-sub digest_data_b64 { local $SIG{__DIE__} = \&CryptX::_croak; Crypt::Digest->new(shift)->add(@_)->b64digest }
-sub digest_data_b64u { local $SIG{__DIE__} = \&CryptX::_croak; Crypt::Digest->new(shift)->add(@_)->b64udigest }
-
sub digest_file { local $SIG{__DIE__} = \&CryptX::_croak; Crypt::Digest->new(shift)->addfile(@_)->digest }
sub digest_file_hex { local $SIG{__DIE__} = \&CryptX::_croak; Crypt::Digest->new(shift)->addfile(@_)->hexdigest }
sub digest_file_b64 { local $SIG{__DIE__} = \&CryptX::_croak; Crypt::Digest->new(shift)->addfile(@_)->b64digest }
diff --git a/lib/Crypt/Digest/BLAKE2b_160.pm b/lib/Crypt/Digest/BLAKE2b_160.pm
index 3dab678d..8c6730aa 100644
--- a/lib/Crypt/Digest/BLAKE2b_160.pm
+++ b/lib/Crypt/Digest/BLAKE2b_160.pm
@@ -4,7 +4,7 @@ package Crypt::Digest::BLAKE2b_160;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::Digest Exporter);
our %EXPORT_TAGS = ( all => [qw( blake2b_160 blake2b_160_hex blake2b_160_b64 blake2b_160_b64u blake2b_160_file blake2b_160_file_hex blake2b_160_file_b64 blake2b_160_file_b64u )] );
@@ -13,19 +13,17 @@ our @EXPORT = qw();
use Carp;
$Carp::Internal{(__PACKAGE__)}++;
-use CryptX;
-
-sub hashsize { Crypt::Digest::hashsize(__PACKAGE__) }
-
-sub blake2b_160 { Crypt::Digest::digest_data(__PACKAGE__, @_) }
-sub blake2b_160_hex { Crypt::Digest::digest_data_hex(__PACKAGE__, @_) }
-sub blake2b_160_b64 { Crypt::Digest::digest_data_b64(__PACKAGE__, @_) }
-sub blake2b_160_b64u { Crypt::Digest::digest_data_b64u(__PACKAGE__, @_) }
-
-sub blake2b_160_file { Crypt::Digest::digest_file(__PACKAGE__, @_) }
-sub blake2b_160_file_hex { Crypt::Digest::digest_file_hex(__PACKAGE__, @_) }
-sub blake2b_160_file_b64 { Crypt::Digest::digest_file_b64(__PACKAGE__, @_) }
-sub blake2b_160_file_b64u { Crypt::Digest::digest_file_b64u(__PACKAGE__, @_) }
+use Crypt::Digest;
+
+sub hashsize { Crypt::Digest::hashsize('BLAKE2b_160') }
+sub blake2b_160 { Crypt::Digest::digest_data('BLAKE2b_160', @_) }
+sub blake2b_160_hex { Crypt::Digest::digest_data_hex('BLAKE2b_160', @_) }
+sub blake2b_160_b64 { Crypt::Digest::digest_data_b64('BLAKE2b_160', @_) }
+sub blake2b_160_b64u { Crypt::Digest::digest_data_b64u('BLAKE2b_160', @_) }
+sub blake2b_160_file { Crypt::Digest::digest_file('BLAKE2b_160', @_) }
+sub blake2b_160_file_hex { Crypt::Digest::digest_file_hex('BLAKE2b_160', @_) }
+sub blake2b_160_file_b64 { Crypt::Digest::digest_file_b64('BLAKE2b_160', @_) }
+sub blake2b_160_file_b64u { Crypt::Digest::digest_file_b64u('BLAKE2b_160', @_) }
1;
diff --git a/lib/Crypt/Digest/BLAKE2b_256.pm b/lib/Crypt/Digest/BLAKE2b_256.pm
index 564ef874..fd9bc59b 100644
--- a/lib/Crypt/Digest/BLAKE2b_256.pm
+++ b/lib/Crypt/Digest/BLAKE2b_256.pm
@@ -4,7 +4,7 @@ package Crypt::Digest::BLAKE2b_256;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::Digest Exporter);
our %EXPORT_TAGS = ( all => [qw( blake2b_256 blake2b_256_hex blake2b_256_b64 blake2b_256_b64u blake2b_256_file blake2b_256_file_hex blake2b_256_file_b64 blake2b_256_file_b64u )] );
@@ -13,19 +13,17 @@ our @EXPORT = qw();
use Carp;
$Carp::Internal{(__PACKAGE__)}++;
-use CryptX;
-
-sub hashsize { Crypt::Digest::hashsize(__PACKAGE__) }
-
-sub blake2b_256 { Crypt::Digest::digest_data(__PACKAGE__, @_) }
-sub blake2b_256_hex { Crypt::Digest::digest_data_hex(__PACKAGE__, @_) }
-sub blake2b_256_b64 { Crypt::Digest::digest_data_b64(__PACKAGE__, @_) }
-sub blake2b_256_b64u { Crypt::Digest::digest_data_b64u(__PACKAGE__, @_) }
-
-sub blake2b_256_file { Crypt::Digest::digest_file(__PACKAGE__, @_) }
-sub blake2b_256_file_hex { Crypt::Digest::digest_file_hex(__PACKAGE__, @_) }
-sub blake2b_256_file_b64 { Crypt::Digest::digest_file_b64(__PACKAGE__, @_) }
-sub blake2b_256_file_b64u { Crypt::Digest::digest_file_b64u(__PACKAGE__, @_) }
+use Crypt::Digest;
+
+sub hashsize { Crypt::Digest::hashsize('BLAKE2b_256') }
+sub blake2b_256 { Crypt::Digest::digest_data('BLAKE2b_256', @_) }
+sub blake2b_256_hex { Crypt::Digest::digest_data_hex('BLAKE2b_256', @_) }
+sub blake2b_256_b64 { Crypt::Digest::digest_data_b64('BLAKE2b_256', @_) }
+sub blake2b_256_b64u { Crypt::Digest::digest_data_b64u('BLAKE2b_256', @_) }
+sub blake2b_256_file { Crypt::Digest::digest_file('BLAKE2b_256', @_) }
+sub blake2b_256_file_hex { Crypt::Digest::digest_file_hex('BLAKE2b_256', @_) }
+sub blake2b_256_file_b64 { Crypt::Digest::digest_file_b64('BLAKE2b_256', @_) }
+sub blake2b_256_file_b64u { Crypt::Digest::digest_file_b64u('BLAKE2b_256', @_) }
1;
diff --git a/lib/Crypt/Digest/BLAKE2b_384.pm b/lib/Crypt/Digest/BLAKE2b_384.pm
index e321763d..03d33b1e 100644
--- a/lib/Crypt/Digest/BLAKE2b_384.pm
+++ b/lib/Crypt/Digest/BLAKE2b_384.pm
@@ -4,7 +4,7 @@ package Crypt::Digest::BLAKE2b_384;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::Digest Exporter);
our %EXPORT_TAGS = ( all => [qw( blake2b_384 blake2b_384_hex blake2b_384_b64 blake2b_384_b64u blake2b_384_file blake2b_384_file_hex blake2b_384_file_b64 blake2b_384_file_b64u )] );
@@ -13,19 +13,17 @@ our @EXPORT = qw();
use Carp;
$Carp::Internal{(__PACKAGE__)}++;
-use CryptX;
-
-sub hashsize { Crypt::Digest::hashsize(__PACKAGE__) }
-
-sub blake2b_384 { Crypt::Digest::digest_data(__PACKAGE__, @_) }
-sub blake2b_384_hex { Crypt::Digest::digest_data_hex(__PACKAGE__, @_) }
-sub blake2b_384_b64 { Crypt::Digest::digest_data_b64(__PACKAGE__, @_) }
-sub blake2b_384_b64u { Crypt::Digest::digest_data_b64u(__PACKAGE__, @_) }
-
-sub blake2b_384_file { Crypt::Digest::digest_file(__PACKAGE__, @_) }
-sub blake2b_384_file_hex { Crypt::Digest::digest_file_hex(__PACKAGE__, @_) }
-sub blake2b_384_file_b64 { Crypt::Digest::digest_file_b64(__PACKAGE__, @_) }
-sub blake2b_384_file_b64u { Crypt::Digest::digest_file_b64u(__PACKAGE__, @_) }
+use Crypt::Digest;
+
+sub hashsize { Crypt::Digest::hashsize('BLAKE2b_384') }
+sub blake2b_384 { Crypt::Digest::digest_data('BLAKE2b_384', @_) }
+sub blake2b_384_hex { Crypt::Digest::digest_data_hex('BLAKE2b_384', @_) }
+sub blake2b_384_b64 { Crypt::Digest::digest_data_b64('BLAKE2b_384', @_) }
+sub blake2b_384_b64u { Crypt::Digest::digest_data_b64u('BLAKE2b_384', @_) }
+sub blake2b_384_file { Crypt::Digest::digest_file('BLAKE2b_384', @_) }
+sub blake2b_384_file_hex { Crypt::Digest::digest_file_hex('BLAKE2b_384', @_) }
+sub blake2b_384_file_b64 { Crypt::Digest::digest_file_b64('BLAKE2b_384', @_) }
+sub blake2b_384_file_b64u { Crypt::Digest::digest_file_b64u('BLAKE2b_384', @_) }
1;
diff --git a/lib/Crypt/Digest/BLAKE2b_512.pm b/lib/Crypt/Digest/BLAKE2b_512.pm
index a59cdd2b..e3b08e4b 100644
--- a/lib/Crypt/Digest/BLAKE2b_512.pm
+++ b/lib/Crypt/Digest/BLAKE2b_512.pm
@@ -4,7 +4,7 @@ package Crypt::Digest::BLAKE2b_512;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::Digest Exporter);
our %EXPORT_TAGS = ( all => [qw( blake2b_512 blake2b_512_hex blake2b_512_b64 blake2b_512_b64u blake2b_512_file blake2b_512_file_hex blake2b_512_file_b64 blake2b_512_file_b64u )] );
@@ -13,19 +13,17 @@ our @EXPORT = qw();
use Carp;
$Carp::Internal{(__PACKAGE__)}++;
-use CryptX;
-
-sub hashsize { Crypt::Digest::hashsize(__PACKAGE__) }
-
-sub blake2b_512 { Crypt::Digest::digest_data(__PACKAGE__, @_) }
-sub blake2b_512_hex { Crypt::Digest::digest_data_hex(__PACKAGE__, @_) }
-sub blake2b_512_b64 { Crypt::Digest::digest_data_b64(__PACKAGE__, @_) }
-sub blake2b_512_b64u { Crypt::Digest::digest_data_b64u(__PACKAGE__, @_) }
-
-sub blake2b_512_file { Crypt::Digest::digest_file(__PACKAGE__, @_) }
-sub blake2b_512_file_hex { Crypt::Digest::digest_file_hex(__PACKAGE__, @_) }
-sub blake2b_512_file_b64 { Crypt::Digest::digest_file_b64(__PACKAGE__, @_) }
-sub blake2b_512_file_b64u { Crypt::Digest::digest_file_b64u(__PACKAGE__, @_) }
+use Crypt::Digest;
+
+sub hashsize { Crypt::Digest::hashsize('BLAKE2b_512') }
+sub blake2b_512 { Crypt::Digest::digest_data('BLAKE2b_512', @_) }
+sub blake2b_512_hex { Crypt::Digest::digest_data_hex('BLAKE2b_512', @_) }
+sub blake2b_512_b64 { Crypt::Digest::digest_data_b64('BLAKE2b_512', @_) }
+sub blake2b_512_b64u { Crypt::Digest::digest_data_b64u('BLAKE2b_512', @_) }
+sub blake2b_512_file { Crypt::Digest::digest_file('BLAKE2b_512', @_) }
+sub blake2b_512_file_hex { Crypt::Digest::digest_file_hex('BLAKE2b_512', @_) }
+sub blake2b_512_file_b64 { Crypt::Digest::digest_file_b64('BLAKE2b_512', @_) }
+sub blake2b_512_file_b64u { Crypt::Digest::digest_file_b64u('BLAKE2b_512', @_) }
1;
diff --git a/lib/Crypt/Digest/BLAKE2s_128.pm b/lib/Crypt/Digest/BLAKE2s_128.pm
index 15c6c04e..5d8dbc9e 100644
--- a/lib/Crypt/Digest/BLAKE2s_128.pm
+++ b/lib/Crypt/Digest/BLAKE2s_128.pm
@@ -4,7 +4,7 @@ package Crypt::Digest::BLAKE2s_128;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::Digest Exporter);
our %EXPORT_TAGS = ( all => [qw( blake2s_128 blake2s_128_hex blake2s_128_b64 blake2s_128_b64u blake2s_128_file blake2s_128_file_hex blake2s_128_file_b64 blake2s_128_file_b64u )] );
@@ -13,19 +13,17 @@ our @EXPORT = qw();
use Carp;
$Carp::Internal{(__PACKAGE__)}++;
-use CryptX;
-
-sub hashsize { Crypt::Digest::hashsize(__PACKAGE__) }
-
-sub blake2s_128 { Crypt::Digest::digest_data(__PACKAGE__, @_) }
-sub blake2s_128_hex { Crypt::Digest::digest_data_hex(__PACKAGE__, @_) }
-sub blake2s_128_b64 { Crypt::Digest::digest_data_b64(__PACKAGE__, @_) }
-sub blake2s_128_b64u { Crypt::Digest::digest_data_b64u(__PACKAGE__, @_) }
-
-sub blake2s_128_file { Crypt::Digest::digest_file(__PACKAGE__, @_) }
-sub blake2s_128_file_hex { Crypt::Digest::digest_file_hex(__PACKAGE__, @_) }
-sub blake2s_128_file_b64 { Crypt::Digest::digest_file_b64(__PACKAGE__, @_) }
-sub blake2s_128_file_b64u { Crypt::Digest::digest_file_b64u(__PACKAGE__, @_) }
+use Crypt::Digest;
+
+sub hashsize { Crypt::Digest::hashsize('BLAKE2s_128') }
+sub blake2s_128 { Crypt::Digest::digest_data('BLAKE2s_128', @_) }
+sub blake2s_128_hex { Crypt::Digest::digest_data_hex('BLAKE2s_128', @_) }
+sub blake2s_128_b64 { Crypt::Digest::digest_data_b64('BLAKE2s_128', @_) }
+sub blake2s_128_b64u { Crypt::Digest::digest_data_b64u('BLAKE2s_128', @_) }
+sub blake2s_128_file { Crypt::Digest::digest_file('BLAKE2s_128', @_) }
+sub blake2s_128_file_hex { Crypt::Digest::digest_file_hex('BLAKE2s_128', @_) }
+sub blake2s_128_file_b64 { Crypt::Digest::digest_file_b64('BLAKE2s_128', @_) }
+sub blake2s_128_file_b64u { Crypt::Digest::digest_file_b64u('BLAKE2s_128', @_) }
1;
diff --git a/lib/Crypt/Digest/BLAKE2s_160.pm b/lib/Crypt/Digest/BLAKE2s_160.pm
index c3e8af12..9c17f783 100644
--- a/lib/Crypt/Digest/BLAKE2s_160.pm
+++ b/lib/Crypt/Digest/BLAKE2s_160.pm
@@ -4,7 +4,7 @@ package Crypt::Digest::BLAKE2s_160;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::Digest Exporter);
our %EXPORT_TAGS = ( all => [qw( blake2s_160 blake2s_160_hex blake2s_160_b64 blake2s_160_b64u blake2s_160_file blake2s_160_file_hex blake2s_160_file_b64 blake2s_160_file_b64u )] );
@@ -13,19 +13,17 @@ our @EXPORT = qw();
use Carp;
$Carp::Internal{(__PACKAGE__)}++;
-use CryptX;
-
-sub hashsize { Crypt::Digest::hashsize(__PACKAGE__) }
-
-sub blake2s_160 { Crypt::Digest::digest_data(__PACKAGE__, @_) }
-sub blake2s_160_hex { Crypt::Digest::digest_data_hex(__PACKAGE__, @_) }
-sub blake2s_160_b64 { Crypt::Digest::digest_data_b64(__PACKAGE__, @_) }
-sub blake2s_160_b64u { Crypt::Digest::digest_data_b64u(__PACKAGE__, @_) }
-
-sub blake2s_160_file { Crypt::Digest::digest_file(__PACKAGE__, @_) }
-sub blake2s_160_file_hex { Crypt::Digest::digest_file_hex(__PACKAGE__, @_) }
-sub blake2s_160_file_b64 { Crypt::Digest::digest_file_b64(__PACKAGE__, @_) }
-sub blake2s_160_file_b64u { Crypt::Digest::digest_file_b64u(__PACKAGE__, @_) }
+use Crypt::Digest;
+
+sub hashsize { Crypt::Digest::hashsize('BLAKE2s_160') }
+sub blake2s_160 { Crypt::Digest::digest_data('BLAKE2s_160', @_) }
+sub blake2s_160_hex { Crypt::Digest::digest_data_hex('BLAKE2s_160', @_) }
+sub blake2s_160_b64 { Crypt::Digest::digest_data_b64('BLAKE2s_160', @_) }
+sub blake2s_160_b64u { Crypt::Digest::digest_data_b64u('BLAKE2s_160', @_) }
+sub blake2s_160_file { Crypt::Digest::digest_file('BLAKE2s_160', @_) }
+sub blake2s_160_file_hex { Crypt::Digest::digest_file_hex('BLAKE2s_160', @_) }
+sub blake2s_160_file_b64 { Crypt::Digest::digest_file_b64('BLAKE2s_160', @_) }
+sub blake2s_160_file_b64u { Crypt::Digest::digest_file_b64u('BLAKE2s_160', @_) }
1;
diff --git a/lib/Crypt/Digest/BLAKE2s_224.pm b/lib/Crypt/Digest/BLAKE2s_224.pm
index c8534cf0..c8abbf22 100644
--- a/lib/Crypt/Digest/BLAKE2s_224.pm
+++ b/lib/Crypt/Digest/BLAKE2s_224.pm
@@ -4,7 +4,7 @@ package Crypt::Digest::BLAKE2s_224;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::Digest Exporter);
our %EXPORT_TAGS = ( all => [qw( blake2s_224 blake2s_224_hex blake2s_224_b64 blake2s_224_b64u blake2s_224_file blake2s_224_file_hex blake2s_224_file_b64 blake2s_224_file_b64u )] );
@@ -13,19 +13,17 @@ our @EXPORT = qw();
use Carp;
$Carp::Internal{(__PACKAGE__)}++;
-use CryptX;
-
-sub hashsize { Crypt::Digest::hashsize(__PACKAGE__) }
-
-sub blake2s_224 { Crypt::Digest::digest_data(__PACKAGE__, @_) }
-sub blake2s_224_hex { Crypt::Digest::digest_data_hex(__PACKAGE__, @_) }
-sub blake2s_224_b64 { Crypt::Digest::digest_data_b64(__PACKAGE__, @_) }
-sub blake2s_224_b64u { Crypt::Digest::digest_data_b64u(__PACKAGE__, @_) }
-
-sub blake2s_224_file { Crypt::Digest::digest_file(__PACKAGE__, @_) }
-sub blake2s_224_file_hex { Crypt::Digest::digest_file_hex(__PACKAGE__, @_) }
-sub blake2s_224_file_b64 { Crypt::Digest::digest_file_b64(__PACKAGE__, @_) }
-sub blake2s_224_file_b64u { Crypt::Digest::digest_file_b64u(__PACKAGE__, @_) }
+use Crypt::Digest;
+
+sub hashsize { Crypt::Digest::hashsize('BLAKE2s_224') }
+sub blake2s_224 { Crypt::Digest::digest_data('BLAKE2s_224', @_) }
+sub blake2s_224_hex { Crypt::Digest::digest_data_hex('BLAKE2s_224', @_) }
+sub blake2s_224_b64 { Crypt::Digest::digest_data_b64('BLAKE2s_224', @_) }
+sub blake2s_224_b64u { Crypt::Digest::digest_data_b64u('BLAKE2s_224', @_) }
+sub blake2s_224_file { Crypt::Digest::digest_file('BLAKE2s_224', @_) }
+sub blake2s_224_file_hex { Crypt::Digest::digest_file_hex('BLAKE2s_224', @_) }
+sub blake2s_224_file_b64 { Crypt::Digest::digest_file_b64('BLAKE2s_224', @_) }
+sub blake2s_224_file_b64u { Crypt::Digest::digest_file_b64u('BLAKE2s_224', @_) }
1;
diff --git a/lib/Crypt/Digest/BLAKE2s_256.pm b/lib/Crypt/Digest/BLAKE2s_256.pm
index 8d4a1ad1..de55e6de 100644
--- a/lib/Crypt/Digest/BLAKE2s_256.pm
+++ b/lib/Crypt/Digest/BLAKE2s_256.pm
@@ -4,7 +4,7 @@ package Crypt::Digest::BLAKE2s_256;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::Digest Exporter);
our %EXPORT_TAGS = ( all => [qw( blake2s_256 blake2s_256_hex blake2s_256_b64 blake2s_256_b64u blake2s_256_file blake2s_256_file_hex blake2s_256_file_b64 blake2s_256_file_b64u )] );
@@ -13,19 +13,17 @@ our @EXPORT = qw();
use Carp;
$Carp::Internal{(__PACKAGE__)}++;
-use CryptX;
-
-sub hashsize { Crypt::Digest::hashsize(__PACKAGE__) }
-
-sub blake2s_256 { Crypt::Digest::digest_data(__PACKAGE__, @_) }
-sub blake2s_256_hex { Crypt::Digest::digest_data_hex(__PACKAGE__, @_) }
-sub blake2s_256_b64 { Crypt::Digest::digest_data_b64(__PACKAGE__, @_) }
-sub blake2s_256_b64u { Crypt::Digest::digest_data_b64u(__PACKAGE__, @_) }
-
-sub blake2s_256_file { Crypt::Digest::digest_file(__PACKAGE__, @_) }
-sub blake2s_256_file_hex { Crypt::Digest::digest_file_hex(__PACKAGE__, @_) }
-sub blake2s_256_file_b64 { Crypt::Digest::digest_file_b64(__PACKAGE__, @_) }
-sub blake2s_256_file_b64u { Crypt::Digest::digest_file_b64u(__PACKAGE__, @_) }
+use Crypt::Digest;
+
+sub hashsize { Crypt::Digest::hashsize('BLAKE2s_256') }
+sub blake2s_256 { Crypt::Digest::digest_data('BLAKE2s_256', @_) }
+sub blake2s_256_hex { Crypt::Digest::digest_data_hex('BLAKE2s_256', @_) }
+sub blake2s_256_b64 { Crypt::Digest::digest_data_b64('BLAKE2s_256', @_) }
+sub blake2s_256_b64u { Crypt::Digest::digest_data_b64u('BLAKE2s_256', @_) }
+sub blake2s_256_file { Crypt::Digest::digest_file('BLAKE2s_256', @_) }
+sub blake2s_256_file_hex { Crypt::Digest::digest_file_hex('BLAKE2s_256', @_) }
+sub blake2s_256_file_b64 { Crypt::Digest::digest_file_b64('BLAKE2s_256', @_) }
+sub blake2s_256_file_b64u { Crypt::Digest::digest_file_b64u('BLAKE2s_256', @_) }
1;
diff --git a/lib/Crypt/Digest/CHAES.pm b/lib/Crypt/Digest/CHAES.pm
index c4ffb33c..d4456447 100644
--- a/lib/Crypt/Digest/CHAES.pm
+++ b/lib/Crypt/Digest/CHAES.pm
@@ -4,7 +4,7 @@ package Crypt::Digest::CHAES;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::Digest Exporter);
our %EXPORT_TAGS = ( all => [qw( chaes chaes_hex chaes_b64 chaes_b64u chaes_file chaes_file_hex chaes_file_b64 chaes_file_b64u )] );
@@ -13,19 +13,17 @@ our @EXPORT = qw();
use Carp;
$Carp::Internal{(__PACKAGE__)}++;
-use CryptX;
-
-sub hashsize { Crypt::Digest::hashsize(__PACKAGE__) }
-
-sub chaes { Crypt::Digest::digest_data(__PACKAGE__, @_) }
-sub chaes_hex { Crypt::Digest::digest_data_hex(__PACKAGE__, @_) }
-sub chaes_b64 { Crypt::Digest::digest_data_b64(__PACKAGE__, @_) }
-sub chaes_b64u { Crypt::Digest::digest_data_b64u(__PACKAGE__, @_) }
-
-sub chaes_file { Crypt::Digest::digest_file(__PACKAGE__, @_) }
-sub chaes_file_hex { Crypt::Digest::digest_file_hex(__PACKAGE__, @_) }
-sub chaes_file_b64 { Crypt::Digest::digest_file_b64(__PACKAGE__, @_) }
-sub chaes_file_b64u { Crypt::Digest::digest_file_b64u(__PACKAGE__, @_) }
+use Crypt::Digest;
+
+sub hashsize { Crypt::Digest::hashsize('CHAES') }
+sub chaes { Crypt::Digest::digest_data('CHAES', @_) }
+sub chaes_hex { Crypt::Digest::digest_data_hex('CHAES', @_) }
+sub chaes_b64 { Crypt::Digest::digest_data_b64('CHAES', @_) }
+sub chaes_b64u { Crypt::Digest::digest_data_b64u('CHAES', @_) }
+sub chaes_file { Crypt::Digest::digest_file('CHAES', @_) }
+sub chaes_file_hex { Crypt::Digest::digest_file_hex('CHAES', @_) }
+sub chaes_file_b64 { Crypt::Digest::digest_file_b64('CHAES', @_) }
+sub chaes_file_b64u { Crypt::Digest::digest_file_b64u('CHAES', @_) }
1;
diff --git a/lib/Crypt/Digest/Keccak224.pm b/lib/Crypt/Digest/Keccak224.pm
new file mode 100644
index 00000000..2b163297
--- /dev/null
+++ b/lib/Crypt/Digest/Keccak224.pm
@@ -0,0 +1,223 @@
+package Crypt::Digest::Keccak224;
+
+### BEWARE - GENERATED FILE, DO NOT EDIT MANUALLY!
+
+use strict;
+use warnings;
+our $VERSION = '0.059';
+
+use base qw(Crypt::Digest Exporter);
+our %EXPORT_TAGS = ( all => [qw( keccak224 keccak224_hex keccak224_b64 keccak224_b64u keccak224_file keccak224_file_hex keccak224_file_b64 keccak224_file_b64u )] );
+our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
+our @EXPORT = qw();
+
+use Carp;
+$Carp::Internal{(__PACKAGE__)}++;
+use Crypt::Digest;
+
+sub hashsize { Crypt::Digest::hashsize('Keccak224') }
+sub keccak224 { Crypt::Digest::digest_data('Keccak224', @_) }
+sub keccak224_hex { Crypt::Digest::digest_data_hex('Keccak224', @_) }
+sub keccak224_b64 { Crypt::Digest::digest_data_b64('Keccak224', @_) }
+sub keccak224_b64u { Crypt::Digest::digest_data_b64u('Keccak224', @_) }
+sub keccak224_file { Crypt::Digest::digest_file('Keccak224', @_) }
+sub keccak224_file_hex { Crypt::Digest::digest_file_hex('Keccak224', @_) }
+sub keccak224_file_b64 { Crypt::Digest::digest_file_b64('Keccak224', @_) }
+sub keccak224_file_b64u { Crypt::Digest::digest_file_b64u('Keccak224', @_) }
+
+1;
+
+=pod
+
+=head1 NAME
+
+Crypt::Digest::Keccak224 - Hash function Keccak-224 [size: 224 bits]
+
+=head1 SYNOPSIS
+
+ ### Functional interface:
+ use Crypt::Digest::Keccak224 qw( keccak224 keccak224_hex keccak224_b64 keccak224_b64u
+ keccak224_file keccak224_file_hex keccak224_file_b64 keccak224_file_b64u );
+
+ # calculate digest from string/buffer
+ $keccak224_raw = keccak224('data string');
+ $keccak224_hex = keccak224_hex('data string');
+ $keccak224_b64 = keccak224_b64('data string');
+ $keccak224_b64u = keccak224_b64u('data string');
+ # calculate digest from file
+ $keccak224_raw = keccak224_file('filename.dat');
+ $keccak224_hex = keccak224_file_hex('filename.dat');
+ $keccak224_b64 = keccak224_file_b64('filename.dat');
+ $keccak224_b64u = keccak224_file_b64u('filename.dat');
+ # calculate digest from filehandle
+ $keccak224_raw = keccak224_file(*FILEHANDLE);
+ $keccak224_hex = keccak224_file_hex(*FILEHANDLE);
+ $keccak224_b64 = keccak224_file_b64(*FILEHANDLE);
+ $keccak224_b64u = keccak224_file_b64u(*FILEHANDLE);
+
+ ### OO interface:
+ use Crypt::Digest::Keccak224;
+
+ $d = Crypt::Digest::Keccak224->new;
+ $d->add('any data');
+ $d->addfile('filename.dat');
+ $d->addfile(*FILEHANDLE);
+ $result_raw = $d->digest; # raw bytes
+ $result_hex = $d->hexdigest; # hexadecimal form
+ $result_b64 = $d->b64digest; # Base64 form
+ $result_b64u = $d->b64udigest; # Base64 URL Safe form
+
+=head1 DESCRIPTION
+
+Provides an interface to the Keccak224 digest algorithm.
+
+=head1 EXPORT
+
+Nothing is exported by default.
+
+You can export selected functions:
+
+ use Crypt::Digest::Keccak224 qw(keccak224 keccak224_hex keccak224_b64 keccak224_b64u
+ keccak224_file keccak224_file_hex keccak224_file_b64 keccak224_file_b64u);
+
+Or all of them at once:
+
+ use Crypt::Digest::Keccak224 ':all';
+
+=head1 FUNCTIONS
+
+=head2 keccak224
+
+Logically joins all arguments into a single string, and returns its Keccak224 digest encoded as a binary string.
+
+ $keccak224_raw = keccak224('data string');
+ #or
+ $keccak224_raw = keccak224('any data', 'more data', 'even more data');
+
+=head2 keccak224_hex
+
+Logically joins all arguments into a single string, and returns its Keccak224 digest encoded as a hexadecimal string.
+
+ $keccak224_hex = keccak224_hex('data string');
+ #or
+ $keccak224_hex = keccak224_hex('any data', 'more data', 'even more data');
+
+=head2 keccak224_b64
+
+Logically joins all arguments into a single string, and returns its Keccak224 digest encoded as a Base64 string, B<with> trailing '=' padding.
+
+ $keccak224_b64 = keccak224_b64('data string');
+ #or
+ $keccak224_b64 = keccak224_b64('any data', 'more data', 'even more data');
+
+=head2 keccak224_b64u
+
+Logically joins all arguments into a single string, and returns its Keccak224 digest encoded as a Base64 URL Safe string (see RFC 4648 section 5).
+
+ $keccak224_b64url = keccak224_b64u('data string');
+ #or
+ $keccak224_b64url = keccak224_b64u('any data', 'more data', 'even more data');
+
+=head2 keccak224_file
+
+Reads file (defined by filename or filehandle) content, and returns its Keccak224 digest encoded as a binary string.
+
+ $keccak224_raw = keccak224_file('filename.dat');
+ #or
+ $keccak224_raw = keccak224_file(*FILEHANDLE);
+
+=head2 keccak224_file_hex
+
+Reads file (defined by filename or filehandle) content, and returns its Keccak224 digest encoded as a hexadecimal string.
+
+ $keccak224_hex = keccak224_file_hex('filename.dat');
+ #or
+ $keccak224_hex = keccak224_file_hex(*FILEHANDLE);
+
+B<BEWARE:> You have to make sure that the filehandle is in binary mode before you pass it as argument to the addfile() method.
+
+=head2 keccak224_file_b64
+
+Reads file (defined by filename or filehandle) content, and returns its Keccak224 digest encoded as a Base64 string, B<with> trailing '=' padding.
+
+ $keccak224_b64 = keccak224_file_b64('filename.dat');
+ #or
+ $keccak224_b64 = keccak224_file_b64(*FILEHANDLE);
+
+=head2 keccak224_file_b64u
+
+Reads file (defined by filename or filehandle) content, and returns its Keccak224 digest encoded as a Base64 URL Safe string (see RFC 4648 section 5).
+
+ $keccak224_b64url = keccak224_file_b64u('filename.dat');
+ #or
+ $keccak224_b64url = keccak224_file_b64u(*FILEHANDLE);
+
+=head1 METHODS
+
+The OO interface provides the same set of functions as L<Crypt::Digest>.
+
+=head2 new
+
+ $d = Crypt::Digest::Keccak224->new();
+
+=head2 clone
+
+ $d->clone();
+
+=head2 reset
+
+ $d->reset();
+
+=head2 add
+
+ $d->add('any data');
+ #or
+ $d->add('any data', 'more data', 'even more data');
+
+=head2 addfile
+
+ $d->addfile('filename.dat');
+ #or
+ $d->addfile(*FILEHANDLE);
+
+=head2 add_bits
+
+ $d->add_bits($bit_string); # e.g. $d->add_bits("111100001010");
+ #or
+ $d->add_bits($data, $nbits); # e.g. $d->add_bits("\xF0\xA0", 16);
+
+=head2 hashsize
+
+ $d->hashsize;
+ #or
+ Crypt::Digest::Keccak224->hashsize();
+ #or
+ Crypt::Digest::Keccak224::hashsize();
+
+=head2 digest
+
+ $result_raw = $d->digest();
+
+=head2 hexdigest
+
+ $result_hex = $d->hexdigest();
+
+=head2 b64digest
+
+ $result_b64 = $d->b64digest();
+
+=head2 b64udigest
+
+ $result_b64url = $d->b64udigest();
+
+=head1 SEE ALSO
+
+=over
+
+=item * L<CryptX|CryptX>, L<Crypt::Digest>
+
+=item * L<https://keccak.team/index.html>
+
+=back
+
+=cut
diff --git a/lib/Crypt/Digest/Keccak256.pm b/lib/Crypt/Digest/Keccak256.pm
new file mode 100644
index 00000000..dfc7badc
--- /dev/null
+++ b/lib/Crypt/Digest/Keccak256.pm
@@ -0,0 +1,223 @@
+package Crypt::Digest::Keccak256;
+
+### BEWARE - GENERATED FILE, DO NOT EDIT MANUALLY!
+
+use strict;
+use warnings;
+our $VERSION = '0.059';
+
+use base qw(Crypt::Digest Exporter);
+our %EXPORT_TAGS = ( all => [qw( keccak256 keccak256_hex keccak256_b64 keccak256_b64u keccak256_file keccak256_file_hex keccak256_file_b64 keccak256_file_b64u )] );
+our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
+our @EXPORT = qw();
+
+use Carp;
+$Carp::Internal{(__PACKAGE__)}++;
+use Crypt::Digest;
+
+sub hashsize { Crypt::Digest::hashsize('Keccak256') }
+sub keccak256 { Crypt::Digest::digest_data('Keccak256', @_) }
+sub keccak256_hex { Crypt::Digest::digest_data_hex('Keccak256', @_) }
+sub keccak256_b64 { Crypt::Digest::digest_data_b64('Keccak256', @_) }
+sub keccak256_b64u { Crypt::Digest::digest_data_b64u('Keccak256', @_) }
+sub keccak256_file { Crypt::Digest::digest_file('Keccak256', @_) }
+sub keccak256_file_hex { Crypt::Digest::digest_file_hex('Keccak256', @_) }
+sub keccak256_file_b64 { Crypt::Digest::digest_file_b64('Keccak256', @_) }
+sub keccak256_file_b64u { Crypt::Digest::digest_file_b64u('Keccak256', @_) }
+
+1;
+
+=pod
+
+=head1 NAME
+
+Crypt::Digest::Keccak256 - Hash function Keccak-256 [size: 256 bits]
+
+=head1 SYNOPSIS
+
+ ### Functional interface:
+ use Crypt::Digest::Keccak256 qw( keccak256 keccak256_hex keccak256_b64 keccak256_b64u
+ keccak256_file keccak256_file_hex keccak256_file_b64 keccak256_file_b64u );
+
+ # calculate digest from string/buffer
+ $keccak256_raw = keccak256('data string');
+ $keccak256_hex = keccak256_hex('data string');
+ $keccak256_b64 = keccak256_b64('data string');
+ $keccak256_b64u = keccak256_b64u('data string');
+ # calculate digest from file
+ $keccak256_raw = keccak256_file('filename.dat');
+ $keccak256_hex = keccak256_file_hex('filename.dat');
+ $keccak256_b64 = keccak256_file_b64('filename.dat');
+ $keccak256_b64u = keccak256_file_b64u('filename.dat');
+ # calculate digest from filehandle
+ $keccak256_raw = keccak256_file(*FILEHANDLE);
+ $keccak256_hex = keccak256_file_hex(*FILEHANDLE);
+ $keccak256_b64 = keccak256_file_b64(*FILEHANDLE);
+ $keccak256_b64u = keccak256_file_b64u(*FILEHANDLE);
+
+ ### OO interface:
+ use Crypt::Digest::Keccak256;
+
+ $d = Crypt::Digest::Keccak256->new;
+ $d->add('any data');
+ $d->addfile('filename.dat');
+ $d->addfile(*FILEHANDLE);
+ $result_raw = $d->digest; # raw bytes
+ $result_hex = $d->hexdigest; # hexadecimal form
+ $result_b64 = $d->b64digest; # Base64 form
+ $result_b64u = $d->b64udigest; # Base64 URL Safe form
+
+=head1 DESCRIPTION
+
+Provides an interface to the Keccak256 digest algorithm.
+
+=head1 EXPORT
+
+Nothing is exported by default.
+
+You can export selected functions:
+
+ use Crypt::Digest::Keccak256 qw(keccak256 keccak256_hex keccak256_b64 keccak256_b64u
+ keccak256_file keccak256_file_hex keccak256_file_b64 keccak256_file_b64u);
+
+Or all of them at once:
+
+ use Crypt::Digest::Keccak256 ':all';
+
+=head1 FUNCTIONS
+
+=head2 keccak256
+
+Logically joins all arguments into a single string, and returns its Keccak256 digest encoded as a binary string.
+
+ $keccak256_raw = keccak256('data string');
+ #or
+ $keccak256_raw = keccak256('any data', 'more data', 'even more data');
+
+=head2 keccak256_hex
+
+Logically joins all arguments into a single string, and returns its Keccak256 digest encoded as a hexadecimal string.
+
+ $keccak256_hex = keccak256_hex('data string');
+ #or
+ $keccak256_hex = keccak256_hex('any data', 'more data', 'even more data');
+
+=head2 keccak256_b64
+
+Logically joins all arguments into a single string, and returns its Keccak256 digest encoded as a Base64 string, B<with> trailing '=' padding.
+
+ $keccak256_b64 = keccak256_b64('data string');
+ #or
+ $keccak256_b64 = keccak256_b64('any data', 'more data', 'even more data');
+
+=head2 keccak256_b64u
+
+Logically joins all arguments into a single string, and returns its Keccak256 digest encoded as a Base64 URL Safe string (see RFC 4648 section 5).
+
+ $keccak256_b64url = keccak256_b64u('data string');
+ #or
+ $keccak256_b64url = keccak256_b64u('any data', 'more data', 'even more data');
+
+=head2 keccak256_file
+
+Reads file (defined by filename or filehandle) content, and returns its Keccak256 digest encoded as a binary string.
+
+ $keccak256_raw = keccak256_file('filename.dat');
+ #or
+ $keccak256_raw = keccak256_file(*FILEHANDLE);
+
+=head2 keccak256_file_hex
+
+Reads file (defined by filename or filehandle) content, and returns its Keccak256 digest encoded as a hexadecimal string.
+
+ $keccak256_hex = keccak256_file_hex('filename.dat');
+ #or
+ $keccak256_hex = keccak256_file_hex(*FILEHANDLE);
+
+B<BEWARE:> You have to make sure that the filehandle is in binary mode before you pass it as argument to the addfile() method.
+
+=head2 keccak256_file_b64
+
+Reads file (defined by filename or filehandle) content, and returns its Keccak256 digest encoded as a Base64 string, B<with> trailing '=' padding.
+
+ $keccak256_b64 = keccak256_file_b64('filename.dat');
+ #or
+ $keccak256_b64 = keccak256_file_b64(*FILEHANDLE);
+
+=head2 keccak256_file_b64u
+
+Reads file (defined by filename or filehandle) content, and returns its Keccak256 digest encoded as a Base64 URL Safe string (see RFC 4648 section 5).
+
+ $keccak256_b64url = keccak256_file_b64u('filename.dat');
+ #or
+ $keccak256_b64url = keccak256_file_b64u(*FILEHANDLE);
+
+=head1 METHODS
+
+The OO interface provides the same set of functions as L<Crypt::Digest>.
+
+=head2 new
+
+ $d = Crypt::Digest::Keccak256->new();
+
+=head2 clone
+
+ $d->clone();
+
+=head2 reset
+
+ $d->reset();
+
+=head2 add
+
+ $d->add('any data');
+ #or
+ $d->add('any data', 'more data', 'even more data');
+
+=head2 addfile
+
+ $d->addfile('filename.dat');
+ #or
+ $d->addfile(*FILEHANDLE);
+
+=head2 add_bits
+
+ $d->add_bits($bit_string); # e.g. $d->add_bits("111100001010");
+ #or
+ $d->add_bits($data, $nbits); # e.g. $d->add_bits("\xF0\xA0", 16);
+
+=head2 hashsize
+
+ $d->hashsize;
+ #or
+ Crypt::Digest::Keccak256->hashsize();
+ #or
+ Crypt::Digest::Keccak256::hashsize();
+
+=head2 digest
+
+ $result_raw = $d->digest();
+
+=head2 hexdigest
+
+ $result_hex = $d->hexdigest();
+
+=head2 b64digest
+
+ $result_b64 = $d->b64digest();
+
+=head2 b64udigest
+
+ $result_b64url = $d->b64udigest();
+
+=head1 SEE ALSO
+
+=over
+
+=item * L<CryptX|CryptX>, L<Crypt::Digest>
+
+=item * L<https://keccak.team/index.html>
+
+=back
+
+=cut
diff --git a/lib/Crypt/Digest/Keccak384.pm b/lib/Crypt/Digest/Keccak384.pm
new file mode 100644
index 00000000..017c92d1
--- /dev/null
+++ b/lib/Crypt/Digest/Keccak384.pm
@@ -0,0 +1,223 @@
+package Crypt::Digest::Keccak384;
+
+### BEWARE - GENERATED FILE, DO NOT EDIT MANUALLY!
+
+use strict;
+use warnings;
+our $VERSION = '0.059';
+
+use base qw(Crypt::Digest Exporter);
+our %EXPORT_TAGS = ( all => [qw( keccak384 keccak384_hex keccak384_b64 keccak384_b64u keccak384_file keccak384_file_hex keccak384_file_b64 keccak384_file_b64u )] );
+our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
+our @EXPORT = qw();
+
+use Carp;
+$Carp::Internal{(__PACKAGE__)}++;
+use Crypt::Digest;
+
+sub hashsize { Crypt::Digest::hashsize('Keccak384') }
+sub keccak384 { Crypt::Digest::digest_data('Keccak384', @_) }
+sub keccak384_hex { Crypt::Digest::digest_data_hex('Keccak384', @_) }
+sub keccak384_b64 { Crypt::Digest::digest_data_b64('Keccak384', @_) }
+sub keccak384_b64u { Crypt::Digest::digest_data_b64u('Keccak384', @_) }
+sub keccak384_file { Crypt::Digest::digest_file('Keccak384', @_) }
+sub keccak384_file_hex { Crypt::Digest::digest_file_hex('Keccak384', @_) }
+sub keccak384_file_b64 { Crypt::Digest::digest_file_b64('Keccak384', @_) }
+sub keccak384_file_b64u { Crypt::Digest::digest_file_b64u('Keccak384', @_) }
+
+1;
+
+=pod
+
+=head1 NAME
+
+Crypt::Digest::Keccak384 - Hash function Keccak-384 [size: 384 bits]
+
+=head1 SYNOPSIS
+
+ ### Functional interface:
+ use Crypt::Digest::Keccak384 qw( keccak384 keccak384_hex keccak384_b64 keccak384_b64u
+ keccak384_file keccak384_file_hex keccak384_file_b64 keccak384_file_b64u );
+
+ # calculate digest from string/buffer
+ $keccak384_raw = keccak384('data string');
+ $keccak384_hex = keccak384_hex('data string');
+ $keccak384_b64 = keccak384_b64('data string');
+ $keccak384_b64u = keccak384_b64u('data string');
+ # calculate digest from file
+ $keccak384_raw = keccak384_file('filename.dat');
+ $keccak384_hex = keccak384_file_hex('filename.dat');
+ $keccak384_b64 = keccak384_file_b64('filename.dat');
+ $keccak384_b64u = keccak384_file_b64u('filename.dat');
+ # calculate digest from filehandle
+ $keccak384_raw = keccak384_file(*FILEHANDLE);
+ $keccak384_hex = keccak384_file_hex(*FILEHANDLE);
+ $keccak384_b64 = keccak384_file_b64(*FILEHANDLE);
+ $keccak384_b64u = keccak384_file_b64u(*FILEHANDLE);
+
+ ### OO interface:
+ use Crypt::Digest::Keccak384;
+
+ $d = Crypt::Digest::Keccak384->new;
+ $d->add('any data');
+ $d->addfile('filename.dat');
+ $d->addfile(*FILEHANDLE);
+ $result_raw = $d->digest; # raw bytes
+ $result_hex = $d->hexdigest; # hexadecimal form
+ $result_b64 = $d->b64digest; # Base64 form
+ $result_b64u = $d->b64udigest; # Base64 URL Safe form
+
+=head1 DESCRIPTION
+
+Provides an interface to the Keccak384 digest algorithm.
+
+=head1 EXPORT
+
+Nothing is exported by default.
+
+You can export selected functions:
+
+ use Crypt::Digest::Keccak384 qw(keccak384 keccak384_hex keccak384_b64 keccak384_b64u
+ keccak384_file keccak384_file_hex keccak384_file_b64 keccak384_file_b64u);
+
+Or all of them at once:
+
+ use Crypt::Digest::Keccak384 ':all';
+
+=head1 FUNCTIONS
+
+=head2 keccak384
+
+Logically joins all arguments into a single string, and returns its Keccak384 digest encoded as a binary string.
+
+ $keccak384_raw = keccak384('data string');
+ #or
+ $keccak384_raw = keccak384('any data', 'more data', 'even more data');
+
+=head2 keccak384_hex
+
+Logically joins all arguments into a single string, and returns its Keccak384 digest encoded as a hexadecimal string.
+
+ $keccak384_hex = keccak384_hex('data string');
+ #or
+ $keccak384_hex = keccak384_hex('any data', 'more data', 'even more data');
+
+=head2 keccak384_b64
+
+Logically joins all arguments into a single string, and returns its Keccak384 digest encoded as a Base64 string, B<with> trailing '=' padding.
+
+ $keccak384_b64 = keccak384_b64('data string');
+ #or
+ $keccak384_b64 = keccak384_b64('any data', 'more data', 'even more data');
+
+=head2 keccak384_b64u
+
+Logically joins all arguments into a single string, and returns its Keccak384 digest encoded as a Base64 URL Safe string (see RFC 4648 section 5).
+
+ $keccak384_b64url = keccak384_b64u('data string');
+ #or
+ $keccak384_b64url = keccak384_b64u('any data', 'more data', 'even more data');
+
+=head2 keccak384_file
+
+Reads file (defined by filename or filehandle) content, and returns its Keccak384 digest encoded as a binary string.
+
+ $keccak384_raw = keccak384_file('filename.dat');
+ #or
+ $keccak384_raw = keccak384_file(*FILEHANDLE);
+
+=head2 keccak384_file_hex
+
+Reads file (defined by filename or filehandle) content, and returns its Keccak384 digest encoded as a hexadecimal string.
+
+ $keccak384_hex = keccak384_file_hex('filename.dat');
+ #or
+ $keccak384_hex = keccak384_file_hex(*FILEHANDLE);
+
+B<BEWARE:> You have to make sure that the filehandle is in binary mode before you pass it as argument to the addfile() method.
+
+=head2 keccak384_file_b64
+
+Reads file (defined by filename or filehandle) content, and returns its Keccak384 digest encoded as a Base64 string, B<with> trailing '=' padding.
+
+ $keccak384_b64 = keccak384_file_b64('filename.dat');
+ #or
+ $keccak384_b64 = keccak384_file_b64(*FILEHANDLE);
+
+=head2 keccak384_file_b64u
+
+Reads file (defined by filename or filehandle) content, and returns its Keccak384 digest encoded as a Base64 URL Safe string (see RFC 4648 section 5).
+
+ $keccak384_b64url = keccak384_file_b64u('filename.dat');
+ #or
+ $keccak384_b64url = keccak384_file_b64u(*FILEHANDLE);
+
+=head1 METHODS
+
+The OO interface provides the same set of functions as L<Crypt::Digest>.
+
+=head2 new
+
+ $d = Crypt::Digest::Keccak384->new();
+
+=head2 clone
+
+ $d->clone();
+
+=head2 reset
+
+ $d->reset();
+
+=head2 add
+
+ $d->add('any data');
+ #or
+ $d->add('any data', 'more data', 'even more data');
+
+=head2 addfile
+
+ $d->addfile('filename.dat');
+ #or
+ $d->addfile(*FILEHANDLE);
+
+=head2 add_bits
+
+ $d->add_bits($bit_string); # e.g. $d->add_bits("111100001010");
+ #or
+ $d->add_bits($data, $nbits); # e.g. $d->add_bits("\xF0\xA0", 16);
+
+=head2 hashsize
+
+ $d->hashsize;
+ #or
+ Crypt::Digest::Keccak384->hashsize();
+ #or
+ Crypt::Digest::Keccak384::hashsize();
+
+=head2 digest
+
+ $result_raw = $d->digest();
+
+=head2 hexdigest
+
+ $result_hex = $d->hexdigest();
+
+=head2 b64digest
+
+ $result_b64 = $d->b64digest();
+
+=head2 b64udigest
+
+ $result_b64url = $d->b64udigest();
+
+=head1 SEE ALSO
+
+=over
+
+=item * L<CryptX|CryptX>, L<Crypt::Digest>
+
+=item * L<https://keccak.team/index.html>
+
+=back
+
+=cut
diff --git a/lib/Crypt/Digest/Keccak512.pm b/lib/Crypt/Digest/Keccak512.pm
new file mode 100644
index 00000000..9a54bc15
--- /dev/null
+++ b/lib/Crypt/Digest/Keccak512.pm
@@ -0,0 +1,223 @@
+package Crypt::Digest::Keccak512;
+
+### BEWARE - GENERATED FILE, DO NOT EDIT MANUALLY!
+
+use strict;
+use warnings;
+our $VERSION = '0.059';
+
+use base qw(Crypt::Digest Exporter);
+our %EXPORT_TAGS = ( all => [qw( keccak512 keccak512_hex keccak512_b64 keccak512_b64u keccak512_file keccak512_file_hex keccak512_file_b64 keccak512_file_b64u )] );
+our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
+our @EXPORT = qw();
+
+use Carp;
+$Carp::Internal{(__PACKAGE__)}++;
+use Crypt::Digest;
+
+sub hashsize { Crypt::Digest::hashsize('Keccak512') }
+sub keccak512 { Crypt::Digest::digest_data('Keccak512', @_) }
+sub keccak512_hex { Crypt::Digest::digest_data_hex('Keccak512', @_) }
+sub keccak512_b64 { Crypt::Digest::digest_data_b64('Keccak512', @_) }
+sub keccak512_b64u { Crypt::Digest::digest_data_b64u('Keccak512', @_) }
+sub keccak512_file { Crypt::Digest::digest_file('Keccak512', @_) }
+sub keccak512_file_hex { Crypt::Digest::digest_file_hex('Keccak512', @_) }
+sub keccak512_file_b64 { Crypt::Digest::digest_file_b64('Keccak512', @_) }
+sub keccak512_file_b64u { Crypt::Digest::digest_file_b64u('Keccak512', @_) }
+
+1;
+
+=pod
+
+=head1 NAME
+
+Crypt::Digest::Keccak512 - Hash function Keccak-512 [size: 512 bits]
+
+=head1 SYNOPSIS
+
+ ### Functional interface:
+ use Crypt::Digest::Keccak512 qw( keccak512 keccak512_hex keccak512_b64 keccak512_b64u
+ keccak512_file keccak512_file_hex keccak512_file_b64 keccak512_file_b64u );
+
+ # calculate digest from string/buffer
+ $keccak512_raw = keccak512('data string');
+ $keccak512_hex = keccak512_hex('data string');
+ $keccak512_b64 = keccak512_b64('data string');
+ $keccak512_b64u = keccak512_b64u('data string');
+ # calculate digest from file
+ $keccak512_raw = keccak512_file('filename.dat');
+ $keccak512_hex = keccak512_file_hex('filename.dat');
+ $keccak512_b64 = keccak512_file_b64('filename.dat');
+ $keccak512_b64u = keccak512_file_b64u('filename.dat');
+ # calculate digest from filehandle
+ $keccak512_raw = keccak512_file(*FILEHANDLE);
+ $keccak512_hex = keccak512_file_hex(*FILEHANDLE);
+ $keccak512_b64 = keccak512_file_b64(*FILEHANDLE);
+ $keccak512_b64u = keccak512_file_b64u(*FILEHANDLE);
+
+ ### OO interface:
+ use Crypt::Digest::Keccak512;
+
+ $d = Crypt::Digest::Keccak512->new;
+ $d->add('any data');
+ $d->addfile('filename.dat');
+ $d->addfile(*FILEHANDLE);
+ $result_raw = $d->digest; # raw bytes
+ $result_hex = $d->hexdigest; # hexadecimal form
+ $result_b64 = $d->b64digest; # Base64 form
+ $result_b64u = $d->b64udigest; # Base64 URL Safe form
+
+=head1 DESCRIPTION
+
+Provides an interface to the Keccak512 digest algorithm.
+
+=head1 EXPORT
+
+Nothing is exported by default.
+
+You can export selected functions:
+
+ use Crypt::Digest::Keccak512 qw(keccak512 keccak512_hex keccak512_b64 keccak512_b64u
+ keccak512_file keccak512_file_hex keccak512_file_b64 keccak512_file_b64u);
+
+Or all of them at once:
+
+ use Crypt::Digest::Keccak512 ':all';
+
+=head1 FUNCTIONS
+
+=head2 keccak512
+
+Logically joins all arguments into a single string, and returns its Keccak512 digest encoded as a binary string.
+
+ $keccak512_raw = keccak512('data string');
+ #or
+ $keccak512_raw = keccak512('any data', 'more data', 'even more data');
+
+=head2 keccak512_hex
+
+Logically joins all arguments into a single string, and returns its Keccak512 digest encoded as a hexadecimal string.
+
+ $keccak512_hex = keccak512_hex('data string');
+ #or
+ $keccak512_hex = keccak512_hex('any data', 'more data', 'even more data');
+
+=head2 keccak512_b64
+
+Logically joins all arguments into a single string, and returns its Keccak512 digest encoded as a Base64 string, B<with> trailing '=' padding.
+
+ $keccak512_b64 = keccak512_b64('data string');
+ #or
+ $keccak512_b64 = keccak512_b64('any data', 'more data', 'even more data');
+
+=head2 keccak512_b64u
+
+Logically joins all arguments into a single string, and returns its Keccak512 digest encoded as a Base64 URL Safe string (see RFC 4648 section 5).
+
+ $keccak512_b64url = keccak512_b64u('data string');
+ #or
+ $keccak512_b64url = keccak512_b64u('any data', 'more data', 'even more data');
+
+=head2 keccak512_file
+
+Reads file (defined by filename or filehandle) content, and returns its Keccak512 digest encoded as a binary string.
+
+ $keccak512_raw = keccak512_file('filename.dat');
+ #or
+ $keccak512_raw = keccak512_file(*FILEHANDLE);
+
+=head2 keccak512_file_hex
+
+Reads file (defined by filename or filehandle) content, and returns its Keccak512 digest encoded as a hexadecimal string.
+
+ $keccak512_hex = keccak512_file_hex('filename.dat');
+ #or
+ $keccak512_hex = keccak512_file_hex(*FILEHANDLE);
+
+B<BEWARE:> You have to make sure that the filehandle is in binary mode before you pass it as argument to the addfile() method.
+
+=head2 keccak512_file_b64
+
+Reads file (defined by filename or filehandle) content, and returns its Keccak512 digest encoded as a Base64 string, B<with> trailing '=' padding.
+
+ $keccak512_b64 = keccak512_file_b64('filename.dat');
+ #or
+ $keccak512_b64 = keccak512_file_b64(*FILEHANDLE);
+
+=head2 keccak512_file_b64u
+
+Reads file (defined by filename or filehandle) content, and returns its Keccak512 digest encoded as a Base64 URL Safe string (see RFC 4648 section 5).
+
+ $keccak512_b64url = keccak512_file_b64u('filename.dat');
+ #or
+ $keccak512_b64url = keccak512_file_b64u(*FILEHANDLE);
+
+=head1 METHODS
+
+The OO interface provides the same set of functions as L<Crypt::Digest>.
+
+=head2 new
+
+ $d = Crypt::Digest::Keccak512->new();
+
+=head2 clone
+
+ $d->clone();
+
+=head2 reset
+
+ $d->reset();
+
+=head2 add
+
+ $d->add('any data');
+ #or
+ $d->add('any data', 'more data', 'even more data');
+
+=head2 addfile
+
+ $d->addfile('filename.dat');
+ #or
+ $d->addfile(*FILEHANDLE);
+
+=head2 add_bits
+
+ $d->add_bits($bit_string); # e.g. $d->add_bits("111100001010");
+ #or
+ $d->add_bits($data, $nbits); # e.g. $d->add_bits("\xF0\xA0", 16);
+
+=head2 hashsize
+
+ $d->hashsize;
+ #or
+ Crypt::Digest::Keccak512->hashsize();
+ #or
+ Crypt::Digest::Keccak512::hashsize();
+
+=head2 digest
+
+ $result_raw = $d->digest();
+
+=head2 hexdigest
+
+ $result_hex = $d->hexdigest();
+
+=head2 b64digest
+
+ $result_b64 = $d->b64digest();
+
+=head2 b64udigest
+
+ $result_b64url = $d->b64udigest();
+
+=head1 SEE ALSO
+
+=over
+
+=item * L<CryptX|CryptX>, L<Crypt::Digest>
+
+=item * L<https://keccak.team/index.html>
+
+=back
+
+=cut
diff --git a/lib/Crypt/Digest/MD2.pm b/lib/Crypt/Digest/MD2.pm
index 9d1d5d16..4097df1b 100644
--- a/lib/Crypt/Digest/MD2.pm
+++ b/lib/Crypt/Digest/MD2.pm
@@ -4,7 +4,7 @@ package Crypt::Digest::MD2;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::Digest Exporter);
our %EXPORT_TAGS = ( all => [qw( md2 md2_hex md2_b64 md2_b64u md2_file md2_file_hex md2_file_b64 md2_file_b64u )] );
@@ -13,19 +13,17 @@ our @EXPORT = qw();
use Carp;
$Carp::Internal{(__PACKAGE__)}++;
-use CryptX;
-
-sub hashsize { Crypt::Digest::hashsize(__PACKAGE__) }
-
-sub md2 { Crypt::Digest::digest_data(__PACKAGE__, @_) }
-sub md2_hex { Crypt::Digest::digest_data_hex(__PACKAGE__, @_) }
-sub md2_b64 { Crypt::Digest::digest_data_b64(__PACKAGE__, @_) }
-sub md2_b64u { Crypt::Digest::digest_data_b64u(__PACKAGE__, @_) }
-
-sub md2_file { Crypt::Digest::digest_file(__PACKAGE__, @_) }
-sub md2_file_hex { Crypt::Digest::digest_file_hex(__PACKAGE__, @_) }
-sub md2_file_b64 { Crypt::Digest::digest_file_b64(__PACKAGE__, @_) }
-sub md2_file_b64u { Crypt::Digest::digest_file_b64u(__PACKAGE__, @_) }
+use Crypt::Digest;
+
+sub hashsize { Crypt::Digest::hashsize('MD2') }
+sub md2 { Crypt::Digest::digest_data('MD2', @_) }
+sub md2_hex { Crypt::Digest::digest_data_hex('MD2', @_) }
+sub md2_b64 { Crypt::Digest::digest_data_b64('MD2', @_) }
+sub md2_b64u { Crypt::Digest::digest_data_b64u('MD2', @_) }
+sub md2_file { Crypt::Digest::digest_file('MD2', @_) }
+sub md2_file_hex { Crypt::Digest::digest_file_hex('MD2', @_) }
+sub md2_file_b64 { Crypt::Digest::digest_file_b64('MD2', @_) }
+sub md2_file_b64u { Crypt::Digest::digest_file_b64u('MD2', @_) }
1;
diff --git a/lib/Crypt/Digest/MD4.pm b/lib/Crypt/Digest/MD4.pm
index 2e1171ab..d8e6d447 100644
--- a/lib/Crypt/Digest/MD4.pm
+++ b/lib/Crypt/Digest/MD4.pm
@@ -4,7 +4,7 @@ package Crypt::Digest::MD4;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::Digest Exporter);
our %EXPORT_TAGS = ( all => [qw( md4 md4_hex md4_b64 md4_b64u md4_file md4_file_hex md4_file_b64 md4_file_b64u )] );
@@ -13,19 +13,17 @@ our @EXPORT = qw();
use Carp;
$Carp::Internal{(__PACKAGE__)}++;
-use CryptX;
-
-sub hashsize { Crypt::Digest::hashsize(__PACKAGE__) }
-
-sub md4 { Crypt::Digest::digest_data(__PACKAGE__, @_) }
-sub md4_hex { Crypt::Digest::digest_data_hex(__PACKAGE__, @_) }
-sub md4_b64 { Crypt::Digest::digest_data_b64(__PACKAGE__, @_) }
-sub md4_b64u { Crypt::Digest::digest_data_b64u(__PACKAGE__, @_) }
-
-sub md4_file { Crypt::Digest::digest_file(__PACKAGE__, @_) }
-sub md4_file_hex { Crypt::Digest::digest_file_hex(__PACKAGE__, @_) }
-sub md4_file_b64 { Crypt::Digest::digest_file_b64(__PACKAGE__, @_) }
-sub md4_file_b64u { Crypt::Digest::digest_file_b64u(__PACKAGE__, @_) }
+use Crypt::Digest;
+
+sub hashsize { Crypt::Digest::hashsize('MD4') }
+sub md4 { Crypt::Digest::digest_data('MD4', @_) }
+sub md4_hex { Crypt::Digest::digest_data_hex('MD4', @_) }
+sub md4_b64 { Crypt::Digest::digest_data_b64('MD4', @_) }
+sub md4_b64u { Crypt::Digest::digest_data_b64u('MD4', @_) }
+sub md4_file { Crypt::Digest::digest_file('MD4', @_) }
+sub md4_file_hex { Crypt::Digest::digest_file_hex('MD4', @_) }
+sub md4_file_b64 { Crypt::Digest::digest_file_b64('MD4', @_) }
+sub md4_file_b64u { Crypt::Digest::digest_file_b64u('MD4', @_) }
1;
diff --git a/lib/Crypt/Digest/MD5.pm b/lib/Crypt/Digest/MD5.pm
index 27842228..65d99ee9 100644
--- a/lib/Crypt/Digest/MD5.pm
+++ b/lib/Crypt/Digest/MD5.pm
@@ -4,7 +4,7 @@ package Crypt::Digest::MD5;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::Digest Exporter);
our %EXPORT_TAGS = ( all => [qw( md5 md5_hex md5_b64 md5_b64u md5_file md5_file_hex md5_file_b64 md5_file_b64u )] );
@@ -13,19 +13,17 @@ our @EXPORT = qw();
use Carp;
$Carp::Internal{(__PACKAGE__)}++;
-use CryptX;
-
-sub hashsize { Crypt::Digest::hashsize(__PACKAGE__) }
-
-sub md5 { Crypt::Digest::digest_data(__PACKAGE__, @_) }
-sub md5_hex { Crypt::Digest::digest_data_hex(__PACKAGE__, @_) }
-sub md5_b64 { Crypt::Digest::digest_data_b64(__PACKAGE__, @_) }
-sub md5_b64u { Crypt::Digest::digest_data_b64u(__PACKAGE__, @_) }
-
-sub md5_file { Crypt::Digest::digest_file(__PACKAGE__, @_) }
-sub md5_file_hex { Crypt::Digest::digest_file_hex(__PACKAGE__, @_) }
-sub md5_file_b64 { Crypt::Digest::digest_file_b64(__PACKAGE__, @_) }
-sub md5_file_b64u { Crypt::Digest::digest_file_b64u(__PACKAGE__, @_) }
+use Crypt::Digest;
+
+sub hashsize { Crypt::Digest::hashsize('MD5') }
+sub md5 { Crypt::Digest::digest_data('MD5', @_) }
+sub md5_hex { Crypt::Digest::digest_data_hex('MD5', @_) }
+sub md5_b64 { Crypt::Digest::digest_data_b64('MD5', @_) }
+sub md5_b64u { Crypt::Digest::digest_data_b64u('MD5', @_) }
+sub md5_file { Crypt::Digest::digest_file('MD5', @_) }
+sub md5_file_hex { Crypt::Digest::digest_file_hex('MD5', @_) }
+sub md5_file_b64 { Crypt::Digest::digest_file_b64('MD5', @_) }
+sub md5_file_b64u { Crypt::Digest::digest_file_b64u('MD5', @_) }
1;
diff --git a/lib/Crypt/Digest/RIPEMD128.pm b/lib/Crypt/Digest/RIPEMD128.pm
index 60a41c11..1683b212 100644
--- a/lib/Crypt/Digest/RIPEMD128.pm
+++ b/lib/Crypt/Digest/RIPEMD128.pm
@@ -4,7 +4,7 @@ package Crypt::Digest::RIPEMD128;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::Digest Exporter);
our %EXPORT_TAGS = ( all => [qw( ripemd128 ripemd128_hex ripemd128_b64 ripemd128_b64u ripemd128_file ripemd128_file_hex ripemd128_file_b64 ripemd128_file_b64u )] );
@@ -13,19 +13,17 @@ our @EXPORT = qw();
use Carp;
$Carp::Internal{(__PACKAGE__)}++;
-use CryptX;
-
-sub hashsize { Crypt::Digest::hashsize(__PACKAGE__) }
-
-sub ripemd128 { Crypt::Digest::digest_data(__PACKAGE__, @_) }
-sub ripemd128_hex { Crypt::Digest::digest_data_hex(__PACKAGE__, @_) }
-sub ripemd128_b64 { Crypt::Digest::digest_data_b64(__PACKAGE__, @_) }
-sub ripemd128_b64u { Crypt::Digest::digest_data_b64u(__PACKAGE__, @_) }
-
-sub ripemd128_file { Crypt::Digest::digest_file(__PACKAGE__, @_) }
-sub ripemd128_file_hex { Crypt::Digest::digest_file_hex(__PACKAGE__, @_) }
-sub ripemd128_file_b64 { Crypt::Digest::digest_file_b64(__PACKAGE__, @_) }
-sub ripemd128_file_b64u { Crypt::Digest::digest_file_b64u(__PACKAGE__, @_) }
+use Crypt::Digest;
+
+sub hashsize { Crypt::Digest::hashsize('RIPEMD128') }
+sub ripemd128 { Crypt::Digest::digest_data('RIPEMD128', @_) }
+sub ripemd128_hex { Crypt::Digest::digest_data_hex('RIPEMD128', @_) }
+sub ripemd128_b64 { Crypt::Digest::digest_data_b64('RIPEMD128', @_) }
+sub ripemd128_b64u { Crypt::Digest::digest_data_b64u('RIPEMD128', @_) }
+sub ripemd128_file { Crypt::Digest::digest_file('RIPEMD128', @_) }
+sub ripemd128_file_hex { Crypt::Digest::digest_file_hex('RIPEMD128', @_) }
+sub ripemd128_file_b64 { Crypt::Digest::digest_file_b64('RIPEMD128', @_) }
+sub ripemd128_file_b64u { Crypt::Digest::digest_file_b64u('RIPEMD128', @_) }
1;
diff --git a/lib/Crypt/Digest/RIPEMD160.pm b/lib/Crypt/Digest/RIPEMD160.pm
index 574b2570..7dcc7851 100644
--- a/lib/Crypt/Digest/RIPEMD160.pm
+++ b/lib/Crypt/Digest/RIPEMD160.pm
@@ -4,7 +4,7 @@ package Crypt::Digest::RIPEMD160;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::Digest Exporter);
our %EXPORT_TAGS = ( all => [qw( ripemd160 ripemd160_hex ripemd160_b64 ripemd160_b64u ripemd160_file ripemd160_file_hex ripemd160_file_b64 ripemd160_file_b64u )] );
@@ -13,19 +13,17 @@ our @EXPORT = qw();
use Carp;
$Carp::Internal{(__PACKAGE__)}++;
-use CryptX;
-
-sub hashsize { Crypt::Digest::hashsize(__PACKAGE__) }
-
-sub ripemd160 { Crypt::Digest::digest_data(__PACKAGE__, @_) }
-sub ripemd160_hex { Crypt::Digest::digest_data_hex(__PACKAGE__, @_) }
-sub ripemd160_b64 { Crypt::Digest::digest_data_b64(__PACKAGE__, @_) }
-sub ripemd160_b64u { Crypt::Digest::digest_data_b64u(__PACKAGE__, @_) }
-
-sub ripemd160_file { Crypt::Digest::digest_file(__PACKAGE__, @_) }
-sub ripemd160_file_hex { Crypt::Digest::digest_file_hex(__PACKAGE__, @_) }
-sub ripemd160_file_b64 { Crypt::Digest::digest_file_b64(__PACKAGE__, @_) }
-sub ripemd160_file_b64u { Crypt::Digest::digest_file_b64u(__PACKAGE__, @_) }
+use Crypt::Digest;
+
+sub hashsize { Crypt::Digest::hashsize('RIPEMD160') }
+sub ripemd160 { Crypt::Digest::digest_data('RIPEMD160', @_) }
+sub ripemd160_hex { Crypt::Digest::digest_data_hex('RIPEMD160', @_) }
+sub ripemd160_b64 { Crypt::Digest::digest_data_b64('RIPEMD160', @_) }
+sub ripemd160_b64u { Crypt::Digest::digest_data_b64u('RIPEMD160', @_) }
+sub ripemd160_file { Crypt::Digest::digest_file('RIPEMD160', @_) }
+sub ripemd160_file_hex { Crypt::Digest::digest_file_hex('RIPEMD160', @_) }
+sub ripemd160_file_b64 { Crypt::Digest::digest_file_b64('RIPEMD160', @_) }
+sub ripemd160_file_b64u { Crypt::Digest::digest_file_b64u('RIPEMD160', @_) }
1;
diff --git a/lib/Crypt/Digest/RIPEMD256.pm b/lib/Crypt/Digest/RIPEMD256.pm
index 7909090f..f7ff62ae 100644
--- a/lib/Crypt/Digest/RIPEMD256.pm
+++ b/lib/Crypt/Digest/RIPEMD256.pm
@@ -4,7 +4,7 @@ package Crypt::Digest::RIPEMD256;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::Digest Exporter);
our %EXPORT_TAGS = ( all => [qw( ripemd256 ripemd256_hex ripemd256_b64 ripemd256_b64u ripemd256_file ripemd256_file_hex ripemd256_file_b64 ripemd256_file_b64u )] );
@@ -13,19 +13,17 @@ our @EXPORT = qw();
use Carp;
$Carp::Internal{(__PACKAGE__)}++;
-use CryptX;
-
-sub hashsize { Crypt::Digest::hashsize(__PACKAGE__) }
-
-sub ripemd256 { Crypt::Digest::digest_data(__PACKAGE__, @_) }
-sub ripemd256_hex { Crypt::Digest::digest_data_hex(__PACKAGE__, @_) }
-sub ripemd256_b64 { Crypt::Digest::digest_data_b64(__PACKAGE__, @_) }
-sub ripemd256_b64u { Crypt::Digest::digest_data_b64u(__PACKAGE__, @_) }
-
-sub ripemd256_file { Crypt::Digest::digest_file(__PACKAGE__, @_) }
-sub ripemd256_file_hex { Crypt::Digest::digest_file_hex(__PACKAGE__, @_) }
-sub ripemd256_file_b64 { Crypt::Digest::digest_file_b64(__PACKAGE__, @_) }
-sub ripemd256_file_b64u { Crypt::Digest::digest_file_b64u(__PACKAGE__, @_) }
+use Crypt::Digest;
+
+sub hashsize { Crypt::Digest::hashsize('RIPEMD256') }
+sub ripemd256 { Crypt::Digest::digest_data('RIPEMD256', @_) }
+sub ripemd256_hex { Crypt::Digest::digest_data_hex('RIPEMD256', @_) }
+sub ripemd256_b64 { Crypt::Digest::digest_data_b64('RIPEMD256', @_) }
+sub ripemd256_b64u { Crypt::Digest::digest_data_b64u('RIPEMD256', @_) }
+sub ripemd256_file { Crypt::Digest::digest_file('RIPEMD256', @_) }
+sub ripemd256_file_hex { Crypt::Digest::digest_file_hex('RIPEMD256', @_) }
+sub ripemd256_file_b64 { Crypt::Digest::digest_file_b64('RIPEMD256', @_) }
+sub ripemd256_file_b64u { Crypt::Digest::digest_file_b64u('RIPEMD256', @_) }
1;
diff --git a/lib/Crypt/Digest/RIPEMD320.pm b/lib/Crypt/Digest/RIPEMD320.pm
index 4868aeda..c2e8e0d0 100644
--- a/lib/Crypt/Digest/RIPEMD320.pm
+++ b/lib/Crypt/Digest/RIPEMD320.pm
@@ -4,7 +4,7 @@ package Crypt::Digest::RIPEMD320;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::Digest Exporter);
our %EXPORT_TAGS = ( all => [qw( ripemd320 ripemd320_hex ripemd320_b64 ripemd320_b64u ripemd320_file ripemd320_file_hex ripemd320_file_b64 ripemd320_file_b64u )] );
@@ -13,19 +13,17 @@ our @EXPORT = qw();
use Carp;
$Carp::Internal{(__PACKAGE__)}++;
-use CryptX;
-
-sub hashsize { Crypt::Digest::hashsize(__PACKAGE__) }
-
-sub ripemd320 { Crypt::Digest::digest_data(__PACKAGE__, @_) }
-sub ripemd320_hex { Crypt::Digest::digest_data_hex(__PACKAGE__, @_) }
-sub ripemd320_b64 { Crypt::Digest::digest_data_b64(__PACKAGE__, @_) }
-sub ripemd320_b64u { Crypt::Digest::digest_data_b64u(__PACKAGE__, @_) }
-
-sub ripemd320_file { Crypt::Digest::digest_file(__PACKAGE__, @_) }
-sub ripemd320_file_hex { Crypt::Digest::digest_file_hex(__PACKAGE__, @_) }
-sub ripemd320_file_b64 { Crypt::Digest::digest_file_b64(__PACKAGE__, @_) }
-sub ripemd320_file_b64u { Crypt::Digest::digest_file_b64u(__PACKAGE__, @_) }
+use Crypt::Digest;
+
+sub hashsize { Crypt::Digest::hashsize('RIPEMD320') }
+sub ripemd320 { Crypt::Digest::digest_data('RIPEMD320', @_) }
+sub ripemd320_hex { Crypt::Digest::digest_data_hex('RIPEMD320', @_) }
+sub ripemd320_b64 { Crypt::Digest::digest_data_b64('RIPEMD320', @_) }
+sub ripemd320_b64u { Crypt::Digest::digest_data_b64u('RIPEMD320', @_) }
+sub ripemd320_file { Crypt::Digest::digest_file('RIPEMD320', @_) }
+sub ripemd320_file_hex { Crypt::Digest::digest_file_hex('RIPEMD320', @_) }
+sub ripemd320_file_b64 { Crypt::Digest::digest_file_b64('RIPEMD320', @_) }
+sub ripemd320_file_b64u { Crypt::Digest::digest_file_b64u('RIPEMD320', @_) }
1;
diff --git a/lib/Crypt/Digest/SHA1.pm b/lib/Crypt/Digest/SHA1.pm
index fcabebdc..9e994d0c 100644
--- a/lib/Crypt/Digest/SHA1.pm
+++ b/lib/Crypt/Digest/SHA1.pm
@@ -4,7 +4,7 @@ package Crypt::Digest::SHA1;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::Digest Exporter);
our %EXPORT_TAGS = ( all => [qw( sha1 sha1_hex sha1_b64 sha1_b64u sha1_file sha1_file_hex sha1_file_b64 sha1_file_b64u )] );
@@ -13,19 +13,17 @@ our @EXPORT = qw();
use Carp;
$Carp::Internal{(__PACKAGE__)}++;
-use CryptX;
-
-sub hashsize { Crypt::Digest::hashsize(__PACKAGE__) }
-
-sub sha1 { Crypt::Digest::digest_data(__PACKAGE__, @_) }
-sub sha1_hex { Crypt::Digest::digest_data_hex(__PACKAGE__, @_) }
-sub sha1_b64 { Crypt::Digest::digest_data_b64(__PACKAGE__, @_) }
-sub sha1_b64u { Crypt::Digest::digest_data_b64u(__PACKAGE__, @_) }
-
-sub sha1_file { Crypt::Digest::digest_file(__PACKAGE__, @_) }
-sub sha1_file_hex { Crypt::Digest::digest_file_hex(__PACKAGE__, @_) }
-sub sha1_file_b64 { Crypt::Digest::digest_file_b64(__PACKAGE__, @_) }
-sub sha1_file_b64u { Crypt::Digest::digest_file_b64u(__PACKAGE__, @_) }
+use Crypt::Digest;
+
+sub hashsize { Crypt::Digest::hashsize('SHA1') }
+sub sha1 { Crypt::Digest::digest_data('SHA1', @_) }
+sub sha1_hex { Crypt::Digest::digest_data_hex('SHA1', @_) }
+sub sha1_b64 { Crypt::Digest::digest_data_b64('SHA1', @_) }
+sub sha1_b64u { Crypt::Digest::digest_data_b64u('SHA1', @_) }
+sub sha1_file { Crypt::Digest::digest_file('SHA1', @_) }
+sub sha1_file_hex { Crypt::Digest::digest_file_hex('SHA1', @_) }
+sub sha1_file_b64 { Crypt::Digest::digest_file_b64('SHA1', @_) }
+sub sha1_file_b64u { Crypt::Digest::digest_file_b64u('SHA1', @_) }
1;
diff --git a/lib/Crypt/Digest/SHA224.pm b/lib/Crypt/Digest/SHA224.pm
index da34dd31..5afdac75 100644
--- a/lib/Crypt/Digest/SHA224.pm
+++ b/lib/Crypt/Digest/SHA224.pm
@@ -4,7 +4,7 @@ package Crypt::Digest::SHA224;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::Digest Exporter);
our %EXPORT_TAGS = ( all => [qw( sha224 sha224_hex sha224_b64 sha224_b64u sha224_file sha224_file_hex sha224_file_b64 sha224_file_b64u )] );
@@ -13,19 +13,17 @@ our @EXPORT = qw();
use Carp;
$Carp::Internal{(__PACKAGE__)}++;
-use CryptX;
-
-sub hashsize { Crypt::Digest::hashsize(__PACKAGE__) }
-
-sub sha224 { Crypt::Digest::digest_data(__PACKAGE__, @_) }
-sub sha224_hex { Crypt::Digest::digest_data_hex(__PACKAGE__, @_) }
-sub sha224_b64 { Crypt::Digest::digest_data_b64(__PACKAGE__, @_) }
-sub sha224_b64u { Crypt::Digest::digest_data_b64u(__PACKAGE__, @_) }
-
-sub sha224_file { Crypt::Digest::digest_file(__PACKAGE__, @_) }
-sub sha224_file_hex { Crypt::Digest::digest_file_hex(__PACKAGE__, @_) }
-sub sha224_file_b64 { Crypt::Digest::digest_file_b64(__PACKAGE__, @_) }
-sub sha224_file_b64u { Crypt::Digest::digest_file_b64u(__PACKAGE__, @_) }
+use Crypt::Digest;
+
+sub hashsize { Crypt::Digest::hashsize('SHA224') }
+sub sha224 { Crypt::Digest::digest_data('SHA224', @_) }
+sub sha224_hex { Crypt::Digest::digest_data_hex('SHA224', @_) }
+sub sha224_b64 { Crypt::Digest::digest_data_b64('SHA224', @_) }
+sub sha224_b64u { Crypt::Digest::digest_data_b64u('SHA224', @_) }
+sub sha224_file { Crypt::Digest::digest_file('SHA224', @_) }
+sub sha224_file_hex { Crypt::Digest::digest_file_hex('SHA224', @_) }
+sub sha224_file_b64 { Crypt::Digest::digest_file_b64('SHA224', @_) }
+sub sha224_file_b64u { Crypt::Digest::digest_file_b64u('SHA224', @_) }
1;
diff --git a/lib/Crypt/Digest/SHA256.pm b/lib/Crypt/Digest/SHA256.pm
index e5259130..d81ce7e8 100644
--- a/lib/Crypt/Digest/SHA256.pm
+++ b/lib/Crypt/Digest/SHA256.pm
@@ -4,7 +4,7 @@ package Crypt::Digest::SHA256;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::Digest Exporter);
our %EXPORT_TAGS = ( all => [qw( sha256 sha256_hex sha256_b64 sha256_b64u sha256_file sha256_file_hex sha256_file_b64 sha256_file_b64u )] );
@@ -13,19 +13,17 @@ our @EXPORT = qw();
use Carp;
$Carp::Internal{(__PACKAGE__)}++;
-use CryptX;
-
-sub hashsize { Crypt::Digest::hashsize(__PACKAGE__) }
-
-sub sha256 { Crypt::Digest::digest_data(__PACKAGE__, @_) }
-sub sha256_hex { Crypt::Digest::digest_data_hex(__PACKAGE__, @_) }
-sub sha256_b64 { Crypt::Digest::digest_data_b64(__PACKAGE__, @_) }
-sub sha256_b64u { Crypt::Digest::digest_data_b64u(__PACKAGE__, @_) }
-
-sub sha256_file { Crypt::Digest::digest_file(__PACKAGE__, @_) }
-sub sha256_file_hex { Crypt::Digest::digest_file_hex(__PACKAGE__, @_) }
-sub sha256_file_b64 { Crypt::Digest::digest_file_b64(__PACKAGE__, @_) }
-sub sha256_file_b64u { Crypt::Digest::digest_file_b64u(__PACKAGE__, @_) }
+use Crypt::Digest;
+
+sub hashsize { Crypt::Digest::hashsize('SHA256') }
+sub sha256 { Crypt::Digest::digest_data('SHA256', @_) }
+sub sha256_hex { Crypt::Digest::digest_data_hex('SHA256', @_) }
+sub sha256_b64 { Crypt::Digest::digest_data_b64('SHA256', @_) }
+sub sha256_b64u { Crypt::Digest::digest_data_b64u('SHA256', @_) }
+sub sha256_file { Crypt::Digest::digest_file('SHA256', @_) }
+sub sha256_file_hex { Crypt::Digest::digest_file_hex('SHA256', @_) }
+sub sha256_file_b64 { Crypt::Digest::digest_file_b64('SHA256', @_) }
+sub sha256_file_b64u { Crypt::Digest::digest_file_b64u('SHA256', @_) }
1;
diff --git a/lib/Crypt/Digest/SHA384.pm b/lib/Crypt/Digest/SHA384.pm
index 4cf820e7..79fdd8c3 100644
--- a/lib/Crypt/Digest/SHA384.pm
+++ b/lib/Crypt/Digest/SHA384.pm
@@ -4,7 +4,7 @@ package Crypt::Digest::SHA384;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::Digest Exporter);
our %EXPORT_TAGS = ( all => [qw( sha384 sha384_hex sha384_b64 sha384_b64u sha384_file sha384_file_hex sha384_file_b64 sha384_file_b64u )] );
@@ -13,19 +13,17 @@ our @EXPORT = qw();
use Carp;
$Carp::Internal{(__PACKAGE__)}++;
-use CryptX;
-
-sub hashsize { Crypt::Digest::hashsize(__PACKAGE__) }
-
-sub sha384 { Crypt::Digest::digest_data(__PACKAGE__, @_) }
-sub sha384_hex { Crypt::Digest::digest_data_hex(__PACKAGE__, @_) }
-sub sha384_b64 { Crypt::Digest::digest_data_b64(__PACKAGE__, @_) }
-sub sha384_b64u { Crypt::Digest::digest_data_b64u(__PACKAGE__, @_) }
-
-sub sha384_file { Crypt::Digest::digest_file(__PACKAGE__, @_) }
-sub sha384_file_hex { Crypt::Digest::digest_file_hex(__PACKAGE__, @_) }
-sub sha384_file_b64 { Crypt::Digest::digest_file_b64(__PACKAGE__, @_) }
-sub sha384_file_b64u { Crypt::Digest::digest_file_b64u(__PACKAGE__, @_) }
+use Crypt::Digest;
+
+sub hashsize { Crypt::Digest::hashsize('SHA384') }
+sub sha384 { Crypt::Digest::digest_data('SHA384', @_) }
+sub sha384_hex { Crypt::Digest::digest_data_hex('SHA384', @_) }
+sub sha384_b64 { Crypt::Digest::digest_data_b64('SHA384', @_) }
+sub sha384_b64u { Crypt::Digest::digest_data_b64u('SHA384', @_) }
+sub sha384_file { Crypt::Digest::digest_file('SHA384', @_) }
+sub sha384_file_hex { Crypt::Digest::digest_file_hex('SHA384', @_) }
+sub sha384_file_b64 { Crypt::Digest::digest_file_b64('SHA384', @_) }
+sub sha384_file_b64u { Crypt::Digest::digest_file_b64u('SHA384', @_) }
1;
diff --git a/lib/Crypt/Digest/SHA3_224.pm b/lib/Crypt/Digest/SHA3_224.pm
index 5f2d334d..8eb3a82b 100644
--- a/lib/Crypt/Digest/SHA3_224.pm
+++ b/lib/Crypt/Digest/SHA3_224.pm
@@ -4,7 +4,7 @@ package Crypt::Digest::SHA3_224;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::Digest Exporter);
our %EXPORT_TAGS = ( all => [qw( sha3_224 sha3_224_hex sha3_224_b64 sha3_224_b64u sha3_224_file sha3_224_file_hex sha3_224_file_b64 sha3_224_file_b64u )] );
@@ -13,19 +13,17 @@ our @EXPORT = qw();
use Carp;
$Carp::Internal{(__PACKAGE__)}++;
-use CryptX;
-
-sub hashsize { Crypt::Digest::hashsize(__PACKAGE__) }
-
-sub sha3_224 { Crypt::Digest::digest_data(__PACKAGE__, @_) }
-sub sha3_224_hex { Crypt::Digest::digest_data_hex(__PACKAGE__, @_) }
-sub sha3_224_b64 { Crypt::Digest::digest_data_b64(__PACKAGE__, @_) }
-sub sha3_224_b64u { Crypt::Digest::digest_data_b64u(__PACKAGE__, @_) }
-
-sub sha3_224_file { Crypt::Digest::digest_file(__PACKAGE__, @_) }
-sub sha3_224_file_hex { Crypt::Digest::digest_file_hex(__PACKAGE__, @_) }
-sub sha3_224_file_b64 { Crypt::Digest::digest_file_b64(__PACKAGE__, @_) }
-sub sha3_224_file_b64u { Crypt::Digest::digest_file_b64u(__PACKAGE__, @_) }
+use Crypt::Digest;
+
+sub hashsize { Crypt::Digest::hashsize('SHA3_224') }
+sub sha3_224 { Crypt::Digest::digest_data('SHA3_224', @_) }
+sub sha3_224_hex { Crypt::Digest::digest_data_hex('SHA3_224', @_) }
+sub sha3_224_b64 { Crypt::Digest::digest_data_b64('SHA3_224', @_) }
+sub sha3_224_b64u { Crypt::Digest::digest_data_b64u('SHA3_224', @_) }
+sub sha3_224_file { Crypt::Digest::digest_file('SHA3_224', @_) }
+sub sha3_224_file_hex { Crypt::Digest::digest_file_hex('SHA3_224', @_) }
+sub sha3_224_file_b64 { Crypt::Digest::digest_file_b64('SHA3_224', @_) }
+sub sha3_224_file_b64u { Crypt::Digest::digest_file_b64u('SHA3_224', @_) }
1;
diff --git a/lib/Crypt/Digest/SHA3_256.pm b/lib/Crypt/Digest/SHA3_256.pm
index dffda719..75828ad2 100644
--- a/lib/Crypt/Digest/SHA3_256.pm
+++ b/lib/Crypt/Digest/SHA3_256.pm
@@ -4,7 +4,7 @@ package Crypt::Digest::SHA3_256;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::Digest Exporter);
our %EXPORT_TAGS = ( all => [qw( sha3_256 sha3_256_hex sha3_256_b64 sha3_256_b64u sha3_256_file sha3_256_file_hex sha3_256_file_b64 sha3_256_file_b64u )] );
@@ -13,19 +13,17 @@ our @EXPORT = qw();
use Carp;
$Carp::Internal{(__PACKAGE__)}++;
-use CryptX;
-
-sub hashsize { Crypt::Digest::hashsize(__PACKAGE__) }
-
-sub sha3_256 { Crypt::Digest::digest_data(__PACKAGE__, @_) }
-sub sha3_256_hex { Crypt::Digest::digest_data_hex(__PACKAGE__, @_) }
-sub sha3_256_b64 { Crypt::Digest::digest_data_b64(__PACKAGE__, @_) }
-sub sha3_256_b64u { Crypt::Digest::digest_data_b64u(__PACKAGE__, @_) }
-
-sub sha3_256_file { Crypt::Digest::digest_file(__PACKAGE__, @_) }
-sub sha3_256_file_hex { Crypt::Digest::digest_file_hex(__PACKAGE__, @_) }
-sub sha3_256_file_b64 { Crypt::Digest::digest_file_b64(__PACKAGE__, @_) }
-sub sha3_256_file_b64u { Crypt::Digest::digest_file_b64u(__PACKAGE__, @_) }
+use Crypt::Digest;
+
+sub hashsize { Crypt::Digest::hashsize('SHA3_256') }
+sub sha3_256 { Crypt::Digest::digest_data('SHA3_256', @_) }
+sub sha3_256_hex { Crypt::Digest::digest_data_hex('SHA3_256', @_) }
+sub sha3_256_b64 { Crypt::Digest::digest_data_b64('SHA3_256', @_) }
+sub sha3_256_b64u { Crypt::Digest::digest_data_b64u('SHA3_256', @_) }
+sub sha3_256_file { Crypt::Digest::digest_file('SHA3_256', @_) }
+sub sha3_256_file_hex { Crypt::Digest::digest_file_hex('SHA3_256', @_) }
+sub sha3_256_file_b64 { Crypt::Digest::digest_file_b64('SHA3_256', @_) }
+sub sha3_256_file_b64u { Crypt::Digest::digest_file_b64u('SHA3_256', @_) }
1;
diff --git a/lib/Crypt/Digest/SHA3_384.pm b/lib/Crypt/Digest/SHA3_384.pm
index cfcb8c8e..3d15489f 100644
--- a/lib/Crypt/Digest/SHA3_384.pm
+++ b/lib/Crypt/Digest/SHA3_384.pm
@@ -4,7 +4,7 @@ package Crypt::Digest::SHA3_384;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::Digest Exporter);
our %EXPORT_TAGS = ( all => [qw( sha3_384 sha3_384_hex sha3_384_b64 sha3_384_b64u sha3_384_file sha3_384_file_hex sha3_384_file_b64 sha3_384_file_b64u )] );
@@ -13,19 +13,17 @@ our @EXPORT = qw();
use Carp;
$Carp::Internal{(__PACKAGE__)}++;
-use CryptX;
-
-sub hashsize { Crypt::Digest::hashsize(__PACKAGE__) }
-
-sub sha3_384 { Crypt::Digest::digest_data(__PACKAGE__, @_) }
-sub sha3_384_hex { Crypt::Digest::digest_data_hex(__PACKAGE__, @_) }
-sub sha3_384_b64 { Crypt::Digest::digest_data_b64(__PACKAGE__, @_) }
-sub sha3_384_b64u { Crypt::Digest::digest_data_b64u(__PACKAGE__, @_) }
-
-sub sha3_384_file { Crypt::Digest::digest_file(__PACKAGE__, @_) }
-sub sha3_384_file_hex { Crypt::Digest::digest_file_hex(__PACKAGE__, @_) }
-sub sha3_384_file_b64 { Crypt::Digest::digest_file_b64(__PACKAGE__, @_) }
-sub sha3_384_file_b64u { Crypt::Digest::digest_file_b64u(__PACKAGE__, @_) }
+use Crypt::Digest;
+
+sub hashsize { Crypt::Digest::hashsize('SHA3_384') }
+sub sha3_384 { Crypt::Digest::digest_data('SHA3_384', @_) }
+sub sha3_384_hex { Crypt::Digest::digest_data_hex('SHA3_384', @_) }
+sub sha3_384_b64 { Crypt::Digest::digest_data_b64('SHA3_384', @_) }
+sub sha3_384_b64u { Crypt::Digest::digest_data_b64u('SHA3_384', @_) }
+sub sha3_384_file { Crypt::Digest::digest_file('SHA3_384', @_) }
+sub sha3_384_file_hex { Crypt::Digest::digest_file_hex('SHA3_384', @_) }
+sub sha3_384_file_b64 { Crypt::Digest::digest_file_b64('SHA3_384', @_) }
+sub sha3_384_file_b64u { Crypt::Digest::digest_file_b64u('SHA3_384', @_) }
1;
diff --git a/lib/Crypt/Digest/SHA3_512.pm b/lib/Crypt/Digest/SHA3_512.pm
index d2c8aa17..27afec41 100644
--- a/lib/Crypt/Digest/SHA3_512.pm
+++ b/lib/Crypt/Digest/SHA3_512.pm
@@ -4,7 +4,7 @@ package Crypt::Digest::SHA3_512;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::Digest Exporter);
our %EXPORT_TAGS = ( all => [qw( sha3_512 sha3_512_hex sha3_512_b64 sha3_512_b64u sha3_512_file sha3_512_file_hex sha3_512_file_b64 sha3_512_file_b64u )] );
@@ -13,19 +13,17 @@ our @EXPORT = qw();
use Carp;
$Carp::Internal{(__PACKAGE__)}++;
-use CryptX;
-
-sub hashsize { Crypt::Digest::hashsize(__PACKAGE__) }
-
-sub sha3_512 { Crypt::Digest::digest_data(__PACKAGE__, @_) }
-sub sha3_512_hex { Crypt::Digest::digest_data_hex(__PACKAGE__, @_) }
-sub sha3_512_b64 { Crypt::Digest::digest_data_b64(__PACKAGE__, @_) }
-sub sha3_512_b64u { Crypt::Digest::digest_data_b64u(__PACKAGE__, @_) }
-
-sub sha3_512_file { Crypt::Digest::digest_file(__PACKAGE__, @_) }
-sub sha3_512_file_hex { Crypt::Digest::digest_file_hex(__PACKAGE__, @_) }
-sub sha3_512_file_b64 { Crypt::Digest::digest_file_b64(__PACKAGE__, @_) }
-sub sha3_512_file_b64u { Crypt::Digest::digest_file_b64u(__PACKAGE__, @_) }
+use Crypt::Digest;
+
+sub hashsize { Crypt::Digest::hashsize('SHA3_512') }
+sub sha3_512 { Crypt::Digest::digest_data('SHA3_512', @_) }
+sub sha3_512_hex { Crypt::Digest::digest_data_hex('SHA3_512', @_) }
+sub sha3_512_b64 { Crypt::Digest::digest_data_b64('SHA3_512', @_) }
+sub sha3_512_b64u { Crypt::Digest::digest_data_b64u('SHA3_512', @_) }
+sub sha3_512_file { Crypt::Digest::digest_file('SHA3_512', @_) }
+sub sha3_512_file_hex { Crypt::Digest::digest_file_hex('SHA3_512', @_) }
+sub sha3_512_file_b64 { Crypt::Digest::digest_file_b64('SHA3_512', @_) }
+sub sha3_512_file_b64u { Crypt::Digest::digest_file_b64u('SHA3_512', @_) }
1;
diff --git a/lib/Crypt/Digest/SHA512.pm b/lib/Crypt/Digest/SHA512.pm
index c12ed5a5..7ba414a2 100644
--- a/lib/Crypt/Digest/SHA512.pm
+++ b/lib/Crypt/Digest/SHA512.pm
@@ -4,7 +4,7 @@ package Crypt::Digest::SHA512;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::Digest Exporter);
our %EXPORT_TAGS = ( all => [qw( sha512 sha512_hex sha512_b64 sha512_b64u sha512_file sha512_file_hex sha512_file_b64 sha512_file_b64u )] );
@@ -13,19 +13,17 @@ our @EXPORT = qw();
use Carp;
$Carp::Internal{(__PACKAGE__)}++;
-use CryptX;
-
-sub hashsize { Crypt::Digest::hashsize(__PACKAGE__) }
-
-sub sha512 { Crypt::Digest::digest_data(__PACKAGE__, @_) }
-sub sha512_hex { Crypt::Digest::digest_data_hex(__PACKAGE__, @_) }
-sub sha512_b64 { Crypt::Digest::digest_data_b64(__PACKAGE__, @_) }
-sub sha512_b64u { Crypt::Digest::digest_data_b64u(__PACKAGE__, @_) }
-
-sub sha512_file { Crypt::Digest::digest_file(__PACKAGE__, @_) }
-sub sha512_file_hex { Crypt::Digest::digest_file_hex(__PACKAGE__, @_) }
-sub sha512_file_b64 { Crypt::Digest::digest_file_b64(__PACKAGE__, @_) }
-sub sha512_file_b64u { Crypt::Digest::digest_file_b64u(__PACKAGE__, @_) }
+use Crypt::Digest;
+
+sub hashsize { Crypt::Digest::hashsize('SHA512') }
+sub sha512 { Crypt::Digest::digest_data('SHA512', @_) }
+sub sha512_hex { Crypt::Digest::digest_data_hex('SHA512', @_) }
+sub sha512_b64 { Crypt::Digest::digest_data_b64('SHA512', @_) }
+sub sha512_b64u { Crypt::Digest::digest_data_b64u('SHA512', @_) }
+sub sha512_file { Crypt::Digest::digest_file('SHA512', @_) }
+sub sha512_file_hex { Crypt::Digest::digest_file_hex('SHA512', @_) }
+sub sha512_file_b64 { Crypt::Digest::digest_file_b64('SHA512', @_) }
+sub sha512_file_b64u { Crypt::Digest::digest_file_b64u('SHA512', @_) }
1;
diff --git a/lib/Crypt/Digest/SHA512_224.pm b/lib/Crypt/Digest/SHA512_224.pm
index 7d719ba6..1f83b53f 100644
--- a/lib/Crypt/Digest/SHA512_224.pm
+++ b/lib/Crypt/Digest/SHA512_224.pm
@@ -4,7 +4,7 @@ package Crypt::Digest::SHA512_224;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::Digest Exporter);
our %EXPORT_TAGS = ( all => [qw( sha512_224 sha512_224_hex sha512_224_b64 sha512_224_b64u sha512_224_file sha512_224_file_hex sha512_224_file_b64 sha512_224_file_b64u )] );
@@ -13,19 +13,17 @@ our @EXPORT = qw();
use Carp;
$Carp::Internal{(__PACKAGE__)}++;
-use CryptX;
-
-sub hashsize { Crypt::Digest::hashsize(__PACKAGE__) }
-
-sub sha512_224 { Crypt::Digest::digest_data(__PACKAGE__, @_) }
-sub sha512_224_hex { Crypt::Digest::digest_data_hex(__PACKAGE__, @_) }
-sub sha512_224_b64 { Crypt::Digest::digest_data_b64(__PACKAGE__, @_) }
-sub sha512_224_b64u { Crypt::Digest::digest_data_b64u(__PACKAGE__, @_) }
-
-sub sha512_224_file { Crypt::Digest::digest_file(__PACKAGE__, @_) }
-sub sha512_224_file_hex { Crypt::Digest::digest_file_hex(__PACKAGE__, @_) }
-sub sha512_224_file_b64 { Crypt::Digest::digest_file_b64(__PACKAGE__, @_) }
-sub sha512_224_file_b64u { Crypt::Digest::digest_file_b64u(__PACKAGE__, @_) }
+use Crypt::Digest;
+
+sub hashsize { Crypt::Digest::hashsize('SHA512_224') }
+sub sha512_224 { Crypt::Digest::digest_data('SHA512_224', @_) }
+sub sha512_224_hex { Crypt::Digest::digest_data_hex('SHA512_224', @_) }
+sub sha512_224_b64 { Crypt::Digest::digest_data_b64('SHA512_224', @_) }
+sub sha512_224_b64u { Crypt::Digest::digest_data_b64u('SHA512_224', @_) }
+sub sha512_224_file { Crypt::Digest::digest_file('SHA512_224', @_) }
+sub sha512_224_file_hex { Crypt::Digest::digest_file_hex('SHA512_224', @_) }
+sub sha512_224_file_b64 { Crypt::Digest::digest_file_b64('SHA512_224', @_) }
+sub sha512_224_file_b64u { Crypt::Digest::digest_file_b64u('SHA512_224', @_) }
1;
diff --git a/lib/Crypt/Digest/SHA512_256.pm b/lib/Crypt/Digest/SHA512_256.pm
index 625855ce..fb8d92d2 100644
--- a/lib/Crypt/Digest/SHA512_256.pm
+++ b/lib/Crypt/Digest/SHA512_256.pm
@@ -4,7 +4,7 @@ package Crypt::Digest::SHA512_256;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::Digest Exporter);
our %EXPORT_TAGS = ( all => [qw( sha512_256 sha512_256_hex sha512_256_b64 sha512_256_b64u sha512_256_file sha512_256_file_hex sha512_256_file_b64 sha512_256_file_b64u )] );
@@ -13,19 +13,17 @@ our @EXPORT = qw();
use Carp;
$Carp::Internal{(__PACKAGE__)}++;
-use CryptX;
-
-sub hashsize { Crypt::Digest::hashsize(__PACKAGE__) }
-
-sub sha512_256 { Crypt::Digest::digest_data(__PACKAGE__, @_) }
-sub sha512_256_hex { Crypt::Digest::digest_data_hex(__PACKAGE__, @_) }
-sub sha512_256_b64 { Crypt::Digest::digest_data_b64(__PACKAGE__, @_) }
-sub sha512_256_b64u { Crypt::Digest::digest_data_b64u(__PACKAGE__, @_) }
-
-sub sha512_256_file { Crypt::Digest::digest_file(__PACKAGE__, @_) }
-sub sha512_256_file_hex { Crypt::Digest::digest_file_hex(__PACKAGE__, @_) }
-sub sha512_256_file_b64 { Crypt::Digest::digest_file_b64(__PACKAGE__, @_) }
-sub sha512_256_file_b64u { Crypt::Digest::digest_file_b64u(__PACKAGE__, @_) }
+use Crypt::Digest;
+
+sub hashsize { Crypt::Digest::hashsize('SHA512_256') }
+sub sha512_256 { Crypt::Digest::digest_data('SHA512_256', @_) }
+sub sha512_256_hex { Crypt::Digest::digest_data_hex('SHA512_256', @_) }
+sub sha512_256_b64 { Crypt::Digest::digest_data_b64('SHA512_256', @_) }
+sub sha512_256_b64u { Crypt::Digest::digest_data_b64u('SHA512_256', @_) }
+sub sha512_256_file { Crypt::Digest::digest_file('SHA512_256', @_) }
+sub sha512_256_file_hex { Crypt::Digest::digest_file_hex('SHA512_256', @_) }
+sub sha512_256_file_b64 { Crypt::Digest::digest_file_b64('SHA512_256', @_) }
+sub sha512_256_file_b64u { Crypt::Digest::digest_file_b64u('SHA512_256', @_) }
1;
diff --git a/lib/Crypt/Digest/SHAKE.pm b/lib/Crypt/Digest/SHAKE.pm
index c5bbabfc..90dd48f4 100644
--- a/lib/Crypt/Digest/SHAKE.pm
+++ b/lib/Crypt/Digest/SHAKE.pm
@@ -2,14 +2,12 @@ package Crypt::Digest::SHAKE;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use Carp;
$Carp::Internal{(__PACKAGE__)}++;
use CryptX;
-sub new { my $class = shift; _new(@_) }
-
sub addfile {
my ($self, $file) = @_;
diff --git a/lib/Crypt/Digest/Tiger192.pm b/lib/Crypt/Digest/Tiger192.pm
index 97ba660f..8b248ac6 100644
--- a/lib/Crypt/Digest/Tiger192.pm
+++ b/lib/Crypt/Digest/Tiger192.pm
@@ -4,7 +4,7 @@ package Crypt::Digest::Tiger192;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::Digest Exporter);
our %EXPORT_TAGS = ( all => [qw( tiger192 tiger192_hex tiger192_b64 tiger192_b64u tiger192_file tiger192_file_hex tiger192_file_b64 tiger192_file_b64u )] );
@@ -13,19 +13,17 @@ our @EXPORT = qw();
use Carp;
$Carp::Internal{(__PACKAGE__)}++;
-use CryptX;
-
-sub hashsize { Crypt::Digest::hashsize(__PACKAGE__) }
-
-sub tiger192 { Crypt::Digest::digest_data(__PACKAGE__, @_) }
-sub tiger192_hex { Crypt::Digest::digest_data_hex(__PACKAGE__, @_) }
-sub tiger192_b64 { Crypt::Digest::digest_data_b64(__PACKAGE__, @_) }
-sub tiger192_b64u { Crypt::Digest::digest_data_b64u(__PACKAGE__, @_) }
-
-sub tiger192_file { Crypt::Digest::digest_file(__PACKAGE__, @_) }
-sub tiger192_file_hex { Crypt::Digest::digest_file_hex(__PACKAGE__, @_) }
-sub tiger192_file_b64 { Crypt::Digest::digest_file_b64(__PACKAGE__, @_) }
-sub tiger192_file_b64u { Crypt::Digest::digest_file_b64u(__PACKAGE__, @_) }
+use Crypt::Digest;
+
+sub hashsize { Crypt::Digest::hashsize('Tiger192') }
+sub tiger192 { Crypt::Digest::digest_data('Tiger192', @_) }
+sub tiger192_hex { Crypt::Digest::digest_data_hex('Tiger192', @_) }
+sub tiger192_b64 { Crypt::Digest::digest_data_b64('Tiger192', @_) }
+sub tiger192_b64u { Crypt::Digest::digest_data_b64u('Tiger192', @_) }
+sub tiger192_file { Crypt::Digest::digest_file('Tiger192', @_) }
+sub tiger192_file_hex { Crypt::Digest::digest_file_hex('Tiger192', @_) }
+sub tiger192_file_b64 { Crypt::Digest::digest_file_b64('Tiger192', @_) }
+sub tiger192_file_b64u { Crypt::Digest::digest_file_b64u('Tiger192', @_) }
1;
diff --git a/lib/Crypt/Digest/Whirlpool.pm b/lib/Crypt/Digest/Whirlpool.pm
index 37b4b549..d86bbc4d 100644
--- a/lib/Crypt/Digest/Whirlpool.pm
+++ b/lib/Crypt/Digest/Whirlpool.pm
@@ -4,7 +4,7 @@ package Crypt::Digest::Whirlpool;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::Digest Exporter);
our %EXPORT_TAGS = ( all => [qw( whirlpool whirlpool_hex whirlpool_b64 whirlpool_b64u whirlpool_file whirlpool_file_hex whirlpool_file_b64 whirlpool_file_b64u )] );
@@ -13,19 +13,17 @@ our @EXPORT = qw();
use Carp;
$Carp::Internal{(__PACKAGE__)}++;
-use CryptX;
-
-sub hashsize { Crypt::Digest::hashsize(__PACKAGE__) }
-
-sub whirlpool { Crypt::Digest::digest_data(__PACKAGE__, @_) }
-sub whirlpool_hex { Crypt::Digest::digest_data_hex(__PACKAGE__, @_) }
-sub whirlpool_b64 { Crypt::Digest::digest_data_b64(__PACKAGE__, @_) }
-sub whirlpool_b64u { Crypt::Digest::digest_data_b64u(__PACKAGE__, @_) }
-
-sub whirlpool_file { Crypt::Digest::digest_file(__PACKAGE__, @_) }
-sub whirlpool_file_hex { Crypt::Digest::digest_file_hex(__PACKAGE__, @_) }
-sub whirlpool_file_b64 { Crypt::Digest::digest_file_b64(__PACKAGE__, @_) }
-sub whirlpool_file_b64u { Crypt::Digest::digest_file_b64u(__PACKAGE__, @_) }
+use Crypt::Digest;
+
+sub hashsize { Crypt::Digest::hashsize('Whirlpool') }
+sub whirlpool { Crypt::Digest::digest_data('Whirlpool', @_) }
+sub whirlpool_hex { Crypt::Digest::digest_data_hex('Whirlpool', @_) }
+sub whirlpool_b64 { Crypt::Digest::digest_data_b64('Whirlpool', @_) }
+sub whirlpool_b64u { Crypt::Digest::digest_data_b64u('Whirlpool', @_) }
+sub whirlpool_file { Crypt::Digest::digest_file('Whirlpool', @_) }
+sub whirlpool_file_hex { Crypt::Digest::digest_file_hex('Whirlpool', @_) }
+sub whirlpool_file_b64 { Crypt::Digest::digest_file_b64('Whirlpool', @_) }
+sub whirlpool_file_b64u { Crypt::Digest::digest_file_b64u('Whirlpool', @_) }
1;
diff --git a/lib/Crypt/KeyDerivation.pm b/lib/Crypt/KeyDerivation.pm
index fa33215a..ea0b2d27 100644
--- a/lib/Crypt/KeyDerivation.pm
+++ b/lib/Crypt/KeyDerivation.pm
@@ -2,7 +2,7 @@ package Crypt::KeyDerivation;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import';
our %EXPORT_TAGS = ( all => [qw(pbkdf1 pbkdf2 hkdf hkdf_expand hkdf_extract)] );
@@ -12,57 +12,6 @@ our @EXPORT = qw();
use Carp;
$Carp::Internal{(__PACKAGE__)}++;
use CryptX;
-use Crypt::Digest;
-
-sub pbkdf1 {
- my ($password, $salt, $iteration_count, $hash_name, $len) = @_;
- $iteration_count ||= 5000;
- $hash_name = Crypt::Digest::_trans_digest_name($hash_name||'SHA256');
- $len ||= 32;
- local $SIG{__DIE__} = \&CryptX::_croak;
- return _pkcs_5_alg1($password, $salt, $iteration_count, $hash_name, $len);
-}
-
-sub pbkdf2 {
- my ($password, $salt, $iteration_count, $hash_name, $len) = @_;
- $iteration_count ||= 5000;
- $hash_name = Crypt::Digest::_trans_digest_name($hash_name||'SHA256');
- $len ||= 32;
- local $SIG{__DIE__} = \&CryptX::_croak;
- return _pkcs_5_alg2($password, $salt, $iteration_count, $hash_name, $len);
-}
-
-sub hkdf_extract {
- # RFC: HKDF-Extract(salt, IKM, [Hash]) -> PRK
- #my ($hash_name, $salt, $keying_material) = @_;
- my ($keying_material, $salt, $hash_name) = @_;
- $hash_name = Crypt::Digest::_trans_digest_name($hash_name||'SHA256');
- $salt = pack("H*", "00" x Crypt::Digest->hashsize($hash_name)) unless defined $salt; # according to rfc5869 defaults to HashLen zero octets
- local $SIG{__DIE__} = \&CryptX::_croak;
- return _hkdf_extract($hash_name, $salt, $keying_material);
-}
-
-sub hkdf_expand {
- # RFC: HKDF-Expand(PRK, info, L, [Hash]) -> OKM
- #my ($hash_name, $info, $keying_material, $len) = @_;
- my ($keying_material, $hash_name, $len, $info) = @_;
- $len ||= 32;
- $info ||= '';
- $hash_name = Crypt::Digest::_trans_digest_name($hash_name||'SHA256');
- local $SIG{__DIE__} = \&CryptX::_croak;
- return _hkdf_expand($hash_name, $info, $keying_material, $len);
-}
-
-sub hkdf {
- #my ($hash_name, $salt, $info, $keying_material, $len) = @_;
- my ($keying_material, $salt, $hash_name, $len, $info) = @_;
- $len ||= 32;
- $info ||= '';
- $hash_name = Crypt::Digest::_trans_digest_name($hash_name||'SHA256');
- $salt = pack("H*", "00" x Crypt::Digest->hashsize($hash_name)) unless defined $salt; # according to rfc5869 defaults to HashLen zero octets
- local $SIG{__DIE__} = \&CryptX::_croak;
- return _hkdf($hash_name, $salt, $info, $keying_material, $len);
-}
1;
diff --git a/lib/Crypt/Mac.pm b/lib/Crypt/Mac.pm
index adf35217..8d6f696b 100644
--- a/lib/Crypt/Mac.pm
+++ b/lib/Crypt/Mac.pm
@@ -2,35 +2,21 @@ package Crypt::Mac;
use strict;
use warnings;
-our $VERSION = '0.056';
-
-require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import';
-our %EXPORT_TAGS = ( all => [qw( mac mac_hex )] );
-our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
-our @EXPORT = qw();
+our $VERSION = '0.059';
use Carp;
$Carp::Internal{(__PACKAGE__)}++;
use CryptX;
-sub add {
- my $self = shift;
- local $SIG{__DIE__} = \&CryptX::_croak;
- $self->_add_single($_) for (@_);
- return $self;
-}
-
sub addfile {
my ($self, $file) = @_;
my $handle;
if (ref(\$file) eq 'SCALAR') {
- #filename
open($handle, "<", $file) || die "FATAL: cannot open '$file': $!";
binmode($handle);
}
else {
- #handle
$handle = $file
}
die "FATAL: invalid handle" unless defined $handle;
@@ -39,7 +25,7 @@ sub addfile {
my $buf = "";
local $SIG{__DIE__} = \&CryptX::_croak;
while (($n = read($handle, $buf, 32*1024))) {
- $self->_add_single($buf)
+ $self->add($buf);
}
die "FATAL: read failed: $!" unless defined $n;
diff --git a/lib/Crypt/Mac/BLAKE2b.pm b/lib/Crypt/Mac/BLAKE2b.pm
index 95905290..26b12d02 100644
--- a/lib/Crypt/Mac/BLAKE2b.pm
+++ b/lib/Crypt/Mac/BLAKE2b.pm
@@ -4,20 +4,13 @@ package Crypt::Mac::BLAKE2b;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::Mac Exporter);
our %EXPORT_TAGS = ( all => [qw( blake2b blake2b_hex blake2b_b64 blake2b_b64u )] );
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw();
-use CryptX;
-sub new { my $class = shift; _new(@_) }
-sub blake2b { Crypt::Mac::BLAKE2b->new(shift, shift)->add(@_)->mac }
-sub blake2b_hex { Crypt::Mac::BLAKE2b->new(shift, shift)->add(@_)->hexmac }
-sub blake2b_b64 { Crypt::Mac::BLAKE2b->new(shift, shift)->add(@_)->b64mac }
-sub blake2b_b64u { Crypt::Mac::BLAKE2b->new(shift, shift)->add(@_)->b64umac }
-
1;
=pod
diff --git a/lib/Crypt/Mac/BLAKE2s.pm b/lib/Crypt/Mac/BLAKE2s.pm
index 02951e4a..2faab14e 100644
--- a/lib/Crypt/Mac/BLAKE2s.pm
+++ b/lib/Crypt/Mac/BLAKE2s.pm
@@ -4,20 +4,13 @@ package Crypt::Mac::BLAKE2s;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::Mac Exporter);
our %EXPORT_TAGS = ( all => [qw( blake2s blake2s_hex blake2s_b64 blake2s_b64u )] );
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw();
-use CryptX;
-sub new { my $class = shift; _new(@_) }
-sub blake2s { Crypt::Mac::BLAKE2s->new(shift, shift)->add(@_)->mac }
-sub blake2s_hex { Crypt::Mac::BLAKE2s->new(shift, shift)->add(@_)->hexmac }
-sub blake2s_b64 { Crypt::Mac::BLAKE2s->new(shift, shift)->add(@_)->b64mac }
-sub blake2s_b64u { Crypt::Mac::BLAKE2s->new(shift, shift)->add(@_)->b64umac }
-
1;
=pod
diff --git a/lib/Crypt/Mac/F9.pm b/lib/Crypt/Mac/F9.pm
index 311d0624..9310ab5c 100644
--- a/lib/Crypt/Mac/F9.pm
+++ b/lib/Crypt/Mac/F9.pm
@@ -4,22 +4,13 @@ package Crypt::Mac::F9;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::Mac Exporter);
our %EXPORT_TAGS = ( all => [qw( f9 f9_hex f9_b64 f9_b64u )] );
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw();
-use CryptX;
-use Crypt::Cipher;
-
-sub new { my $class = shift; _new(Crypt::Cipher::_trans_cipher_name(shift), @_) }
-sub f9 { Crypt::Mac::F9->new(shift, shift)->add(@_)->mac }
-sub f9_hex { Crypt::Mac::F9->new(shift, shift)->add(@_)->hexmac }
-sub f9_b64 { Crypt::Mac::F9->new(shift, shift)->add(@_)->b64mac }
-sub f9_b64u { Crypt::Mac::F9->new(shift, shift)->add(@_)->b64umac }
-
1;
=pod
diff --git a/lib/Crypt/Mac/HMAC.pm b/lib/Crypt/Mac/HMAC.pm
index 618e41bd..f381f74a 100644
--- a/lib/Crypt/Mac/HMAC.pm
+++ b/lib/Crypt/Mac/HMAC.pm
@@ -4,22 +4,13 @@ package Crypt::Mac::HMAC;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::Mac Exporter);
our %EXPORT_TAGS = ( all => [qw( hmac hmac_hex hmac_b64 hmac_b64u )] );
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw();
-use CryptX;
-use Crypt::Digest;
-
-sub new { my $class = shift; _new(Crypt::Digest::_trans_digest_name(shift), @_) }
-sub hmac { Crypt::Mac::HMAC->new(shift, shift)->add(@_)->mac }
-sub hmac_hex { Crypt::Mac::HMAC->new(shift, shift)->add(@_)->hexmac }
-sub hmac_b64 { Crypt::Mac::HMAC->new(shift, shift)->add(@_)->b64mac }
-sub hmac_b64u { Crypt::Mac::HMAC->new(shift, shift)->add(@_)->b64umac }
-
1;
=pod
diff --git a/lib/Crypt/Mac/OMAC.pm b/lib/Crypt/Mac/OMAC.pm
index d1ad335a..d3ee44b5 100644
--- a/lib/Crypt/Mac/OMAC.pm
+++ b/lib/Crypt/Mac/OMAC.pm
@@ -4,22 +4,13 @@ package Crypt::Mac::OMAC;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::Mac Exporter);
our %EXPORT_TAGS = ( all => [qw( omac omac_hex omac_b64 omac_b64u )] );
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw();
-use CryptX;
-use Crypt::Cipher;
-
-sub new { my $class = shift; _new(Crypt::Cipher::_trans_cipher_name(shift), @_) }
-sub omac { Crypt::Mac::OMAC->new(shift, shift)->add(@_)->mac }
-sub omac_hex { Crypt::Mac::OMAC->new(shift, shift)->add(@_)->hexmac }
-sub omac_b64 { Crypt::Mac::OMAC->new(shift, shift)->add(@_)->b64mac }
-sub omac_b64u { Crypt::Mac::OMAC->new(shift, shift)->add(@_)->b64umac }
-
1;
=pod
diff --git a/lib/Crypt/Mac/PMAC.pm b/lib/Crypt/Mac/PMAC.pm
index f66ba827..f9c952fe 100644
--- a/lib/Crypt/Mac/PMAC.pm
+++ b/lib/Crypt/Mac/PMAC.pm
@@ -4,22 +4,13 @@ package Crypt::Mac::PMAC;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::Mac Exporter);
our %EXPORT_TAGS = ( all => [qw( pmac pmac_hex pmac_b64 pmac_b64u )] );
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw();
-use CryptX;
-use Crypt::Cipher;
-
-sub new { my $class = shift; _new(Crypt::Cipher::_trans_cipher_name(shift), @_) }
-sub pmac { Crypt::Mac::PMAC->new(shift, shift)->add(@_)->mac }
-sub pmac_hex { Crypt::Mac::PMAC->new(shift, shift)->add(@_)->hexmac }
-sub pmac_b64 { Crypt::Mac::PMAC->new(shift, shift)->add(@_)->b64mac }
-sub pmac_b64u { Crypt::Mac::PMAC->new(shift, shift)->add(@_)->b64umac }
-
1;
=pod
diff --git a/lib/Crypt/Mac/Pelican.pm b/lib/Crypt/Mac/Pelican.pm
index 3a8ab2f0..104c5835 100644
--- a/lib/Crypt/Mac/Pelican.pm
+++ b/lib/Crypt/Mac/Pelican.pm
@@ -4,20 +4,13 @@ package Crypt::Mac::Pelican;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::Mac Exporter);
our %EXPORT_TAGS = ( all => [qw( pelican pelican_hex pelican_b64 pelican_b64u )] );
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw();
-use CryptX;
-sub new { my $class = shift; _new(@_) }
-sub pelican { Crypt::Mac::Pelican->new(shift)->add(@_)->mac }
-sub pelican_hex { Crypt::Mac::Pelican->new(shift)->add(@_)->hexmac }
-sub pelican_b64 { Crypt::Mac::Pelican->new(shift)->add(@_)->b64mac }
-sub pelican_b64u { Crypt::Mac::Pelican->new(shift)->add(@_)->b64umac }
-
1;
=pod
diff --git a/lib/Crypt/Mac/Poly1305.pm b/lib/Crypt/Mac/Poly1305.pm
index a7115535..73e58b4d 100644
--- a/lib/Crypt/Mac/Poly1305.pm
+++ b/lib/Crypt/Mac/Poly1305.pm
@@ -4,20 +4,13 @@ package Crypt::Mac::Poly1305;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::Mac Exporter);
our %EXPORT_TAGS = ( all => [qw( poly1305 poly1305_hex poly1305_b64 poly1305_b64u )] );
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw();
-use CryptX;
-sub new { my $class = shift; _new(@_) }
-sub poly1305 { Crypt::Mac::Poly1305->new(shift)->add(@_)->mac }
-sub poly1305_hex { Crypt::Mac::Poly1305->new(shift)->add(@_)->hexmac }
-sub poly1305_b64 { Crypt::Mac::Poly1305->new(shift)->add(@_)->b64mac }
-sub poly1305_b64u { Crypt::Mac::Poly1305->new(shift)->add(@_)->b64umac }
-
1;
=pod
diff --git a/lib/Crypt/Mac/XCBC.pm b/lib/Crypt/Mac/XCBC.pm
index 3bd9646c..d17634d2 100644
--- a/lib/Crypt/Mac/XCBC.pm
+++ b/lib/Crypt/Mac/XCBC.pm
@@ -4,22 +4,13 @@ package Crypt::Mac::XCBC;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::Mac Exporter);
our %EXPORT_TAGS = ( all => [qw( xcbc xcbc_hex xcbc_b64 xcbc_b64u )] );
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw();
-use CryptX;
-use Crypt::Cipher;
-
-sub new { my $class = shift; _new(Crypt::Cipher::_trans_cipher_name(shift), @_) }
-sub xcbc { Crypt::Mac::XCBC->new(shift, shift)->add(@_)->mac }
-sub xcbc_hex { Crypt::Mac::XCBC->new(shift, shift)->add(@_)->hexmac }
-sub xcbc_b64 { Crypt::Mac::XCBC->new(shift, shift)->add(@_)->b64mac }
-sub xcbc_b64u { Crypt::Mac::XCBC->new(shift, shift)->add(@_)->b64umac }
-
1;
=pod
diff --git a/lib/Crypt/Misc.pm b/lib/Crypt/Misc.pm
index 4ab80c93..72489ea5 100644
--- a/lib/Crypt/Misc.pm
+++ b/lib/Crypt/Misc.pm
@@ -2,7 +2,7 @@ package Crypt::Misc;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
require Exporter; our @ISA = qw(Exporter); ### use Exporter 5.57 'import';
use Carp 'croak';
@@ -35,22 +35,6 @@ use Crypt::Mode::OFB;
use Crypt::Cipher;
use Crypt::PRNG 'random_bytes';
-sub encode_b64 {
- CryptX::_encode_base64(@_);
-}
-
-sub decode_b64 {
- CryptX::_decode_base64(@_);
-}
-
-sub encode_b64u {
- CryptX::_encode_base64url(@_);
-}
-
-sub decode_b64u {
- CryptX::_decode_base64url(@_);
-}
-
sub _encode_b58 {
my ($bytes, $alphabet) = @_;
@@ -61,7 +45,7 @@ sub _encode_b58 {
if ($bytes =~ /^(\x00+)/) {
$base58 = ('0' x length($1));
}
- $base58 .= CryptX::_bin_to_radix($bytes, 58);
+ $base58 .= _bin_to_radix($bytes, 58);
if (defined $alphabet) {
my $default = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv";
@@ -80,7 +64,7 @@ sub _decode_b58 {
my $default = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv";
if (defined $alphabet) {
- return undef if $alphabet !~ /^[a-zA-Z0-9]{58}$/;
+ return undef if $alphabet !~ /^[a-zA-Z0-9]{58}$/ || $base58 !~ /^[$alphabet]+$/;
eval "\$base58 =~ tr/$alphabet/$default/"; # HACK: https://stackoverflow.com/questions/11415045/using-a-char-variable-in-tr
return undef if $@;
}
@@ -92,7 +76,7 @@ sub _decode_b58 {
$base58 = $2;
$bytes = ("\x00" x length($1));
}
- $bytes .= CryptX::_radix_to_bin($base58, 58) if defined $base58 && length($base58) > 0;
+ $bytes .= _radix_to_bin($base58, 58) if defined $base58 && length($base58) > 0;
return $bytes;
}
@@ -109,27 +93,6 @@ sub encode_b58r { _encode_b58(shift, "rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65
sub encode_b58t { _encode_b58(shift, "RPShNAF39wBUDnEGHJKLM4pQrsT7VWXYZ2bcdeCg65jkm8ofqi1tuvaxyz") } # Tipple
sub encode_b58s { _encode_b58(shift, "gsphnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCr65jkm8oFqi1tuvAxyz") } # Stellar
-sub encode_b32r { CryptX::_encode_b32(shift, 0) } # rfc4648
-sub encode_b32b { CryptX::_encode_b32(shift, 1) } # base32hex
-sub encode_b32z { CryptX::_encode_b32(shift, 2) } # zbase32
-sub encode_b32c { CryptX::_encode_b32(shift, 3) } # crockford
-
-sub decode_b32r { CryptX::_decode_b32(shift, 0) } # rfc4648
-sub decode_b32b { CryptX::_decode_b32(shift, 1) } # base32hex
-sub decode_b32z { CryptX::_decode_b32(shift, 2) } # zbase32
-sub decode_b32c { CryptX::_decode_b32(shift, 3) } # crockford
-
-
-sub increment_octets_be {
- CryptX::_increment_octets_be(@_);
- #$_[0] = CryptX::_increment_octets_be($_[0]);
-}
-
-sub increment_octets_le {
- CryptX::_increment_octets_le(@_);
- #$_[0] = CryptX::_increment_octets_le($_[0]);
-}
-
sub pem_to_der {
my ($data, $password) = @_;
@@ -194,6 +157,7 @@ sub der_to_pem {
}
sub read_rawfile {
+ # $data = read_rawfile($filename);
my $f = shift;
croak "FATAL: read_rawfile() non-existing file '$f'" unless -f $f;
open my $fh, "<", $f or croak "FATAL: read_rawfile() cannot open file '$f': $!";
diff --git a/lib/Crypt/Mode.pm b/lib/Crypt/Mode.pm
index eb00dad5..a8474588 100644
--- a/lib/Crypt/Mode.pm
+++ b/lib/Crypt/Mode.pm
@@ -2,64 +2,9 @@ package Crypt::Mode;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
-### METHODS
-
-sub new { die } # overriden in subclass
-
-sub encrypt {
- my ($self, $pt) = (shift, shift);
- $self->_start(1, @_);
- return $self->add($pt) . $self->finish;
-}
-
-sub decrypt {
- my ($self, $ct) = (shift, shift);
- $self->_start(-1, @_);
- return $self->add($ct) . $self->finish;
-}
-
-sub start_encrypt {
- my $self = shift;
- $self->_start(1, @_);
- return $self;
-}
-
-sub start_decrypt {
- my $self = shift;
- $self->_start(-1, @_);
- return $self;
-}
-
-sub finish {
- shift->_finish(@_);
-}
-
-sub add {
- my $self = shift;
- my $rv = '';
- $rv .= $self->_crypt($_) for (@_);
- return $rv;
-}
-
-sub _crypt {
- my $self = shift;
- my $dir = $self->_get_dir;
- return $self->_encrypt(@_) if $dir == 1;
- return $self->_decrypt(@_) if $dir == -1;
- return;
-}
-
-sub _finish {
- my $self = shift;
- my $dir = $self->_get_dir;
- return $self->_finish_enc(@_) if $dir == 1;
- return $self->_finish_dec(@_) if $dir == -1;
- return;
-}
-
-sub CLONE_SKIP { 1 } # prevent cloning
+### not used
1;
diff --git a/lib/Crypt/Mode/CBC.pm b/lib/Crypt/Mode/CBC.pm
index 2993770b..be0a98cd 100644
--- a/lib/Crypt/Mode/CBC.pm
+++ b/lib/Crypt/Mode/CBC.pm
@@ -4,12 +4,23 @@ package Crypt::Mode::CBC;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use Crypt::Cipher;
-use base 'Crypt::Mode';
-sub new { my $class = shift; _new(Crypt::Cipher::_trans_cipher_name(shift), @_) }
+sub encrypt {
+ my ($self, $pt) = (shift, shift);
+ local $SIG{__DIE__} = \&CryptX::_croak;
+ $self->start_encrypt(@_)->add($pt) . $self->finish;
+}
+
+sub decrypt {
+ my ($self, $ct) = (shift, shift);
+ local $SIG{__DIE__} = \&CryptX::_croak;
+ $self->start_decrypt(@_)->add($ct) . $self->finish;
+}
+
+sub CLONE_SKIP { 1 } # prevent cloning
1;
diff --git a/lib/Crypt/Mode/CFB.pm b/lib/Crypt/Mode/CFB.pm
index 00528f3b..effa2404 100644
--- a/lib/Crypt/Mode/CFB.pm
+++ b/lib/Crypt/Mode/CFB.pm
@@ -4,12 +4,23 @@ package Crypt::Mode::CFB;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use Crypt::Cipher;
-use base 'Crypt::Mode';
-sub new { my $class = shift; _new(Crypt::Cipher::_trans_cipher_name(shift), @_) }
+sub encrypt {
+ my ($self, $pt) = (shift, shift);
+ local $SIG{__DIE__} = \&CryptX::_croak;
+ $self->start_encrypt(@_)->add($pt);
+}
+
+sub decrypt {
+ my ($self, $ct) = (shift, shift);
+ local $SIG{__DIE__} = \&CryptX::_croak;
+ $self->start_decrypt(@_)->add($ct);
+}
+
+sub CLONE_SKIP { 1 } # prevent cloning
1;
diff --git a/lib/Crypt/Mode/CTR.pm b/lib/Crypt/Mode/CTR.pm
index 7bfcef21..b8a6e647 100644
--- a/lib/Crypt/Mode/CTR.pm
+++ b/lib/Crypt/Mode/CTR.pm
@@ -4,12 +4,23 @@ package Crypt::Mode::CTR;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use Crypt::Cipher;
-use base 'Crypt::Mode';
-sub new { my $class = shift; _new(Crypt::Cipher::_trans_cipher_name(shift), @_) }
+sub encrypt {
+ my ($self, $pt) = (shift, shift);
+ local $SIG{__DIE__} = \&CryptX::_croak;
+ $self->start_encrypt(@_)->add($pt);
+}
+
+sub decrypt {
+ my ($self, $ct) = (shift, shift);
+ local $SIG{__DIE__} = \&CryptX::_croak;
+ $self->start_decrypt(@_)->add($ct);
+}
+
+sub CLONE_SKIP { 1 } # prevent cloning
1;
diff --git a/lib/Crypt/Mode/ECB.pm b/lib/Crypt/Mode/ECB.pm
index 3826d1b5..73711ffe 100644
--- a/lib/Crypt/Mode/ECB.pm
+++ b/lib/Crypt/Mode/ECB.pm
@@ -4,12 +4,23 @@ package Crypt::Mode::ECB;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use Crypt::Cipher;
-use base 'Crypt::Mode';
-sub new { my $class = shift; _new(Crypt::Cipher::_trans_cipher_name(shift), @_) }
+sub encrypt {
+ my ($self, $pt) = (shift, shift);
+ local $SIG{__DIE__} = \&CryptX::_croak;
+ $self->start_encrypt(@_)->add($pt) . $self->finish;
+}
+
+sub decrypt {
+ my ($self, $ct) = (shift, shift);
+ local $SIG{__DIE__} = \&CryptX::_croak;
+ $self->start_decrypt(@_)->add($ct) . $self->finish;
+}
+
+sub CLONE_SKIP { 1 } # prevent cloning
1;
diff --git a/lib/Crypt/Mode/OFB.pm b/lib/Crypt/Mode/OFB.pm
index 25bb3e9d..7ef45437 100644
--- a/lib/Crypt/Mode/OFB.pm
+++ b/lib/Crypt/Mode/OFB.pm
@@ -4,12 +4,23 @@ package Crypt::Mode::OFB;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use Crypt::Cipher;
-use base 'Crypt::Mode';
-sub new { my $class = shift; _new(Crypt::Cipher::_trans_cipher_name(shift), @_) }
+sub encrypt {
+ my ($self, $pt) = (shift, shift);
+ local $SIG{__DIE__} = \&CryptX::_croak;
+ $self->start_encrypt(@_)->add($pt);
+}
+
+sub decrypt {
+ my ($self, $ct) = (shift, shift);
+ local $SIG{__DIE__} = \&CryptX::_croak;
+ $self->start_decrypt(@_)->add($ct);
+}
+
+sub CLONE_SKIP { 1 } # prevent cloning
1;
diff --git a/lib/Crypt/PK.pm b/lib/Crypt/PK.pm
index c8285563..28d7bb6e 100644
--- a/lib/Crypt/PK.pm
+++ b/lib/Crypt/PK.pm
@@ -2,7 +2,7 @@ package Crypt::PK;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use Carp;
diff --git a/lib/Crypt/PK/DH.pm b/lib/Crypt/PK/DH.pm
index aa3786c5..1f9971d9 100644
--- a/lib/Crypt/PK/DH.pm
+++ b/lib/Crypt/PK/DH.pm
@@ -2,7 +2,7 @@ package Crypt::PK::DH;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import';
our %EXPORT_TAGS = ( all => [qw( dh_shared_secret )] );
@@ -168,10 +168,8 @@ my %DH_PARAMS = (
);
sub new {
- my ($class, $f) = @_;
- my $self = _new();
- $self->import_key($f) if $f;
- return $self;
+ my $self = shift->_new();
+ return @_ > 0 ? $self->import_key(@_) : $self;
}
sub import_key {
diff --git a/lib/Crypt/PK/DSA.pm b/lib/Crypt/PK/DSA.pm
index afd64850..3ce42994 100644
--- a/lib/Crypt/PK/DSA.pm
+++ b/lib/Crypt/PK/DSA.pm
@@ -2,7 +2,7 @@ package Crypt::PK::DSA;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import';
our %EXPORT_TAGS = ( all => [qw( dsa_encrypt dsa_decrypt dsa_sign_message dsa_verify_message dsa_sign_hash dsa_verify_hash )] );
@@ -10,16 +10,15 @@ our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw();
use Carp;
+$Carp::Internal{(__PACKAGE__)}++;
use CryptX;
use Crypt::Digest 'digest_data';
use Crypt::Misc qw(read_rawfile encode_b64u decode_b64u encode_b64 decode_b64 pem_to_der der_to_pem);
use Crypt::PK;
sub new {
- my ($class, $f, $p) = @_;
- my $self = _new();
- $self->import_key($f, $p) if $f;
- return $self;
+ my $self = shift->_new();
+ return @_ > 0 ? $self->import_key(@_) : $self;
}
sub generate_key {
@@ -96,55 +95,11 @@ sub import_key {
croak "FATAL: invalid or unsupported DSA key format";
}
-sub encrypt {
- my ($self, $data, $hash_name) = @_;
- $hash_name = Crypt::Digest::_trans_digest_name($hash_name||'SHA1');
- return $self->_encrypt($data, $hash_name);
-}
-
-sub decrypt {
- my ($self, $data) = @_;
- return $self->_decrypt($data);
-}
-
-sub _truncate {
- my ($self, $hash) = @_;
- ### section 4.6 of FIPS 186-4
- # let N be the bit length of q
- # z = the leftmost min(N, outlen) bits of Hash(M).
- my $q = $self->size_q; # = size in bytes
- return $hash if $q >= length($hash);
- return substr($hash, 0, $q);
-}
-
-sub sign_message {
- my ($self, $data, $hash_name) = @_;
- $hash_name ||= 'SHA1';
- my $data_hash = digest_data($hash_name, $data);
- return $self->_sign($self->_truncate($data_hash));
-}
-
-sub verify_message {
- my ($self, $sig, $data, $hash_name) = @_;
- $hash_name ||= 'SHA1';
- my $data_hash = digest_data($hash_name, $data);
- return $self->_verify($sig, $self->_truncate($data_hash));
-}
-
-sub sign_hash {
- my ($self, $data_hash) = @_;
- return $self->_sign($self->_truncate($data_hash));
-}
-
-sub verify_hash {
- my ($self, $sig, $data_hash) = @_;
- return $self->_verify($sig, $self->_truncate($data_hash));
-}
-
### FUNCTIONS
sub dsa_encrypt {
my $key = shift;
+ local $SIG{__DIE__} = \&CryptX::_croak;
$key = __PACKAGE__->new($key) unless ref $key;
carp "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
return $key->encrypt(@_);
@@ -152,6 +107,7 @@ sub dsa_encrypt {
sub dsa_decrypt {
my $key = shift;
+ local $SIG{__DIE__} = \&CryptX::_croak;
$key = __PACKAGE__->new($key) unless ref $key;
carp "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
return $key->decrypt(@_);
@@ -159,6 +115,7 @@ sub dsa_decrypt {
sub dsa_sign_message {
my $key = shift;
+ local $SIG{__DIE__} = \&CryptX::_croak;
$key = __PACKAGE__->new($key) unless ref $key;
carp "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
return $key->sign_message(@_);
@@ -166,6 +123,7 @@ sub dsa_sign_message {
sub dsa_verify_message {
my $key = shift;
+ local $SIG{__DIE__} = \&CryptX::_croak;
$key = __PACKAGE__->new($key) unless ref $key;
carp "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
return $key->verify_message(@_);
@@ -173,6 +131,7 @@ sub dsa_verify_message {
sub dsa_sign_hash {
my $key = shift;
+ local $SIG{__DIE__} = \&CryptX::_croak;
$key = __PACKAGE__->new($key) unless ref $key;
carp "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
return $key->sign_hash(@_);
@@ -180,6 +139,7 @@ sub dsa_sign_hash {
sub dsa_verify_hash {
my $key = shift;
+ local $SIG{__DIE__} = \&CryptX::_croak;
$key = __PACKAGE__->new($key) unless ref $key;
carp "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
return $key->verify_hash(@_);
diff --git a/lib/Crypt/PK/ECC.pm b/lib/Crypt/PK/ECC.pm
index 28d83589..9e2d06ab 100644
--- a/lib/Crypt/PK/ECC.pm
+++ b/lib/Crypt/PK/ECC.pm
@@ -2,7 +2,7 @@ package Crypt::PK::ECC;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import';
our %EXPORT_TAGS = ( all => [qw( ecc_encrypt ecc_decrypt ecc_sign_message ecc_verify_message ecc_sign_hash ecc_verify_hash ecc_shared_secret )] );
@@ -10,429 +10,177 @@ our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw();
use Carp;
+$Carp::Internal{(__PACKAGE__)}++;
use CryptX;
use Crypt::Digest qw(digest_data digest_data_b64u);
use Crypt::Misc qw(read_rawfile encode_b64u decode_b64u encode_b64 decode_b64 pem_to_der der_to_pem);
use Crypt::PK;
our %curve = (
- ### http://www.ecc-brainpool.org/download/Domain-parameters.pdf (v1.0 19.10.2005)
- brainpoolp160r1 => {
- oid => '1.3.36.3.3.2.8.1.1.1',
- prime => "E95E4A5F737059DC60DFC7AD95B3D8139515620F",
- A => "340E7BE2A280EB74E2BE61BADA745D97E8F7C300",
- B => "1E589A8595423412134FAA2DBDEC95C8D8675E58",
- Gx => "BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC3",
- Gy => "1667CB477A1A8EC338F94741669C976316DA6321",
- order => "E95E4A5F737059DC60DF5991D45029409E60FC09",
- cofactor => 1,
+ # extra curves not recognized by libtomcrypt
+ 'wap-wsg-idm-ecid-wtls8' => {
+ prime => "FFFFFFFFFFFFFFFFFFFFFFFFFDE7",
+ A => "0000000000000000000000000000",
+ B => "0000000000000000000000000003",
+ order => "0100000000000001ECEA551AD837E9",
+ Gx => "0000000000000000000000000001",
+ Gy => "0000000000000000000000000002",
+ cofactor => 1,
+ oid => '2.23.43.1.4.8',
},
- brainpoolp192r1 => {
- oid => '1.3.36.3.3.2.8.1.1.3',
- prime => "C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297",
- A => "6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF",
- B => "469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9",
- Gx => "C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD6",
- Gy => "14B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F",
- order => "C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1",
- cofactor => 1,
- },
- brainpoolp224r1 => {
- oid => '1.3.36.3.3.2.8.1.1.5',
- prime => "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF",
- A => "68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43",
- B => "2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B",
- Gx => "0D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D",
- Gy => "58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD",
- order => "D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F",
- cofactor => 1,
- },
- brainpoolp256r1 => {
- oid => '1.3.36.3.3.2.8.1.1.7',
- prime => "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377",
- A => "7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9",
- B => "26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6",
- Gx => "8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262",
- Gy => "547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997",
- order => "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7",
- cofactor => 1,
- },
- brainpoolp320r1 => {
- oid => '1.3.36.3.3.2.8.1.1.9',
- prime => "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27",
- A => "3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4",
- B => "520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6",
- Gx => "43BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E20611",
- Gy => "14FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1",
- order => "D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311",
- cofactor => 1,
- },
- brainpoolp384r1 => {
- oid => '1.3.36.3.3.2.8.1.1.11',
- prime => "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53",
- A => "7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826",
- B => "04A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11",
- Gx => "1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E",
- Gy => "8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315",
- order => "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565",
- cofactor => 1,
- },
- brainpoolp512r1 => {
- oid => '1.3.36.3.3.2.8.1.1.13',
- prime => "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3",
- A => "7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA",
- B => "3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723",
- Gx => "81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822",
- Gy => "7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892",
- order => "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069",
- cofactor => 1,
- },
- ### http://www.secg.org/collateral/sec2_final.pdf (September 20, 2000 - Version 1.0)
- secp112r1 => {
- oid => '1.3.132.0.6',
- prime => "DB7C2ABF62E35E668076BEAD208B",
- A => "DB7C2ABF62E35E668076BEAD2088",
- B => "659EF8BA043916EEDE8911702B22",
- Gx => "09487239995A5EE76B55F9C2F098",
- Gy => "A89CE5AF8724C0A23E0E0FF77500",
- order => "DB7C2ABF62E35E7628DFAC6561C5",
- cofactor => 1,
- },
- secp112r2 => {
- oid => '1.3.132.0.7',
- prime => "DB7C2ABF62E35E668076BEAD208B",
- A => "6127C24C05F38A0AAAF65C0EF02C",
- B => "51DEF1815DB5ED74FCC34C85D709",
- Gx => "4BA30AB5E892B4E1649DD0928643",
- Gy => "ADCD46F5882E3747DEF36E956E97",
- order => "36DF0AAFD8B8D7597CA10520D04B",
- cofactor => 4,
- },
- secp128r1 => {
- oid => '1.3.132.0.28',
- prime => "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF",
- A => "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC",
- B => "E87579C11079F43DD824993C2CEE5ED3",
- Gx => "161FF7528B899B2D0C28607CA52C5B86",
- Gy => "CF5AC8395BAFEB13C02DA292DDED7A83",
- order => "FFFFFFFE0000000075A30D1B9038A115",
- cofactor => 1,
- },
- secp128r2 => {
- oid => '1.3.132.0.29',
- prime => "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF",
- A => "D6031998D1B3BBFEBF59CC9BBFF9AEE1",
- B => "5EEEFCA380D02919DC2C6558BB6D8A5D",
- Gx => "7B6AA5D85E572983E6FB32A7CDEBC140",
- Gy => "27B6916A894D3AEE7106FE805FC34B44",
- order => "3FFFFFFF7FFFFFFFBE0024720613B5A3",
- cofactor => 4,
- },
- secp160k1 => {
- oid => '1.3.132.0.9',
- prime => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73",
- A => "0000000000000000000000000000000000000000",
- B => "0000000000000000000000000000000000000007",
- Gx => "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB",
- Gy => "938CF935318FDCED6BC28286531733C3F03C4FEE",
- order => "0100000000000000000001B8FA16DFAB9ACA16B6B3",
- cofactor => 1,
- },
- secp160r1 => {
- oid => '1.3.132.0.8',
- prime => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF",
- A => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC",
- B => "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45",
- Gx => "4A96B5688EF573284664698968C38BB913CBFC82",
- Gy => "23A628553168947D59DCC912042351377AC5FB32",
- order => "0100000000000000000001F4C8F927AED3CA752257",
- cofactor => 1,
- },
- secp160r2 => {
- oid => '1.3.132.0.30',
- prime => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73",
- A => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70",
- B => "B4E134D3FB59EB8BAB57274904664D5AF50388BA",
- Gx => "52DCB034293A117E1F4FF11B30F7199D3144CE6D",
- Gy => "FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E",
- order => "0100000000000000000000351EE786A818F3A1A16B",
- cofactor => 1,
- },
- secp192k1 => {
- oid => '1.3.132.0.31',
- prime => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37",
- A => "000000000000000000000000000000000000000000000000",
- B => "000000000000000000000000000000000000000000000003",
- Gx => "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D",
- Gy => "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D",
- order => "FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D",
- cofactor => 1,
- },
- secp192r1 => { # == NIST P-192, X9.62 prime192v1
- oid => '1.2.840.10045.3.1.1',
- prime => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
- A => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC",
- B => "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1",
- Gx => "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012",
- Gy => "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811",
- order => "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831",
- cofactor => 1,
- },
- secp224k1 => {
- oid => '1.3.132.0.32',
- prime => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D",
- A => "00000000000000000000000000000000000000000000000000000000",
- B => "00000000000000000000000000000000000000000000000000000005",
- Gx => "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C",
- Gy => "7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5",
- order => "010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7",
- cofactor => 1,
- },
- secp224r1 => { # == NIST P-224
- oid => '1.3.132.0.33',
- prime => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001",
- A => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE",
- B => "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4",
- Gx => "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21",
- Gy => "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34",
- order => "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D",
- cofactor => 1,
- },
- secp256k1 => {
- oid => '1.3.132.0.10',
- prime => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F",
- A => "0000000000000000000000000000000000000000000000000000000000000000",
- B => "0000000000000000000000000000000000000000000000000000000000000007",
- Gx => "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798",
- Gy => "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8",
- order => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141",
- cofactor => 1,
- },
- secp256r1 => { # == NIST P-256, X9.62 prime256v1
- oid => '1.2.840.10045.3.1.7',
- prime => "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
- A => "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC",
- B => "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B",
- Gx => "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296",
- Gy => "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
- order => "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
- cofactor => 1,
- },
- secp384r1 => { # == NIST P-384
- oid => '1.3.132.0.34',
- prime => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF",
- A => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC",
- B => "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF",
- Gx => "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7",
- Gy => "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F",
- order => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973",
- cofactor => 1,
- },
- secp521r1 => { # == NIST P-521
- oid => '1.3.132.0.35',
- prime => "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
- A => "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC",
- B => "0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00",
- Gx => "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66",
- Gy => "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650",
- order => "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409",
- cofactor => 1
- },
- ### http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf (July 2013)
- nistp192 => { # == secp192r1, X9.62 prime192v1
- oid => '1.2.840.10045.3.1.1',
- prime => 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF',
- A => 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC',
- B => '64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1',
- Gx => '188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012',
- Gy => '07192B95FFC8DA78631011ED6B24CDD573F977A11E794811',
- order => 'FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831',
- cofactor => 1,
- },
- nistp224 => { # == secp224r1
- oid => '1.3.132.0.33',
- prime => 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001',
- A => 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE',
- B => 'B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4',
- Gx => 'B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21',
- Gy => 'BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34',
- order => 'FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D',
- cofactor => 1,
- },
- nistp256 => { # == secp256r1, X9.62 prime256v1
- oid => '1.2.840.10045.3.1.7',
- prime => 'FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF',
- A => 'FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC',
- B => '5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B',
- Gx => '6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296',
- Gy => '4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5',
- order => 'FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551',
- cofactor => 1,
- },
- nistp384 => { # == secp384r1
- oid => '1.3.132.0.34',
- prime => 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF',
- A => 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC',
- B => 'B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF',
- Gx => 'AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7',
- Gy => '3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F',
- order => 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973',
- cofactor => 1,
- },
- nistp521 => { # == secp521r1
- oid => '1.3.132.0.35',
- prime => '1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF',
- A => '1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC',
- B => '051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00',
- Gx => '0C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66',
- Gy => '11839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650',
- order => '1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409',
- cofactor => 1,
- },
- ### ANS X9.62 elliptic curves - http://www.flexiprovider.de/CurvesGfpX962.html
- prime192v1 => { # == secp192r1, NIST P-192
- oid => '1.2.840.10045.3.1.1',
- prime => 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF',
- A => 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC',
- B => '64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1',
- Gx => '188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012',
- Gy => '07192B95FFC8DA78631011ED6B24CDD573F977A11E794811',
- order => 'FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831',
- cofactor => 1,
- },
- prime192v2 => {
- oid => '1.2.840.10045.3.1.2',
- prime => 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF',
- A => 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC',
- B => 'CC22D6DFB95C6B25E49C0D6364A4E5980C393AA21668D953',
- Gx => 'EEA2BAE7E1497842F2DE7769CFE9C989C072AD696F48034A',
- Gy => '6574D11D69B6EC7A672BB82A083DF2F2B0847DE970B2DE15',
- order => 'FFFFFFFFFFFFFFFFFFFFFFFE5FB1A724DC80418648D8DD31',
- cofactor => 1
- },
- prime192v3 => {
- oid => '1.2.840.10045.3.1.3',
- prime => 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF',
- A => 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC',
- B => '22123DC2395A05CAA7423DAECCC94760A7D462256BD56916',
- Gx => '7D29778100C65A1DA1783716588DCE2B8B4AEE8E228F1896',
- Gy => '38A90F22637337334B49DCB66A6DC8F9978ACA7648A943B0',
- order => 'FFFFFFFFFFFFFFFFFFFFFFFF7A62D031C83F4294F640EC13',
- cofactor => 1,
- },
- prime239v1 => {
- oid => '1.2.840.10045.3.1.4',
- prime => '7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF',
- A => '7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC',
- B => '6B016C3BDCF18941D0D654921475CA71A9DB2FB27D1D37796185C2942C0A',
- Gx => '0FFA963CDCA8816CCC33B8642BEDF905C3D358573D3F27FBBD3B3CB9AAAF',
- Gy => '7DEBE8E4E90A5DAE6E4054CA530BA04654B36818CE226B39FCCB7B02F1AE',
- order => '7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF9E5E9A9F5D9071FBD1522688909D0B',
- cofactor => 1,
- },
- prime239v2 => {
- oid => '1.2.840.10045.3.1.5',
- prime => '7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF',
- A => '7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC',
- B => '617FAB6832576CBBFED50D99F0249C3FEE58B94BA0038C7AE84C8C832F2C',
- Gx => '38AF09D98727705120C921BB5E9E26296A3CDCF2F35757A0EAFD87B830E7',
- Gy => '5B0125E4DBEA0EC7206DA0FC01D9B081329FB555DE6EF460237DFF8BE4BA',
- order => '7FFFFFFFFFFFFFFFFFFFFFFF800000CFA7E8594377D414C03821BC582063',
- cofactor => 1,
- },
- prime239v3 => {
- oid => '1.2.840.10045.3.1.6',
- prime => '7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF',
- A => '7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC',
- B => '255705FA2A306654B1F4CB03D6A750A30C250102D4988717D9BA15AB6D3E',
- Gx => '6768AE8E18BB92CFCF005C949AA2C6D94853D0E660BBF854B1C9505FE95A',
- Gy => '1607E6898F390C06BC1D552BAD226F3B6FCFE48B6E818499AF18E3ED6CF3',
- order => '7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF975DEB41B3A6057C3C432146526551',
- cofactor => 1,
- },
- prime256v1 => { # == secp256r1, NIST P-256
- oid => '1.2.840.10045.3.1.7',
- prime => 'FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF',
- A => 'FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC',
- B => '5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B',
- Gx => '6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296',
- Gy => '4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5',
- order => 'FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551',
- cofactor => 1,
+ 'wap-wsg-idm-ecid-wtls9' => {
+ prime => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC808F",
+ A => "0000000000000000000000000000000000000000",
+ B => "0000000000000000000000000000000000000003",
+ order => "0100000000000000000001CDC98AE0E2DE574ABF33",
+ Gx => "0000000000000000000000000000000000000001",
+ Gy => "0000000000000000000000000000000000000002",
+ cofactor => 1,
+ oid => '2.23.43.1.4.9',
},
);
-my %jwkcrv = (
- 'P-192' => 'secp192r1',
- 'P-224' => 'secp224r1',
- 'P-256' => 'secp256r1',
- 'P-384' => 'secp384r1',
- 'P-521' => 'secp521r1',
+my %jwk2curve = (
+ 'P-192' => 'secp192r1',
+ 'P-224' => 'secp224r1',
+ 'P-256' => 'secp256r1',
+ 'P-384' => 'secp384r1',
+ 'P-521' => 'secp521r1',
+);
+
+my %curve2jwk = (
+ '1.2.840.10045.3.1.1' => 'P-192', # secp192r1
+ '1.3.132.0.33' => 'P-224', # secp224r1
+ '1.2.840.10045.3.1.7' => 'P-256', # secp256r1
+ '1.3.132.0.34' => 'P-384', # secp384r1
+ '1.3.132.0.35' => 'P-521', # secp521r1
+ 'nistp192' => 'P-192',
+ 'nistp224' => 'P-224',
+ 'nistp256' => 'P-256',
+ 'nistp384' => 'P-384',
+ 'nistp521' => 'P-521',
+ 'prime192v1' => 'P-192',
+ 'prime256v1' => 'P-256',
+ 'secp192r1' => 'P-192',
+ 'secp224r1' => 'P-224',
+ 'secp256r1' => 'P-256',
+ 'secp384r1' => 'P-384',
+ 'secp521r1' => 'P-521',
+);
+
+our %curve2ltc = ( # must be "our" as we use it from XS code
+ # OIDs
+ "1.2.840.10045.3.1.1" => "SECP192R1",
+ "1.2.840.10045.3.1.2" => "PRIME192V2",
+ "1.2.840.10045.3.1.3" => "PRIME192V3",
+ "1.2.840.10045.3.1.4" => "PRIME239V1",
+ "1.2.840.10045.3.1.5" => "PRIME239V2",
+ "1.2.840.10045.3.1.6" => "PRIME239V3",
+ "1.2.840.10045.3.1.7" => "SECP256R1",
+ "1.3.132.0.10" => "SECP256K1",
+ "1.3.132.0.28" => "SECP128R1",
+ "1.3.132.0.29" => "SECP128R2",
+ "1.3.132.0.30" => "SECP160R2",
+ "1.3.132.0.31" => "SECP192K1",
+ "1.3.132.0.32" => "SECP224K1",
+ "1.3.132.0.33" => "SECP224R1",
+ "1.3.132.0.34" => "SECP384R1",
+ "1.3.132.0.35" => "SECP521R1",
+ "1.3.132.0.6" => "SECP112R1",
+ "1.3.132.0.7" => "SECP112R2",
+ "1.3.132.0.8" => "SECP160R1",
+ "1.3.132.0.9" => "SECP160K1",
+ "1.3.36.3.3.2.8.1.1.1" => "BRAINPOOLP160R1",
+ "1.3.36.3.3.2.8.1.1.11" => "BRAINPOOLP384R1",
+ "1.3.36.3.3.2.8.1.1.13" => "BRAINPOOLP512R1",
+ "1.3.36.3.3.2.8.1.1.3" => "BRAINPOOLP192R1",
+ "1.3.36.3.3.2.8.1.1.5" => "BRAINPOOLP224R1",
+ "1.3.36.3.3.2.8.1.1.7" => "BRAINPOOLP256R1",
+ "1.3.36.3.3.2.8.1.1.9" => "BRAINPOOLP320R1",
+ "1.3.36.3.3.2.8.1.1.10" => "BRAINPOOLP320T1",
+ "1.3.36.3.3.2.8.1.1.12" => "BRAINPOOLP384T1",
+ "1.3.36.3.3.2.8.1.1.14" => "BRAINPOOLP512T1",
+ "1.3.36.3.3.2.8.1.1.2" => "BRAINPOOLP160T1",
+ "1.3.36.3.3.2.8.1.1.4" => "BRAINPOOLP192T1",
+ "1.3.36.3.3.2.8.1.1.6" => "BRAINPOOLP224T1",
+ "1.3.36.3.3.2.8.1.1.8" => "BRAINPOOLP256T1",
+ # JWT names
+ "P-192" => "SECP192R1",
+ "P-224" => "SECP224R1",
+ "P-256" => "SECP256R1",
+ "P-384" => "SECP384R1",
+ "P-521" => "SECP521R1",
+ # openssl names
+ "brainpoolp160r1" => "BRAINPOOLP160R1",
+ "brainpoolp192r1" => "BRAINPOOLP192R1",
+ "brainpoolp224r1" => "BRAINPOOLP224R1",
+ "brainpoolp256r1" => "BRAINPOOLP256R1",
+ "brainpoolp320r1" => "BRAINPOOLP320R1",
+ "brainpoolp384r1" => "BRAINPOOLP384R1",
+ "brainpoolp512r1" => "BRAINPOOLP512R1",
+ "brainpoolp160t1" => "BRAINPOOLP160T1",
+ "brainpoolp192t1" => "BRAINPOOLP192T1",
+ "brainpoolp224t1" => "BRAINPOOLP224T1",
+ "brainpoolp256t1" => "BRAINPOOLP256T1",
+ "brainpoolp320t1" => "BRAINPOOLP320T1",
+ "brainpoolp384t1" => "BRAINPOOLP384T1",
+ "brainpoolp512t1" => "BRAINPOOLP512T1",
+ "nistp192" => "SECP192R1",
+ "nistp224" => "SECP224R1",
+ "nistp256" => "SECP256R1",
+ "nistp384" => "SECP384R1",
+ "nistp521" => "SECP521R1",
+ "prime192v1" => "SECP192R1",
+ "prime192v2" => "PRIME192V2",
+ "prime192v3" => "PRIME192V3",
+ "prime239v1" => "PRIME239V1",
+ "prime239v2" => "PRIME239V2",
+ "prime239v3" => "PRIME239V3",
+ "prime256v1" => "SECP256R1",
+ "secp112r1" => "SECP112R1",
+ "secp112r2" => "SECP112R2",
+ "secp128r1" => "SECP128R1",
+ "secp128r2" => "SECP128R2",
+ "secp160k1" => "SECP160K1",
+ "secp160r1" => "SECP160R1",
+ "secp160r2" => "SECP160R2",
+ "secp192k1" => "SECP192K1",
+ "secp192r1" => "SECP192R1",
+ "secp224k1" => "SECP224K1",
+ "secp224r1" => "SECP224R1",
+ "secp256k1" => "SECP256K1",
+ "secp256r1" => "SECP256R1",
+ "secp384r1" => "SECP384R1",
+ "secp521r1" => "SECP521R1",
+ "wap-wsg-idm-ecid-wtls6" => 'SECP112R1',
+ "wap-wsg-idm-ecid-wtls7" => 'SECP160R2',
+ "wap-wsg-idm-ecid-wtls12" => 'SECP224R1',
);
sub _import_hex {
my ($self, $x, $y, $k, $crv) = @_;
- my $p = $curve{$crv}{prime};
- croak "FATAL: invalid or unknown curve" if !$p;
- $p =~ s/^0+//;
- my $hex_size = length($p) % 2 ? length($p) + 1 : length($p);
- if ($k) {
- $k =~ /^0+/;
- croak "FATAL: too long private key (k)" if length($k) > $hex_size;
- my $priv_hex = "0" x ($hex_size - length($k)) . $k;
- return $self->import_key_raw(pack("H*", $priv_hex), $crv);
+ croak "FATAL: no curve" if !$crv;
+ if (defined $k && length($k) > 0) {
+ croak "FATAL: invalid length (k)" if length($k) % 2;
+ return $self->import_key_raw(pack("H*", $k), $crv);
}
- elsif ($x && $y) {
- $x =~ /^0+/;
- $y =~ /^0+/;
- croak "FATAL: too long public key (x)" if length($x) > $hex_size;
- croak "FATAL: too long public key (y)" if length($y) > $hex_size;
- my $pub_hex = "04" . ("0" x ($hex_size - length($x))) . $x . ("0" x ($hex_size - length($y))) . $y;
+ elsif (defined $x && defined $y) {
+ croak "FATAL: invalid length (x)" if length($x) % 2;
+ croak "FATAL: invalid length (y)" if length($y) % 2;
+ croak "FATAL: invalid length (x,y)" if length($y) != length($x);
+ my $pub_hex = "04" . $x . $y;
return $self->import_key_raw(pack("H*", $pub_hex), $crv);
}
}
-sub _curve_name_lookup {
- my ($self, $key) = @_;
-
- return $key->{curve_name} if $key->{curve_name} && exists $curve{$key->{curve_name}};
-
- defined(my $A = $key->{curve_A}) or return;
- defined(my $B = $key->{curve_B}) or return;
- defined(my $Gx = $key->{curve_Gx}) or return;
- defined(my $Gy = $key->{curve_Gy}) or return;
- defined(my $order = $key->{curve_order}) or return;
- defined(my $prime = $key->{curve_prime}) or return;
- defined(my $cofactor = $key->{curve_cofactor}) or return;
- $A =~ s/^0+//;
- $B =~ s/^0+//;
- $Gx =~ s/^0+//;
- $Gy =~ s/^0+//;
- $order =~ s/^0+//;
- $prime =~ s/^0+//;
-
- for my $k (sort keys %curve) {
- (my $c_A = $curve{$k}{A} ) =~ s/^0+//;
- (my $c_B = $curve{$k}{B} ) =~ s/^0+//;
- (my $c_Gx = $curve{$k}{Gx} ) =~ s/^0+//;
- (my $c_Gy = $curve{$k}{Gy} ) =~ s/^0+//;
- (my $c_order = $curve{$k}{order} ) =~ s/^0+//;
- (my $c_prime = $curve{$k}{prime} ) =~ s/^0+//;
- my $c_cofactor = $curve{$k}{cofactor};
- return $k if $A eq $c_A && $B eq $c_B && $Gx eq $c_Gx && $Gy eq $c_Gy &&
- $order eq $c_order && $prime eq $c_prime && $cofactor == $c_cofactor;
- }
-}
-
sub new {
- my ($class, $f, $p) = @_;
- my $self = _new();
- $self->import_key($f, $p) if $f;
- return $self;
+ my $self = shift->_new();
+ return @_ > 0 ? $self->import_key(@_) : $self;
}
sub export_key_pem {
my ($self, $type, $password, $cipher) = @_;
+ local $SIG{__DIE__} = \&CryptX::_croak;
my $key = $self->export_key_der($type||'');
return unless $key;
return der_to_pem($key, "EC PRIVATE KEY", $password, $cipher) if substr($type, 0, 7) eq 'private';
@@ -441,13 +189,11 @@ sub export_key_pem {
sub export_key_jwk {
my ($self, $type, $wanthash) = @_;
+ local $SIG{__DIE__} = \&CryptX::_croak;
my $kh = $self->key2hash;
- my $curve = $self->_curve_name_lookup($kh);
- $curve = 'P-192' if $curve =~ /(secp192r1|nistp192|prime192v1)/;
- $curve = 'P-224' if $curve =~ /(secp224r1|nistp224)/;
- $curve = 'P-256' if $curve =~ /(secp256r1|nistp256|prime256v1)/;
- $curve = 'P-384' if $curve =~ /(secp384r1|nistp384)/;
- $curve = 'P-521' if $curve =~ /(secp521r1|nistp521)/;
+ $kh->{curve_oid} = '' if !defined $kh->{curve_oid};
+ $kh->{curve_name} = '' if !defined $kh->{curve_name};
+ my $curve_jwt = $curve2jwk{$kh->{curve_oid}} || $curve2jwk{lc $kh->{curve_name}} || $kh->{curve_name};
if ($type && $type eq 'private') {
return unless $kh->{pub_x} && $kh->{pub_y} && $kh->{k};
for (qw/pub_x pub_y k/) {
@@ -456,7 +202,7 @@ sub export_key_jwk {
# NOTE: x + y are not necessary in privkey
# but they are used in https://tools.ietf.org/html/rfc7517#appendix-A.2
my $hash = {
- kty => "EC", crv=>$curve,
+ kty => "EC", crv => $curve_jwt,
x => encode_b64u(pack("H*", $kh->{pub_x})),
y => encode_b64u(pack("H*", $kh->{pub_y})),
d => encode_b64u(pack("H*", $kh->{k})),
@@ -469,7 +215,7 @@ sub export_key_jwk {
$kh->{$_} = "0$kh->{$_}" if length($kh->{$_}) % 2;
}
my $hash = {
- kty => "EC", crv=>$curve,
+ kty => "EC", crv => $curve_jwt,
x => encode_b64u(pack("H*", $kh->{pub_x})),
y => encode_b64u(pack("H*", $kh->{pub_y})),
};
@@ -479,6 +225,7 @@ sub export_key_jwk {
sub export_key_jwk_thumbprint {
my ($self, $hash_name) = @_;
+ local $SIG{__DIE__} = \&CryptX::_croak;
$hash_name ||= 'SHA256';
my $h = $self->export_key_jwk('public', 1);
my $json = CryptX::_encode_json({crv=>$h->{crv}, kty=>$h->{kty}, x=>$h->{x}, y=>$h->{y}});
@@ -487,15 +234,15 @@ sub export_key_jwk_thumbprint {
sub import_key {
my ($self, $key, $password) = @_;
+ local $SIG{__DIE__} = \&CryptX::_croak;
croak "FATAL: undefined key" unless $key;
# special case
if (ref($key) eq 'HASH') {
if (($key->{pub_x} && $key->{pub_y}) || $key->{k}) {
# hash exported via key2hash
- my $curve = $self->_curve_name_lookup($key);
- croak "FATAL: invalid or unknown curve" if !$curve;
- return $self->_import_hex($key->{pub_x}, $key->{pub_y}, $key->{k}, $curve);
+ my $curve_name = $key->{curve_name} || $key->{curve_oid};
+ return $self->_import_hex($key->{pub_x}, $key->{pub_y}, $key->{k}, $curve_name);
}
if ($key->{crv} && $key->{kty} && $key->{kty} eq "EC" && ($key->{d} || ($key->{x} && $key->{y}))) {
# hash with items corresponding to JSON Web Key (JWK)
@@ -503,11 +250,11 @@ sub import_key {
for (qw/x y d/) {
$key->{$_} = eval { unpack("H*", decode_b64u($key->{$_})) } if exists $key->{$_};
}
- if (my $curve = $jwkcrv{$key->{crv}}) {
- return $self->_import_hex($key->{x}, $key->{y}, $key->{d}, $curve);
+ if (my $curve_name = $jwk2curve{$key->{crv}}) {
+ return $self->_import_hex($key->{x}, $key->{y}, $key->{d}, $curve_name);
}
# curve is not JWK compliant e.g. P-192 P-224 P-256 P-384 P-521 (we'll try to import anyway)
- return $self->_import_hex($key->{x}, $key->{y}, $key->{d}, lc($key->{crv}));
+ return $self->_import_hex($key->{x}, $key->{y}, $key->{d}, $key->{crv});
}
croak "FATAL: unexpected ECC key hash";
}
@@ -533,8 +280,8 @@ sub import_key {
return $self->_import_pkcs8($data, $password);
}
elsif ($data =~ /-----BEGIN ENCRYPTED PRIVATE KEY-----(.*?)-----END/sg) {
- # XXX-TODO: pkcs#8 encrypted private key
- croak "FATAL: encrypted pkcs8 EC private keys are not supported";
+ $data = pem_to_der($data, $password);
+ return $self->_import_pkcs8($data, $password);
}
elsif ($data =~ /^\s*(\{.*?\})\s*$/s) {
# JSON Web Key (JWK) - http://tools.ietf.org/html/draft-ietf-jose-json-web-key
@@ -544,13 +291,17 @@ sub import_key {
for (qw/x y d/) {
$h->{$_} = eval { unpack("H*", decode_b64u($h->{$_})) } if exists $h->{$_};
}
- if (my $curve = $jwkcrv{$h->{crv}}) {
- return $self->_import_hex($h->{x}, $h->{y}, $h->{d}, $curve);
+ if (my $curve_name = $jwk2curve{$h->{crv}}) {
+ return $self->_import_hex($h->{x}, $h->{y}, $h->{d}, $curve_name);
}
# curve is not JWK compliant e.g. P-192 P-224 P-256 P-384 P-521 (we'll try to import anyway)
- return $self->_import_hex($h->{x}, $h->{y}, $h->{d}, lc($h->{crv}));
+ return $self->_import_hex($h->{x}, $h->{y}, $h->{d}, $h->{crv});
}
}
+ elsif ($data =~ /-----BEGIN CERTIFICATE-----(.*?)-----END CERTIFICATE-----/sg) {
+ $data = pem_to_der($data);
+ return $self->_import_x509($data);
+ }
elsif ($data =~ /---- BEGIN SSH2 PUBLIC KEY ----(.*?)---- END SSH2 PUBLIC KEY ----/sg) {
$data = pem_to_der($data);
my ($typ, $skip, $pubkey) = Crypt::PK::_ssh_parse($data);
@@ -562,61 +313,12 @@ sub import_key {
return $self->import_key_raw($pubkey, "$2") if $pubkey && $typ =~ /^ecdsa-(.+?)-(.*)$/;
}
else {
- my $rv = eval { $self->_import($data) } || eval { $self->_import_pkcs8($data, $password) };
+ my $rv = eval { $self->_import($data) } || eval { $self->_import_pkcs8($data, $password) } || eval { $self->_import_x509($data) };
return $rv if $rv;
}
croak "FATAL: invalid or unsupported EC key format";
}
-sub encrypt {
- my ($self, $data, $hash_name) = @_;
- $hash_name = Crypt::Digest::_trans_digest_name($hash_name||'SHA1');
- return $self->_encrypt($data, $hash_name);
-}
-
-sub decrypt {
- my ($self, $data) = @_;
- return $self->_decrypt($data);
-}
-
-sub sign_message {
- my ($self, $data, $hash_name) = @_;
- $hash_name ||= 'SHA1';
- my $data_hash = digest_data($hash_name, $data);
- return $self->_sign($data_hash);
-}
-
-sub sign_message_rfc7518 {
- my ($self, $data, $hash_name) = @_;
- $hash_name ||= 'SHA1';
- my $data_hash = digest_data($hash_name, $data);
- return $self->_sign_rfc7518($data_hash);
-}
-
-sub verify_message {
- my ($self, $sig, $data, $hash_name) = @_;
- $hash_name ||= 'SHA1';
- my $data_hash = digest_data($hash_name, $data);
- return $self->_verify($sig, $data_hash);
-}
-
-sub verify_message_rfc7518 {
- my ($self, $sig, $data, $hash_name) = @_;
- $hash_name ||= 'SHA1';
- my $data_hash = digest_data($hash_name, $data);
- return $self->_verify_rfc7518($sig, $data_hash);
-}
-
-sub sign_hash {
- my ($self, $data_hash) = @_;
- return $self->_sign($data_hash);
-}
-
-sub verify_hash {
- my ($self, $sig, $data_hash) = @_;
- return $self->_verify($sig, $data_hash);
-}
-
sub curve2hash {
my $self = shift;
my $kh = $self->key2hash;
@@ -627,7 +329,8 @@ sub curve2hash {
Gx => $kh->{curve_Gx},
Gy => $kh->{curve_Gy},
cofactor => $kh->{curve_cofactor},
- order => $kh->{curve_order}
+ order => $kh->{curve_order},
+ oid => $kh->{curve_oid},
};
}
@@ -635,6 +338,7 @@ sub curve2hash {
sub ecc_encrypt {
my $key = shift;
+ local $SIG{__DIE__} = \&CryptX::_croak;
$key = __PACKAGE__->new($key) unless ref $key;
carp "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
return $key->encrypt(@_);
@@ -642,6 +346,7 @@ sub ecc_encrypt {
sub ecc_decrypt {
my $key = shift;
+ local $SIG{__DIE__} = \&CryptX::_croak;
$key = __PACKAGE__->new($key) unless ref $key;
carp "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
return $key->decrypt(@_);
@@ -649,6 +354,7 @@ sub ecc_decrypt {
sub ecc_sign_message {
my $key = shift;
+ local $SIG{__DIE__} = \&CryptX::_croak;
$key = __PACKAGE__->new($key) unless ref $key;
carp "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
return $key->sign_message(@_);
@@ -656,6 +362,7 @@ sub ecc_sign_message {
sub ecc_verify_message {
my $key = shift;
+ local $SIG{__DIE__} = \&CryptX::_croak;
$key = __PACKAGE__->new($key) unless ref $key;
carp "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
return $key->verify_message(@_);
@@ -663,6 +370,7 @@ sub ecc_verify_message {
sub ecc_sign_hash {
my $key = shift;
+ local $SIG{__DIE__} = \&CryptX::_croak;
$key = __PACKAGE__->new($key) unless ref $key;
carp "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
return $key->sign_hash(@_);
@@ -670,6 +378,7 @@ sub ecc_sign_hash {
sub ecc_verify_hash {
my $key = shift;
+ local $SIG{__DIE__} = \&CryptX::_croak;
$key = __PACKAGE__->new($key) unless ref $key;
carp "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
return $key->verify_hash(@_);
@@ -677,6 +386,7 @@ sub ecc_verify_hash {
sub ecc_shared_secret {
my ($privkey, $pubkey) = @_;
+ local $SIG{__DIE__} = \&CryptX::_croak;
$privkey = __PACKAGE__->new($privkey) unless ref $privkey;
$pubkey = __PACKAGE__->new($pubkey) unless ref $pubkey;
carp "FATAL: invalid 'privkey' param" unless ref($privkey) eq __PACKAGE__ && $privkey->is_private;
@@ -912,6 +622,13 @@ Supported key formats:
lBQ9T/RsLLc+PmpB1+7yPAR+oR5gZn3kJQ==
-----END EC PRIVATE KEY-----
+=item * EC private keys with curve defined by OID + compressed form (supported since: CryptX-0.059)
+
+ -----BEGIN EC PRIVATE KEY-----
+ MFcCAQEEIBG1c3z52T8XwMsahGVdOZWgKCQJfv+l7djuJjgetdbDoAoGCCqGSM49
+ AwEHoSQDIgADoBUyo8CQAFPeYPvv78ylh5MwFZjTCLQeb042TjiMJxE=
+ -----END EC PRIVATE KEY-----
+
=item * EC private keys in password protected PEM format
-----BEGIN EC PRIVATE KEY-----
@@ -944,6 +661,13 @@ Supported key formats:
CLQeb042TjiMJxG+9DLFmRSMlBQ9T/RsLLc+PmpB1+7yPAR+oR5gZn3kJQ==
-----END PUBLIC KEY-----
+=item * EC public keys with curve defined by OID + public point in compressed form (supported since: CryptX-0.059)
+
+ -----BEGIN PUBLIC KEY-----
+ MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgADoBUyo8CQAFPeYPvv78ylh5MwFZjT
+ CLQeb042TjiMJxE=
+ -----END PUBLIC KEY-----
+
=item * PKCS#8 private keys with all curve parameters
-----BEGIN PRIVATE KEY-----
@@ -964,7 +688,7 @@ Supported key formats:
lEHQYjWya2YnHaPq/iMFa7A=
-----END PRIVATE KEY-----
-=item * PKCS#8 encrypted private keys ARE NOT SUPPORTED YET!
+=item * PKCS#8 encrypted private keys - password protected keys (supported since: CryptX-0.059)
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIGYMBwGCiqGSIb3DQEMAQMwDgQINApjTa6oFl0CAggABHi+59l4d4e6KtG9yci2
@@ -973,6 +697,19 @@ Supported key formats:
4INKZyMv/G7VpZ0=
-----END ENCRYPTED PRIVATE KEY-----
+=item * EC public key from X509 certificate
+
+ -----BEGIN CERTIFICATE-----
+ MIIBdDCCARqgAwIBAgIJAL2BBClDEnnOMAoGCCqGSM49BAMEMBcxFTATBgNVBAMM
+ DFRlc3QgQ2VydCBFQzAgFw0xNzEyMzAyMDMzNDFaGA8zMDE3MDUwMjIwMzM0MVow
+ FzEVMBMGA1UEAwwMVGVzdCBDZXJ0IEVDMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE
+ KvkL2r5xZp7RzxLQJK+6tn/7lic+L70e1fmNbHOdxRaRvbK5G0AQWrdsbjJb92Ni
+ lCQk2+w/i+VuS2Q3MSR5TaNQME4wHQYDVR0OBBYEFGbJkDyKgaMcIGHS8/WuqIVw
+ +R8sMB8GA1UdIwQYMBaAFGbJkDyKgaMcIGHS8/WuqIVw+R8sMAwGA1UdEwQFMAMB
+ Af8wCgYIKoZIzj0EAwQDSAAwRQIhAJtOsmrM+gJpImoynAyqTN+7myL71uxd+YeC
+ 6ze4MnzWAiBQi5/BqEr/SQ1+BC2TPtswvJPRFh2ZvT/6Km3gKoNVXQ==
+ -----END CERTIFICATE-----
+
=item * SSH public EC keys
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNT...T3xYfJIs=
@@ -1035,6 +772,13 @@ that does not explicitly contain curve parameters but only curve OID.
#or
my $public_der = $pk->export_key_der('public_short');
+Since CryptX-0.59 C<export_key_der> can also export keys in "compressed" format
+that defines curve by OID + stores public point in compressed form.
+
+ my $private_pem = $pk->export_key_der('private_compressed');
+ #or
+ my $public_pem = $pk->export_key_der('public_compressed');
+
=head2 export_key_pem
my $private_pem = $pk->export_key_pem('private');
@@ -1048,6 +792,13 @@ that does not explicitly contain curve parameters but only curve OID.
#or
my $public_pem = $pk->export_key_pem('public_short');
+Since CryptX-0.59 C<export_key_pem> can also export keys in "compressed" format
+that defines curve by OID + stores public point in compressed form.
+
+ my $private_pem = $pk->export_key_pem('private_compressed');
+ #or
+ my $public_pem = $pk->export_key_pem('public_compressed');
+
Support for password protected PEM keys
my $private_pem = $pk->export_key_pem('private', $password);
@@ -1154,11 +905,25 @@ Same as L<verify_message|/verify_message> only the signature format is as define
my $pk = Crypt::PK::ECC->new($priv_key_filename);
my $signature = $priv->sign_hash($message_hash);
+=head2 sign_hash_rfc7518
+
+I<Since: CryptX-0.059>
+
+Same as L<sign_hash|/sign_hash> only the signature format is as defined by L<https://tools.ietf.org/html/rfc7518>
+(JWA - JSON Web Algorithms).
+
=head2 verify_hash
my $pk = Crypt::PK::ECC->new($pub_key_filename);
my $valid = $pub->verify_hash($signature, $message_hash);
+=head2 verify_hash_rfc7518
+
+I<Since: CryptX-0.059>
+
+Same as L<verify_hash|/verify_hash> only the signature format is as defined by L<https://tools.ietf.org/html/rfc7518>
+(JWA - JSON Web Algorithms).
+
=head2 shared_secret
# Alice having her priv key $pk and Bob's public key $pkb
diff --git a/lib/Crypt/PK/RSA.pm b/lib/Crypt/PK/RSA.pm
index 0344a80c..722b4ed9 100644
--- a/lib/Crypt/PK/RSA.pm
+++ b/lib/Crypt/PK/RSA.pm
@@ -2,7 +2,7 @@ package Crypt::PK::RSA;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import';
our %EXPORT_TAGS = ( all => [qw(rsa_encrypt rsa_decrypt rsa_sign_message rsa_verify_message rsa_sign_hash rsa_verify_hash)] );
@@ -16,10 +16,8 @@ use Crypt::Misc qw(read_rawfile encode_b64u decode_b64u encode_b64 decode_b64 pe
use Crypt::PK;
sub new {
- my ($class, $f, $p) = @_;
- my $self = _new();
- $self->import_key($f, $p) if $f;
- return $self;
+ my $self = shift->_new();
+ return @_ > 0 ? $self->import_key(@_) : $self;
}
sub export_key_pem {
@@ -165,64 +163,11 @@ sub import_key {
croak "FATAL: invalid or unsupported RSA key format";
}
-sub encrypt {
- my ($self, $data, $padding, $hash_name, $lparam) = @_;
- $lparam ||= '';
- $padding ||= 'oaep';
- $hash_name = Crypt::Digest::_trans_digest_name($hash_name||'SHA1');
-
- return $self->_encrypt($data, $padding, $hash_name, $lparam);
-}
-
-sub decrypt {
- my ($self, $data, $padding, $hash_name, $lparam) = @_;
- $lparam ||= '';
- $padding ||= 'oaep';
- $hash_name = Crypt::Digest::_trans_digest_name($hash_name||'SHA1');
-
- return $self->_decrypt($data, $padding, $hash_name, $lparam);
-}
-
-sub sign_hash {
- my ($self, $data, $hash_name, $padding, $saltlen) = @_;
- $saltlen ||= 12;
- $padding ||= 'pss';
- $hash_name = Crypt::Digest::_trans_digest_name($hash_name||'SHA1');
-
- return $self->_sign($data, $padding, $hash_name, $saltlen);
-}
-
-sub sign_message {
- my ($self, $data, $hash_name, $padding, $saltlen) = @_;
- $saltlen ||= 12;
- $padding ||= 'pss';
- $hash_name = Crypt::Digest::_trans_digest_name($hash_name||'SHA1');
-
- return $self->_sign(digest_data($hash_name, $data), $padding, $hash_name, $saltlen);
-}
-
-sub verify_hash {
- my ($self, $sig, $data, $hash_name, $padding, $saltlen) = @_;
- $saltlen ||= 12;
- $padding ||= 'pss';
- $hash_name = Crypt::Digest::_trans_digest_name($hash_name||'SHA1');
-
- return $self->_verify($sig, $data, $padding, $hash_name, $saltlen);
-}
-
-sub verify_message {
- my ($self, $sig, $data, $hash_name, $padding, $saltlen) = @_;
- $saltlen ||= 12;
- $padding ||= 'pss';
- $hash_name = Crypt::Digest::_trans_digest_name($hash_name||'SHA1');
-
- return $self->_verify($sig, digest_data($hash_name, $data), $padding, $hash_name, $saltlen);
-}
-
### FUNCTIONS
sub rsa_encrypt {
my $key = shift;
+ local $SIG{__DIE__} = \&CryptX::_croak;
$key = __PACKAGE__->new($key) unless ref $key;
carp "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
return $key->encrypt(@_);
@@ -230,6 +175,7 @@ sub rsa_encrypt {
sub rsa_decrypt {
my $key = shift;
+ local $SIG{__DIE__} = \&CryptX::_croak;
$key = __PACKAGE__->new($key) unless ref $key;
carp "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
return $key->decrypt(@_);
@@ -237,6 +183,7 @@ sub rsa_decrypt {
sub rsa_sign_hash {
my $key = shift;
+ local $SIG{__DIE__} = \&CryptX::_croak;
$key = __PACKAGE__->new($key) unless ref $key;
carp "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
return $key->sign_hash(@_);
@@ -244,6 +191,7 @@ sub rsa_sign_hash {
sub rsa_verify_hash {
my $key = shift;
+ local $SIG{__DIE__} = \&CryptX::_croak;
$key = __PACKAGE__->new($key) unless ref $key;
carp "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
return $key->verify_hash(@_);
@@ -251,6 +199,7 @@ sub rsa_verify_hash {
sub rsa_sign_message {
my $key = shift;
+ local $SIG{__DIE__} = \&CryptX::_croak;
$key = __PACKAGE__->new($key) unless ref $key;
carp "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
return $key->sign_message(@_);
@@ -258,6 +207,7 @@ sub rsa_sign_message {
sub rsa_verify_message {
my $key = shift;
+ local $SIG{__DIE__} = \&CryptX::_croak;
$key = __PACKAGE__->new($key) unless ref $key;
carp "FATAL: invalid 'key' param" unless ref($key) eq __PACKAGE__;
return $key->verify_message(@_);
diff --git a/lib/Crypt/PRNG.pm b/lib/Crypt/PRNG.pm
index 41cfc155..12858393 100644
--- a/lib/Crypt/PRNG.pm
+++ b/lib/Crypt/PRNG.pm
@@ -2,42 +2,17 @@ package Crypt::PRNG;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
-use base qw(Exporter);
+require Exporter; our @ISA = qw(Exporter); ### use Exporter 'import';
our %EXPORT_TAGS = ( all => [qw(random_bytes random_bytes_hex random_bytes_b64 random_bytes_b64u random_string random_string_from rand irand)] );
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw();
-#BEWARE: cannot use Crypt::Misc qw(encode_b64 encode_b64u);
+use Carp;
+$Carp::Internal{(__PACKAGE__)}++;
use CryptX;
-sub _trans_prng_name {
- my $name = shift;
- $name =~ s/^Crypt::PRNG:://;
- return lc($name);
-}
-
-### METHODS
-
-sub new {
- my $pkg = shift;
- my $prng_name = $pkg eq __PACKAGE__ ? _trans_prng_name(shift||'ChaCha20') : _trans_prng_name($pkg);
- return _new($$, $prng_name, @_);
-}
-
-sub bytes { return shift->_bytes($$, shift) }
-
-sub int32 { return shift->_int32($$) }
-
-sub double { return shift->_double($$, shift) }
-
-sub bytes_hex { return unpack("H*", shift->bytes(shift)) }
-
-sub bytes_b64 { return CryptX::_encode_base64(shift->bytes(shift)) }
-
-sub bytes_b64u { return CryptX::_encode_base64url(shift->bytes(shift)) }
-
sub string {
my ($self, $len) = @_;
return $self->string_from("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", $len);
diff --git a/lib/Crypt/PRNG/ChaCha20.pm b/lib/Crypt/PRNG/ChaCha20.pm
index c0e3dc21..b44441cb 100644
--- a/lib/Crypt/PRNG/ChaCha20.pm
+++ b/lib/Crypt/PRNG/ChaCha20.pm
@@ -2,7 +2,7 @@ package Crypt::PRNG::ChaCha20;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::PRNG Exporter);
our %EXPORT_TAGS = ( all => [qw(random_bytes random_bytes_hex random_bytes_b64 random_bytes_b64u random_string random_string_from rand irand)] );
@@ -10,7 +10,6 @@ our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw();
use CryptX;
-use base 'Crypt::PRNG';
{
### stolen from Bytes::Random::Secure
diff --git a/lib/Crypt/PRNG/Fortuna.pm b/lib/Crypt/PRNG/Fortuna.pm
index 0b4b9e17..19a57096 100644
--- a/lib/Crypt/PRNG/Fortuna.pm
+++ b/lib/Crypt/PRNG/Fortuna.pm
@@ -2,7 +2,7 @@ package Crypt::PRNG::Fortuna;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::PRNG Exporter);
our %EXPORT_TAGS = ( all => [qw(random_bytes random_bytes_hex random_bytes_b64 random_bytes_b64u random_string random_string_from rand irand)] );
@@ -10,7 +10,6 @@ our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw();
use CryptX;
-use base 'Crypt::PRNG';
{
### stolen from Bytes::Random::Secure
diff --git a/lib/Crypt/PRNG/RC4.pm b/lib/Crypt/PRNG/RC4.pm
index e250b7c6..63af12f0 100644
--- a/lib/Crypt/PRNG/RC4.pm
+++ b/lib/Crypt/PRNG/RC4.pm
@@ -2,7 +2,7 @@ package Crypt::PRNG::RC4;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::PRNG Exporter);
our %EXPORT_TAGS = ( all => [qw(random_bytes random_bytes_hex random_bytes_b64 random_bytes_b64u random_string random_string_from rand irand)] );
@@ -10,7 +10,6 @@ our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw();
use CryptX;
-use base 'Crypt::PRNG';
{
### stolen from Bytes::Random::Secure
diff --git a/lib/Crypt/PRNG/Sober128.pm b/lib/Crypt/PRNG/Sober128.pm
index 3fc29253..1249ec89 100644
--- a/lib/Crypt/PRNG/Sober128.pm
+++ b/lib/Crypt/PRNG/Sober128.pm
@@ -2,7 +2,7 @@ package Crypt::PRNG::Sober128;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::PRNG Exporter);
our %EXPORT_TAGS = ( all => [qw(random_bytes random_bytes_hex random_bytes_b64 random_bytes_b64u random_string random_string_from rand irand)] );
@@ -10,7 +10,6 @@ our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw();
use CryptX;
-use base 'Crypt::PRNG';
{
### stolen from Bytes::Random::Secure
diff --git a/lib/Crypt/PRNG/Yarrow.pm b/lib/Crypt/PRNG/Yarrow.pm
index f85450c8..70052a17 100644
--- a/lib/Crypt/PRNG/Yarrow.pm
+++ b/lib/Crypt/PRNG/Yarrow.pm
@@ -2,7 +2,7 @@ package Crypt::PRNG::Yarrow;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use base qw(Crypt::PRNG Exporter);
our %EXPORT_TAGS = ( all => [qw(random_bytes random_bytes_hex random_bytes_b64 random_bytes_b64u random_string random_string_from rand irand)] );
diff --git a/lib/Crypt/Stream/ChaCha.pm b/lib/Crypt/Stream/ChaCha.pm
index 80555aff..2c9eb1ac 100644
--- a/lib/Crypt/Stream/ChaCha.pm
+++ b/lib/Crypt/Stream/ChaCha.pm
@@ -2,7 +2,7 @@ package Crypt::Stream::ChaCha;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use CryptX;
diff --git a/lib/Crypt/Stream/RC4.pm b/lib/Crypt/Stream/RC4.pm
index 2d21f9ff..d1e6ed4f 100644
--- a/lib/Crypt/Stream/RC4.pm
+++ b/lib/Crypt/Stream/RC4.pm
@@ -2,7 +2,7 @@ package Crypt::Stream::RC4;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use CryptX;
diff --git a/lib/Crypt/Stream/Rabbit.pm b/lib/Crypt/Stream/Rabbit.pm
index 2facea9c..649e63db 100644
--- a/lib/Crypt/Stream/Rabbit.pm
+++ b/lib/Crypt/Stream/Rabbit.pm
@@ -2,7 +2,7 @@ package Crypt::Stream::Rabbit;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use CryptX;
diff --git a/lib/Crypt/Stream/Salsa20.pm b/lib/Crypt/Stream/Salsa20.pm
index 005ca167..26478b21 100644
--- a/lib/Crypt/Stream/Salsa20.pm
+++ b/lib/Crypt/Stream/Salsa20.pm
@@ -2,7 +2,7 @@ package Crypt::Stream::Salsa20;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use CryptX;
diff --git a/lib/Crypt/Stream/Sober128.pm b/lib/Crypt/Stream/Sober128.pm
index 1b407957..cc2db1b5 100644
--- a/lib/Crypt/Stream/Sober128.pm
+++ b/lib/Crypt/Stream/Sober128.pm
@@ -2,7 +2,7 @@ package Crypt::Stream::Sober128;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use CryptX;
diff --git a/lib/Crypt/Stream/Sosemanuk.pm b/lib/Crypt/Stream/Sosemanuk.pm
index 6e44f706..790447d9 100644
--- a/lib/Crypt/Stream/Sosemanuk.pm
+++ b/lib/Crypt/Stream/Sosemanuk.pm
@@ -2,7 +2,7 @@ package Crypt::Stream::Sosemanuk;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use CryptX;
diff --git a/lib/CryptX.pm b/lib/CryptX.pm
index 3b60a19a..ead2f929 100644
--- a/lib/CryptX.pm
+++ b/lib/CryptX.pm
@@ -2,10 +2,7 @@ package CryptX;
use strict;
use warnings ;
-our $VERSION = '0.056';
-
-use base qw(Exporter);
-our @EXPORT_OK = qw();
+our $VERSION = '0.059';
require XSLoader;
XSLoader::load('CryptX', $VERSION);
@@ -67,7 +64,7 @@ CryptX - Cryptographic toolkit (self-contained, no external libraries needed)
Cryptography in CryptX is based on L<https://github.com/libtom/libtomcrypt>
-Currently available modules:
+Available modules:
=over
@@ -99,11 +96,12 @@ L<Crypt::Digest::BLAKE2s_128>, L<Crypt::Digest::BLAKE2s_160>, L<Crypt::Digest::B
L<Crypt::Digest::CHAES>, L<Crypt::Digest::MD2>, L<Crypt::Digest::MD4>, L<Crypt::Digest::MD5>, L<Crypt::Digest::RIPEMD128>, L<Crypt::Digest::RIPEMD160>,
L<Crypt::Digest::RIPEMD256>, L<Crypt::Digest::RIPEMD320>, L<Crypt::Digest::SHA1>, L<Crypt::Digest::SHA224>, L<Crypt::Digest::SHA256>, L<Crypt::Digest::SHA384>,
L<Crypt::Digest::SHA512>, L<Crypt::Digest::SHA512_224>, L<Crypt::Digest::SHA512_256>, L<Crypt::Digest::Tiger192>, L<Crypt::Digest::Whirlpool>,
+L<Crypt::Digest::Keccak224>, L<Crypt::Digest::Keccak256>, L<Crypt::Digest::Keccak384>, L<Crypt::Digest::Keccak512>,
L<Crypt::Digest::SHA3_224>, L<Crypt::Digest::SHA3_256>, L<Crypt::Digest::SHA3_384>, L<Crypt::Digest::SHA3_512>, L<Crypt::Digest::SHAKE>
=item * Checksums
-L<Crypt::Checksum>, L<Crypt::Checksum::Adler32>, L<Crypt::Checksum::CRC32>
+L<Crypt::Checksum::Adler32>, L<Crypt::Checksum::CRC32>
=item * Message Authentication Codes
@@ -114,9 +112,9 @@ L<Crypt::Mac::Pelican>, L<Crypt::Mac::PMAC>, L<Crypt::Mac::XCBC>, L<Crypt::Mac::
L<Crypt::PK::RSA>, L<Crypt::PK::DSA>, L<Crypt::PK::ECC>, L<Crypt::PK::DH>
-=item * Cryptographically secure random number generators
+=item * Cryptographically secure random number generators - see L<Crypt::PRNG> and related modules
-L<Crypt::PRNG>, L<Crypt::PRNG::Fortuna>, L<Crypt::PRNG::Yarrow>, L<Crypt::PRNG::RC4>, L<Crypt::PRNG::Sober128>, L<Crypt::PRNG::ChaCha20>
+L<Crypt::PRNG::Fortuna>, L<Crypt::PRNG::Yarrow>, L<Crypt::PRNG::RC4>, L<Crypt::PRNG::Sober128>, L<Crypt::PRNG::ChaCha20>
=item * Key derivation functions - PBKDF1, PBKDF2 and HKDF
@@ -134,6 +132,6 @@ This program is free software; you can redistribute it and/or modify it under th
=head1 COPYRIGHT
-Copyright (c) 2013+ DCIT, a.s. L<http://www.dcit.cz> / Karel Miko
+Copyright (c) 2013+ DCIT, a.s. L<https://www.dcit.cz> / Karel Miko
=cut
diff --git a/lib/Math/BigInt/LTM.pm b/lib/Math/BigInt/LTM.pm
index 3acc41f9..9d09b43f 100644
--- a/lib/Math/BigInt/LTM.pm
+++ b/lib/Math/BigInt/LTM.pm
@@ -2,7 +2,7 @@ package Math::BigInt::LTM;
use strict;
use warnings;
-our $VERSION = '0.056';
+our $VERSION = '0.059';
use CryptX;
diff --git a/src/Makefile b/src/Makefile
index e75ff89d..6775fa91 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -66,7 +66,12 @@ ltc/modes/ofb/ofb_start.o ltc/pk/asn1/der/bit/der_decode_bit_string.o ltc/pk/asn
ltc/pk/asn1/der/bit/der_encode_bit_string.o ltc/pk/asn1/der/bit/der_encode_raw_bit_string.o \
ltc/pk/asn1/der/bit/der_length_bit_string.o ltc/pk/asn1/der/boolean/der_decode_boolean.o \
ltc/pk/asn1/der/boolean/der_encode_boolean.o ltc/pk/asn1/der/boolean/der_length_boolean.o \
-ltc/pk/asn1/der/choice/der_decode_choice.o ltc/pk/asn1/der/generalizedtime/der_decode_generalizedtime.o \
+ltc/pk/asn1/der/choice/der_decode_choice.o ltc/pk/asn1/der/custom_type/der_decode_custom_type.o \
+ltc/pk/asn1/der/custom_type/der_encode_custom_type.o ltc/pk/asn1/der/custom_type/der_length_custom_type.o \
+ltc/pk/asn1/der/general/der_asn1_maps.o ltc/pk/asn1/der/general/der_decode_asn1_identifier.o \
+ltc/pk/asn1/der/general/der_decode_asn1_length.o ltc/pk/asn1/der/general/der_encode_asn1_identifier.o \
+ltc/pk/asn1/der/general/der_encode_asn1_length.o ltc/pk/asn1/der/general/der_length_asn1_identifier.o \
+ltc/pk/asn1/der/general/der_length_asn1_length.o ltc/pk/asn1/der/generalizedtime/der_decode_generalizedtime.o \
ltc/pk/asn1/der/generalizedtime/der_encode_generalizedtime.o ltc/pk/asn1/der/generalizedtime/der_length_generalizedtime.o \
ltc/pk/asn1/der/ia5/der_decode_ia5_string.o ltc/pk/asn1/der/ia5/der_encode_ia5_string.o \
ltc/pk/asn1/der/ia5/der_length_ia5_string.o ltc/pk/asn1/der/integer/der_decode_integer.o \
@@ -77,8 +82,7 @@ ltc/pk/asn1/der/octet/der_encode_octet_string.o ltc/pk/asn1/der/octet/der_length
ltc/pk/asn1/der/printable_string/der_decode_printable_string.o ltc/pk/asn1/der/printable_string/der_encode_printable_string.o \
ltc/pk/asn1/der/printable_string/der_length_printable_string.o ltc/pk/asn1/der/sequence/der_decode_sequence_ex.o \
ltc/pk/asn1/der/sequence/der_decode_sequence_flexi.o ltc/pk/asn1/der/sequence/der_decode_sequence_multi.o \
-ltc/pk/asn1/der/sequence/der_decode_subject_public_key_info.o ltc/pk/asn1/der/sequence/der_encode_sequence_ex.o \
-ltc/pk/asn1/der/sequence/der_encode_sequence_multi.o ltc/pk/asn1/der/sequence/der_encode_subject_public_key_info.o \
+ltc/pk/asn1/der/sequence/der_encode_sequence_ex.o ltc/pk/asn1/der/sequence/der_encode_sequence_multi.o \
ltc/pk/asn1/der/sequence/der_length_sequence.o ltc/pk/asn1/der/sequence/der_sequence_free.o \
ltc/pk/asn1/der/sequence/der_sequence_shrink.o ltc/pk/asn1/der/set/der_encode_set.o \
ltc/pk/asn1/der/set/der_encode_setof.o ltc/pk/asn1/der/short_integer/der_decode_short_integer.o \
@@ -87,6 +91,7 @@ ltc/pk/asn1/der/teletex_string/der_decode_teletex_string.o ltc/pk/asn1/der/telet
ltc/pk/asn1/der/utctime/der_decode_utctime.o ltc/pk/asn1/der/utctime/der_encode_utctime.o \
ltc/pk/asn1/der/utctime/der_length_utctime.o ltc/pk/asn1/der/utf8/der_decode_utf8_string.o \
ltc/pk/asn1/der/utf8/der_encode_utf8_string.o ltc/pk/asn1/der/utf8/der_length_utf8_string.o \
+ltc/pk/asn1/x509/x509_decode_subject_public_key_info.o ltc/pk/asn1/x509/x509_encode_subject_public_key_info.o \
ltc/pk/dh/dh.o ltc/pk/dh/dh_check_pubkey.o ltc/pk/dh/dh_export.o ltc/pk/dh/dh_export_key.o \
ltc/pk/dh/dh_free.o ltc/pk/dh/dh_generate_key.o ltc/pk/dh/dh_import.o ltc/pk/dh/dh_set.o \
ltc/pk/dh/dh_set_pg_dhparam.o ltc/pk/dh/dh_shared_secret.o ltc/pk/dsa/dsa_decrypt_key.o \
@@ -94,24 +99,23 @@ ltc/pk/dsa/dsa_encrypt_key.o ltc/pk/dsa/dsa_export.o ltc/pk/dsa/dsa_free.o ltc/p
ltc/pk/dsa/dsa_generate_pqg.o ltc/pk/dsa/dsa_import.o ltc/pk/dsa/dsa_make_key.o ltc/pk/dsa/dsa_set.o \
ltc/pk/dsa/dsa_set_pqg_dsaparam.o ltc/pk/dsa/dsa_shared_secret.o ltc/pk/dsa/dsa_sign_hash.o \
ltc/pk/dsa/dsa_verify_hash.o ltc/pk/dsa/dsa_verify_key.o ltc/pk/ecc/ecc.o ltc/pk/ecc/ecc_ansi_x963_export.o \
-ltc/pk/ecc/ecc_ansi_x963_import.o ltc/pk/ecc/ecc_decrypt_key.o ltc/pk/ecc/ecc_dp_clear.o \
-ltc/pk/ecc/ecc_dp_fill_from_sets.o ltc/pk/ecc/ecc_dp_from_oid.o ltc/pk/ecc/ecc_dp_from_params.o \
-ltc/pk/ecc/ecc_dp_init.o ltc/pk/ecc/ecc_dp_set.o ltc/pk/ecc/ecc_encrypt_key.o ltc/pk/ecc/ecc_export.o \
-ltc/pk/ecc/ecc_export_full.o ltc/pk/ecc/ecc_export_raw.o ltc/pk/ecc/ecc_free.o ltc/pk/ecc/ecc_get_size.o \
-ltc/pk/ecc/ecc_import.o ltc/pk/ecc/ecc_import_full.o ltc/pk/ecc/ecc_import_pkcs8.o \
-ltc/pk/ecc/ecc_import_raw.o ltc/pk/ecc/ecc_make_key.o ltc/pk/ecc/ecc_shared_secret.o \
-ltc/pk/ecc/ecc_sign_hash.o ltc/pk/ecc/ecc_sizes.o ltc/pk/ecc/ecc_verify_hash.o ltc/pk/ecc/ecc_verify_key.o \
-ltc/pk/ecc/ltc_ecc_export_point.o ltc/pk/ecc/ltc_ecc_import_point.o ltc/pk/ecc/ltc_ecc_is_point.o \
-ltc/pk/ecc/ltc_ecc_is_point_at_infinity.o ltc/pk/ecc/ltc_ecc_is_valid_idx.o ltc/pk/ecc/ltc_ecc_map.o \
+ltc/pk/ecc/ecc_ansi_x963_import.o ltc/pk/ecc/ecc_decrypt_key.o ltc/pk/ecc/ecc_encrypt_key.o \
+ltc/pk/ecc/ecc_export.o ltc/pk/ecc/ecc_export_openssl.o ltc/pk/ecc/ecc_free.o ltc/pk/ecc/ecc_get_key.o \
+ltc/pk/ecc/ecc_get_set.o ltc/pk/ecc/ecc_get_size.o ltc/pk/ecc/ecc_import.o ltc/pk/ecc/ecc_import_openssl.o \
+ltc/pk/ecc/ecc_import_pkcs8.o ltc/pk/ecc/ecc_import_x509.o ltc/pk/ecc/ecc_make_key.o \
+ltc/pk/ecc/ecc_set_dp.o ltc/pk/ecc/ecc_set_dp_internal.o ltc/pk/ecc/ecc_set_key.o \
+ltc/pk/ecc/ecc_shared_secret.o ltc/pk/ecc/ecc_sign_hash.o ltc/pk/ecc/ecc_sizes.o \
+ltc/pk/ecc/ecc_verify_hash.o ltc/pk/ecc/ltc_ecc_export_point.o ltc/pk/ecc/ltc_ecc_import_point.o \
+ltc/pk/ecc/ltc_ecc_is_point.o ltc/pk/ecc/ltc_ecc_is_point_at_infinity.o ltc/pk/ecc/ltc_ecc_map.o \
ltc/pk/ecc/ltc_ecc_mul2add.o ltc/pk/ecc/ltc_ecc_mulmod.o ltc/pk/ecc/ltc_ecc_mulmod_timing.o \
ltc/pk/ecc/ltc_ecc_points.o ltc/pk/ecc/ltc_ecc_projective_add_point.o ltc/pk/ecc/ltc_ecc_projective_dbl_point.o \
-ltc/pk/pkcs1/pkcs_1_i2osp.o ltc/pk/pkcs1/pkcs_1_mgf1.o ltc/pk/pkcs1/pkcs_1_oaep_decode.o \
-ltc/pk/pkcs1/pkcs_1_oaep_encode.o ltc/pk/pkcs1/pkcs_1_os2ip.o ltc/pk/pkcs1/pkcs_1_pss_decode.o \
-ltc/pk/pkcs1/pkcs_1_pss_encode.o ltc/pk/pkcs1/pkcs_1_v1_5_decode.o ltc/pk/pkcs1/pkcs_1_v1_5_encode.o \
-ltc/pk/rsa/rsa_decrypt_key.o ltc/pk/rsa/rsa_encrypt_key.o ltc/pk/rsa/rsa_export.o \
-ltc/pk/rsa/rsa_exptmod.o ltc/pk/rsa/rsa_free.o ltc/pk/rsa/rsa_get_size.o ltc/pk/rsa/rsa_import.o \
-ltc/pk/rsa/rsa_import_pkcs8.o ltc/pk/rsa/rsa_import_x509.o ltc/pk/rsa/rsa_make_key.o \
-ltc/pk/rsa/rsa_set.o ltc/pk/rsa/rsa_sign_hash.o ltc/pk/rsa/rsa_sign_saltlen_get.o \
+ltc/pk/ecc/ltc_ecc_verify_key.o ltc/pk/pkcs1/pkcs_1_i2osp.o ltc/pk/pkcs1/pkcs_1_mgf1.o \
+ltc/pk/pkcs1/pkcs_1_oaep_decode.o ltc/pk/pkcs1/pkcs_1_oaep_encode.o ltc/pk/pkcs1/pkcs_1_os2ip.o \
+ltc/pk/pkcs1/pkcs_1_pss_decode.o ltc/pk/pkcs1/pkcs_1_pss_encode.o ltc/pk/pkcs1/pkcs_1_v1_5_decode.o \
+ltc/pk/pkcs1/pkcs_1_v1_5_encode.o ltc/pk/rsa/rsa_decrypt_key.o ltc/pk/rsa/rsa_encrypt_key.o \
+ltc/pk/rsa/rsa_export.o ltc/pk/rsa/rsa_exptmod.o ltc/pk/rsa/rsa_free.o ltc/pk/rsa/rsa_get_size.o \
+ltc/pk/rsa/rsa_import.o ltc/pk/rsa/rsa_import_pkcs8.o ltc/pk/rsa/rsa_import_x509.o \
+ltc/pk/rsa/rsa_make_key.o ltc/pk/rsa/rsa_set.o ltc/pk/rsa/rsa_sign_hash.o ltc/pk/rsa/rsa_sign_saltlen_get.o \
ltc/pk/rsa/rsa_verify_hash.o ltc/prngs/chacha20.o ltc/prngs/fortuna.o ltc/prngs/rc4.o \
ltc/prngs/rng_get_bytes.o ltc/prngs/rng_make_prng.o ltc/prngs/sober128.o ltc/prngs/sprng.o \
ltc/prngs/yarrow.o ltc/stream/chacha/chacha_crypt.o ltc/stream/chacha/chacha_done.o \
diff --git a/src/Makefile.nmake b/src/Makefile.nmake
index b2f400cb..3bef06ea 100644
--- a/src/Makefile.nmake
+++ b/src/Makefile.nmake
@@ -73,6 +73,11 @@ ltc/pk/asn1/der/bit/der_decode_raw_bit_string.obj ltc/pk/asn1/der/bit/der_encode
ltc/pk/asn1/der/bit/der_encode_raw_bit_string.obj ltc/pk/asn1/der/bit/der_length_bit_string.obj \
ltc/pk/asn1/der/boolean/der_decode_boolean.obj ltc/pk/asn1/der/boolean/der_encode_boolean.obj \
ltc/pk/asn1/der/boolean/der_length_boolean.obj ltc/pk/asn1/der/choice/der_decode_choice.obj \
+ltc/pk/asn1/der/custom_type/der_decode_custom_type.obj ltc/pk/asn1/der/custom_type/der_encode_custom_type.obj \
+ltc/pk/asn1/der/custom_type/der_length_custom_type.obj ltc/pk/asn1/der/general/der_asn1_maps.obj \
+ltc/pk/asn1/der/general/der_decode_asn1_identifier.obj ltc/pk/asn1/der/general/der_decode_asn1_length.obj \
+ltc/pk/asn1/der/general/der_encode_asn1_identifier.obj ltc/pk/asn1/der/general/der_encode_asn1_length.obj \
+ltc/pk/asn1/der/general/der_length_asn1_identifier.obj ltc/pk/asn1/der/general/der_length_asn1_length.obj \
ltc/pk/asn1/der/generalizedtime/der_decode_generalizedtime.obj ltc/pk/asn1/der/generalizedtime/der_encode_generalizedtime.obj \
ltc/pk/asn1/der/generalizedtime/der_length_generalizedtime.obj ltc/pk/asn1/der/ia5/der_decode_ia5_string.obj \
ltc/pk/asn1/der/ia5/der_encode_ia5_string.obj ltc/pk/asn1/der/ia5/der_length_ia5_string.obj \
@@ -83,9 +88,8 @@ ltc/pk/asn1/der/octet/der_decode_octet_string.obj ltc/pk/asn1/der/octet/der_enco
ltc/pk/asn1/der/octet/der_length_octet_string.obj ltc/pk/asn1/der/printable_string/der_decode_printable_string.obj \
ltc/pk/asn1/der/printable_string/der_encode_printable_string.obj ltc/pk/asn1/der/printable_string/der_length_printable_string.obj \
ltc/pk/asn1/der/sequence/der_decode_sequence_ex.obj ltc/pk/asn1/der/sequence/der_decode_sequence_flexi.obj \
-ltc/pk/asn1/der/sequence/der_decode_sequence_multi.obj ltc/pk/asn1/der/sequence/der_decode_subject_public_key_info.obj \
-ltc/pk/asn1/der/sequence/der_encode_sequence_ex.obj ltc/pk/asn1/der/sequence/der_encode_sequence_multi.obj \
-ltc/pk/asn1/der/sequence/der_encode_subject_public_key_info.obj ltc/pk/asn1/der/sequence/der_length_sequence.obj \
+ltc/pk/asn1/der/sequence/der_decode_sequence_multi.obj ltc/pk/asn1/der/sequence/der_encode_sequence_ex.obj \
+ltc/pk/asn1/der/sequence/der_encode_sequence_multi.obj ltc/pk/asn1/der/sequence/der_length_sequence.obj \
ltc/pk/asn1/der/sequence/der_sequence_free.obj ltc/pk/asn1/der/sequence/der_sequence_shrink.obj \
ltc/pk/asn1/der/set/der_encode_set.obj ltc/pk/asn1/der/set/der_encode_setof.obj ltc/pk/asn1/der/short_integer/der_decode_short_integer.obj \
ltc/pk/asn1/der/short_integer/der_encode_short_integer.obj ltc/pk/asn1/der/short_integer/der_length_short_integer.obj \
@@ -93,6 +97,7 @@ ltc/pk/asn1/der/teletex_string/der_decode_teletex_string.obj ltc/pk/asn1/der/tel
ltc/pk/asn1/der/utctime/der_decode_utctime.obj ltc/pk/asn1/der/utctime/der_encode_utctime.obj \
ltc/pk/asn1/der/utctime/der_length_utctime.obj ltc/pk/asn1/der/utf8/der_decode_utf8_string.obj \
ltc/pk/asn1/der/utf8/der_encode_utf8_string.obj ltc/pk/asn1/der/utf8/der_length_utf8_string.obj \
+ltc/pk/asn1/x509/x509_decode_subject_public_key_info.obj ltc/pk/asn1/x509/x509_encode_subject_public_key_info.obj \
ltc/pk/dh/dh.obj ltc/pk/dh/dh_check_pubkey.obj ltc/pk/dh/dh_export.obj ltc/pk/dh/dh_export_key.obj \
ltc/pk/dh/dh_free.obj ltc/pk/dh/dh_generate_key.obj ltc/pk/dh/dh_import.obj ltc/pk/dh/dh_set.obj \
ltc/pk/dh/dh_set_pg_dhparam.obj ltc/pk/dh/dh_shared_secret.obj ltc/pk/dsa/dsa_decrypt_key.obj \
@@ -101,25 +106,24 @@ ltc/pk/dsa/dsa_generate_key.obj ltc/pk/dsa/dsa_generate_pqg.obj ltc/pk/dsa/dsa_i
ltc/pk/dsa/dsa_make_key.obj ltc/pk/dsa/dsa_set.obj ltc/pk/dsa/dsa_set_pqg_dsaparam.obj \
ltc/pk/dsa/dsa_shared_secret.obj ltc/pk/dsa/dsa_sign_hash.obj ltc/pk/dsa/dsa_verify_hash.obj \
ltc/pk/dsa/dsa_verify_key.obj ltc/pk/ecc/ecc.obj ltc/pk/ecc/ecc_ansi_x963_export.obj \
-ltc/pk/ecc/ecc_ansi_x963_import.obj ltc/pk/ecc/ecc_decrypt_key.obj ltc/pk/ecc/ecc_dp_clear.obj \
-ltc/pk/ecc/ecc_dp_fill_from_sets.obj ltc/pk/ecc/ecc_dp_from_oid.obj ltc/pk/ecc/ecc_dp_from_params.obj \
-ltc/pk/ecc/ecc_dp_init.obj ltc/pk/ecc/ecc_dp_set.obj ltc/pk/ecc/ecc_encrypt_key.obj \
-ltc/pk/ecc/ecc_export.obj ltc/pk/ecc/ecc_export_full.obj ltc/pk/ecc/ecc_export_raw.obj \
-ltc/pk/ecc/ecc_free.obj ltc/pk/ecc/ecc_get_size.obj ltc/pk/ecc/ecc_import.obj ltc/pk/ecc/ecc_import_full.obj \
-ltc/pk/ecc/ecc_import_pkcs8.obj ltc/pk/ecc/ecc_import_raw.obj ltc/pk/ecc/ecc_make_key.obj \
-ltc/pk/ecc/ecc_shared_secret.obj ltc/pk/ecc/ecc_sign_hash.obj ltc/pk/ecc/ecc_sizes.obj \
-ltc/pk/ecc/ecc_verify_hash.obj ltc/pk/ecc/ecc_verify_key.obj ltc/pk/ecc/ltc_ecc_export_point.obj \
-ltc/pk/ecc/ltc_ecc_import_point.obj ltc/pk/ecc/ltc_ecc_is_point.obj ltc/pk/ecc/ltc_ecc_is_point_at_infinity.obj \
-ltc/pk/ecc/ltc_ecc_is_valid_idx.obj ltc/pk/ecc/ltc_ecc_map.obj ltc/pk/ecc/ltc_ecc_mul2add.obj \
+ltc/pk/ecc/ecc_ansi_x963_import.obj ltc/pk/ecc/ecc_decrypt_key.obj ltc/pk/ecc/ecc_encrypt_key.obj \
+ltc/pk/ecc/ecc_export.obj ltc/pk/ecc/ecc_export_openssl.obj ltc/pk/ecc/ecc_free.obj \
+ltc/pk/ecc/ecc_get_key.obj ltc/pk/ecc/ecc_get_set.obj ltc/pk/ecc/ecc_get_size.obj \
+ltc/pk/ecc/ecc_import.obj ltc/pk/ecc/ecc_import_openssl.obj ltc/pk/ecc/ecc_import_pkcs8.obj \
+ltc/pk/ecc/ecc_import_x509.obj ltc/pk/ecc/ecc_make_key.obj ltc/pk/ecc/ecc_set_dp.obj \
+ltc/pk/ecc/ecc_set_dp_internal.obj ltc/pk/ecc/ecc_set_key.obj ltc/pk/ecc/ecc_shared_secret.obj \
+ltc/pk/ecc/ecc_sign_hash.obj ltc/pk/ecc/ecc_sizes.obj ltc/pk/ecc/ecc_verify_hash.obj \
+ltc/pk/ecc/ltc_ecc_export_point.obj ltc/pk/ecc/ltc_ecc_import_point.obj ltc/pk/ecc/ltc_ecc_is_point.obj \
+ltc/pk/ecc/ltc_ecc_is_point_at_infinity.obj ltc/pk/ecc/ltc_ecc_map.obj ltc/pk/ecc/ltc_ecc_mul2add.obj \
ltc/pk/ecc/ltc_ecc_mulmod.obj ltc/pk/ecc/ltc_ecc_mulmod_timing.obj ltc/pk/ecc/ltc_ecc_points.obj \
ltc/pk/ecc/ltc_ecc_projective_add_point.obj ltc/pk/ecc/ltc_ecc_projective_dbl_point.obj \
-ltc/pk/pkcs1/pkcs_1_i2osp.obj ltc/pk/pkcs1/pkcs_1_mgf1.obj ltc/pk/pkcs1/pkcs_1_oaep_decode.obj \
-ltc/pk/pkcs1/pkcs_1_oaep_encode.obj ltc/pk/pkcs1/pkcs_1_os2ip.obj ltc/pk/pkcs1/pkcs_1_pss_decode.obj \
-ltc/pk/pkcs1/pkcs_1_pss_encode.obj ltc/pk/pkcs1/pkcs_1_v1_5_decode.obj ltc/pk/pkcs1/pkcs_1_v1_5_encode.obj \
-ltc/pk/rsa/rsa_decrypt_key.obj ltc/pk/rsa/rsa_encrypt_key.obj ltc/pk/rsa/rsa_export.obj \
-ltc/pk/rsa/rsa_exptmod.obj ltc/pk/rsa/rsa_free.obj ltc/pk/rsa/rsa_get_size.obj ltc/pk/rsa/rsa_import.obj \
-ltc/pk/rsa/rsa_import_pkcs8.obj ltc/pk/rsa/rsa_import_x509.obj ltc/pk/rsa/rsa_make_key.obj \
-ltc/pk/rsa/rsa_set.obj ltc/pk/rsa/rsa_sign_hash.obj ltc/pk/rsa/rsa_sign_saltlen_get.obj \
+ltc/pk/ecc/ltc_ecc_verify_key.obj ltc/pk/pkcs1/pkcs_1_i2osp.obj ltc/pk/pkcs1/pkcs_1_mgf1.obj \
+ltc/pk/pkcs1/pkcs_1_oaep_decode.obj ltc/pk/pkcs1/pkcs_1_oaep_encode.obj ltc/pk/pkcs1/pkcs_1_os2ip.obj \
+ltc/pk/pkcs1/pkcs_1_pss_decode.obj ltc/pk/pkcs1/pkcs_1_pss_encode.obj ltc/pk/pkcs1/pkcs_1_v1_5_decode.obj \
+ltc/pk/pkcs1/pkcs_1_v1_5_encode.obj ltc/pk/rsa/rsa_decrypt_key.obj ltc/pk/rsa/rsa_encrypt_key.obj \
+ltc/pk/rsa/rsa_export.obj ltc/pk/rsa/rsa_exptmod.obj ltc/pk/rsa/rsa_free.obj ltc/pk/rsa/rsa_get_size.obj \
+ltc/pk/rsa/rsa_import.obj ltc/pk/rsa/rsa_import_pkcs8.obj ltc/pk/rsa/rsa_import_x509.obj \
+ltc/pk/rsa/rsa_make_key.obj ltc/pk/rsa/rsa_set.obj ltc/pk/rsa/rsa_sign_hash.obj ltc/pk/rsa/rsa_sign_saltlen_get.obj \
ltc/pk/rsa/rsa_verify_hash.obj ltc/prngs/chacha20.obj ltc/prngs/fortuna.obj ltc/prngs/rc4.obj \
ltc/prngs/rng_get_bytes.obj ltc/prngs/rng_make_prng.obj ltc/prngs/sober128.obj ltc/prngs/sprng.obj \
ltc/prngs/yarrow.obj ltc/stream/chacha/chacha_crypt.obj ltc/stream/chacha/chacha_done.obj \
diff --git a/src/ltc/hashes/sha3.c b/src/ltc/hashes/sha3.c
index c6faa0b9..1c01d6a1 100644
--- a/src/ltc/hashes/sha3.c
+++ b/src/ltc/hashes/sha3.c
@@ -72,6 +72,67 @@ const struct ltc_hash_descriptor sha3_512_desc =
&sha3_512_test,
NULL
};
+#endif
+
+#ifdef LTC_KECCAK
+const struct ltc_hash_descriptor keccak_224_desc =
+{
+ "keccak224", /* name of hash */
+ 29, /* internal ID */
+ 28, /* Size of digest in octets */
+ 144, /* Input block size in octets */
+ { 0 }, 0, /* no ASN.1 OID */
+ &sha3_224_init,
+ &sha3_process,
+ &keccak_done,
+ &keccak_224_test,
+ NULL
+};
+
+const struct ltc_hash_descriptor keccak_256_desc =
+{
+ "keccak256", /* name of hash */
+ 30, /* internal ID */
+ 32, /* Size of digest in octets */
+ 136, /* Input block size in octets */
+ { 0 }, 0, /* no ASN.1 OID */
+ &sha3_256_init,
+ &sha3_process,
+ &keccak_done,
+ &keccak_256_test,
+ NULL
+};
+
+const struct ltc_hash_descriptor keccak_384_desc =
+{
+ "keccak384", /* name of hash */
+ 31, /* internal ID */
+ 48, /* Size of digest in octets */
+ 104, /* Input block size in octets */
+ { 0 }, 0, /* no ASN.1 OID */
+ &sha3_384_init,
+ &sha3_process,
+ &keccak_done,
+ &keccak_384_test,
+ NULL
+};
+
+const struct ltc_hash_descriptor keccak_512_desc =
+{
+ "keccak512", /* name of hash */
+ 32, /* internal ID */
+ 64, /* Size of digest in octets */
+ 72, /* Input block size in octets */
+ { 0 }, 0, /* no ASN.1 OID */
+ &sha3_512_init,
+ &sha3_process,
+ &keccak_done,
+ &keccak_512_test,
+ NULL
+};
+#endif
+
+#if defined(LTC_SHA3) || defined(LTC_KECCAK)
#define SHA3_KECCAK_SPONGE_WORDS 25 /* 1600 bits > 200 bytes > 25 x ulong64 */
#define SHA3_KECCAK_ROUNDS 24
@@ -134,6 +195,26 @@ static void keccakf(ulong64 s[25])
}
}
+static LTC_INLINE int _done(hash_state *md, unsigned char *hash, ulong64 pad)
+{
+ unsigned i;
+
+ LTC_ARGCHK(md != NULL);
+ LTC_ARGCHK(hash != NULL);
+
+ md->sha3.s[md->sha3.word_index] ^= (md->sha3.saved ^ (pad << (md->sha3.byte_index * 8)));
+ md->sha3.s[SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words - 1] ^= CONST64(0x8000000000000000);
+ keccakf(md->sha3.s);
+
+ /* store sha3.s[] as little-endian bytes into sha3.sb */
+ for(i = 0; i < SHA3_KECCAK_SPONGE_WORDS; i++) {
+ STORE64L(md->sha3.s[i], md->sha3.sb + i * 8);
+ }
+
+ XMEMCPY(hash, md->sha3.sb, md->sha3.capacity_words * 4);
+ return CRYPT_OK;
+}
+
/* Public Inteface */
int sha3_224_init(hash_state *md)
@@ -168,6 +249,7 @@ int sha3_512_init(hash_state *md)
return CRYPT_OK;
}
+#ifdef LTC_SHA3
int sha3_shake_init(hash_state *md, int num)
{
LTC_ARGCHK(md != NULL);
@@ -176,6 +258,7 @@ int sha3_shake_init(hash_state *md, int num)
md->sha3.capacity_words = (unsigned short)(2 * num / (8 * sizeof(ulong64)));
return CRYPT_OK;
}
+#endif
int sha3_process(hash_state *md, const unsigned char *in, unsigned long inlen)
{
@@ -229,26 +312,21 @@ int sha3_process(hash_state *md, const unsigned char *in, unsigned long inlen)
return CRYPT_OK;
}
+#ifdef LTC_SHA3
int sha3_done(hash_state *md, unsigned char *hash)
{
- unsigned i;
-
- LTC_ARGCHK(md != NULL);
- LTC_ARGCHK(hash != NULL);
-
- md->sha3.s[md->sha3.word_index] ^= (md->sha3.saved ^ (CONST64(0x06) << (md->sha3.byte_index * 8)));
- md->sha3.s[SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words - 1] ^= CONST64(0x8000000000000000);
- keccakf(md->sha3.s);
-
- /* store sha3.s[] as little-endian bytes into sha3.sb */
- for(i = 0; i < SHA3_KECCAK_SPONGE_WORDS; i++) {
- STORE64L(md->sha3.s[i], md->sha3.sb + i * 8);
- }
+ return _done(md, hash, CONST64(0x06));
+}
+#endif
- XMEMCPY(hash, md->sha3.sb, md->sha3.capacity_words * 4);
- return CRYPT_OK;
+#ifdef LTC_KECCAK
+int keccak_done(hash_state *md, unsigned char *hash)
+{
+ return _done(md, hash, CONST64(0x01));
}
+#endif
+#ifdef LTC_SHA3
int sha3_shake_done(hash_state *md, unsigned char *out, unsigned long outlen)
{
/* IMPORTANT NOTE: sha3_shake_done can be called many times */
@@ -298,6 +376,7 @@ int sha3_shake_memory(int num, const unsigned char *in, unsigned long inlen, uns
if ((err = sha3_shake_done(&md, out, *outlen)) != CRYPT_OK) return err;
return CRYPT_OK;
}
+#endif
#endif
diff --git a/src/ltc/hashes/sha3_test.c b/src/ltc/hashes/sha3_test.c
index 5ae86506..2bf74823 100644
--- a/src/ltc/hashes/sha3_test.c
+++ b/src/ltc/hashes/sha3_test.c
@@ -396,6 +396,334 @@ int sha3_shake_test(void)
#endif
+#ifdef LTC_KECCAK
+
+int keccak_224_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ hash_state c;
+ unsigned char hash[MAXBLOCKSIZE];
+
+ keccak_224_init(&c);
+ keccak_process(&c, (unsigned char*) "\xcc", 1);
+ keccak_done(&c, hash);
+ if(compare_testvector(hash, 28,
+ "\xa9\xca\xb5\x9e\xb4\x0a\x10\xb2"
+ "\x46\x29\x0f\x2d\x60\x86\xe3\x2e"
+ "\x36\x89\xfa\xf1\xd2\x6b\x47\x0c"
+ "\x89\x9f\x28\x02", 28,
+ "KECCAK-224", 0) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ keccak_224_init(&c);
+ keccak_process(&c, (unsigned char*)"\x41\xfb", 2);
+ keccak_done(&c, hash);
+ if(compare_testvector(hash, 28,
+ "\x61\x5b\xa3\x67\xaf\xdc\x35\xaa"
+ "\xc3\x97\xbc\x7e\xb5\xd5\x8d\x10"
+ "\x6a\x73\x4b\x24\x98\x6d\x5d\x97"
+ "\x8f\xef\xd6\x2c", 28,
+ "KECCAK-224", 1) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ keccak_224_init(&c);
+ keccak_process(&c, (unsigned char*)
+ "\x52\xa6\x08\xab\x21\xcc\xdd\x8a"
+ "\x44\x57\xa5\x7e\xde\x78\x21\x76", 16);
+ keccak_done(&c, hash);
+ if(compare_testvector(hash, 28,
+ "\x56\x79\xcd\x50\x9c\x51\x20\xaf"
+ "\x54\x79\x5c\xf4\x77\x14\x96\x41"
+ "\xcf\x27\xb2\xeb\xb6\xa5\xf9\x03"
+ "\x40\x70\x4e\x57", 28,
+ "KECCAK-224", 2) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ keccak_224_init(&c);
+ keccak_process(&c, (unsigned char*)
+ "\x43\x3c\x53\x03\x13\x16\x24\xc0"
+ "\x02\x1d\x86\x8a\x30\x82\x54\x75"
+ "\xe8\xd0\xbd\x30\x52\xa0\x22\x18"
+ "\x03\x98\xf4\xca\x44\x23\xb9\x82"
+ "\x14\xb6\xbe\xaa\xc2\x1c\x88\x07"
+ "\xa2\xc3\x3f\x8c\x93\xbd\x42\xb0"
+ "\x92\xcc\x1b\x06\xce\xdf\x32\x24"
+ "\xd5\xed\x1e\xc2\x97\x84\x44\x4f"
+ "\x22\xe0\x8a\x55\xaa\x58\x54\x2b"
+ "\x52\x4b\x02\xcd\x3d\x5d\x5f\x69"
+ "\x07\xaf\xe7\x1c\x5d\x74\x62\x22"
+ "\x4a\x3f\x9d\x9e\x53\xe7\xe0\x84"
+ "\x6d\xcb\xb4\xce", 100);
+ keccak_done(&c, hash);
+ if(compare_testvector(hash, 28,
+ "\x62\xb1\x0f\x1b\x62\x36\xeb\xc2"
+ "\xda\x72\x95\x77\x42\xa8\xd4\xe4"
+ "\x8e\x21\x3b\x5f\x89\x34\x60\x4b"
+ "\xfd\x4d\x2c\x3a", 28,
+ "KECCAK-224", 3) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ return CRYPT_OK;
+#endif
+}
+
+int keccak_256_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ hash_state c;
+ unsigned char hash[MAXBLOCKSIZE];
+
+ keccak_256_init(&c);
+ keccak_process(&c, (unsigned char*) "\xcc", 1);
+ keccak_done(&c, hash);
+ if(compare_testvector(hash, 32,
+ "\xee\xad\x6d\xbf\xc7\x34\x0a\x56"
+ "\xca\xed\xc0\x44\x69\x6a\x16\x88"
+ "\x70\x54\x9a\x6a\x7f\x6f\x56\x96"
+ "\x1e\x84\xa5\x4b\xd9\x97\x0b\x8a", 32,
+ "KECCAK-256", 0) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ keccak_256_init(&c);
+ keccak_process(&c, (unsigned char*)"\x41\xfb", 2);
+ keccak_done(&c, hash);
+ if(compare_testvector(hash, 32,
+ "\xa8\xea\xce\xda\x4d\x47\xb3\x28"
+ "\x1a\x79\x5a\xd9\xe1\xea\x21\x22"
+ "\xb4\x07\xba\xf9\xaa\xbc\xb9\xe1"
+ "\x8b\x57\x17\xb7\x87\x35\x37\xd2", 32,
+ "KECCAK-256", 1) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ keccak_256_init(&c);
+ keccak_process(&c, (unsigned char*)
+ "\x52\xa6\x08\xab\x21\xcc\xdd\x8a"
+ "\x44\x57\xa5\x7e\xde\x78\x21\x76", 16);
+ keccak_done(&c, hash);
+ if(compare_testvector(hash, 32,
+ "\x0e\x32\xde\xfa\x20\x71\xf0\xb5"
+ "\xac\x0e\x6a\x10\x8b\x84\x2e\xd0"
+ "\xf1\xd3\x24\x97\x12\xf5\x8e\xe0"
+ "\xdd\xf9\x56\xfe\x33\x2a\x5f\x95", 32,
+ "KECCAK-256", 2) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ keccak_256_init(&c);
+ keccak_process(&c, (unsigned char*)
+ "\x43\x3c\x53\x03\x13\x16\x24\xc0"
+ "\x02\x1d\x86\x8a\x30\x82\x54\x75"
+ "\xe8\xd0\xbd\x30\x52\xa0\x22\x18"
+ "\x03\x98\xf4\xca\x44\x23\xb9\x82"
+ "\x14\xb6\xbe\xaa\xc2\x1c\x88\x07"
+ "\xa2\xc3\x3f\x8c\x93\xbd\x42\xb0"
+ "\x92\xcc\x1b\x06\xce\xdf\x32\x24"
+ "\xd5\xed\x1e\xc2\x97\x84\x44\x4f"
+ "\x22\xe0\x8a\x55\xaa\x58\x54\x2b"
+ "\x52\x4b\x02\xcd\x3d\x5d\x5f\x69"
+ "\x07\xaf\xe7\x1c\x5d\x74\x62\x22"
+ "\x4a\x3f\x9d\x9e\x53\xe7\xe0\x84"
+ "\x6d\xcb\xb4\xce", 100);
+ keccak_done(&c, hash);
+ if(compare_testvector(hash, 32,
+ "\xce\x87\xa5\x17\x3b\xff\xd9\x23"
+ "\x99\x22\x16\x58\xf8\x01\xd4\x5c"
+ "\x29\x4d\x90\x06\xee\x9f\x3f\x9d"
+ "\x41\x9c\x8d\x42\x77\x48\xdc\x41", 32,
+ "KECCAK-256", 3) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ return CRYPT_OK;
+#endif
+}
+
+int keccak_384_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ hash_state c;
+ unsigned char hash[MAXBLOCKSIZE];
+
+ keccak_384_init(&c);
+ keccak_process(&c, (unsigned char*) "\xcc", 1);
+ keccak_done(&c, hash);
+ if(compare_testvector(hash, 48,
+ "\x1b\x84\xe6\x2a\x46\xe5\xa2\x01"
+ "\x86\x17\x54\xaf\x5d\xc9\x5c\x4a"
+ "\x1a\x69\xca\xf4\xa7\x96\xae\x40"
+ "\x56\x80\x16\x1e\x29\x57\x26\x41"
+ "\xf5\xfa\x1e\x86\x41\xd7\x95\x83"
+ "\x36\xee\x7b\x11\xc5\x8f\x73\xe9", 48,
+ "KECCAK-384", 0) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ keccak_384_init(&c);
+ keccak_process(&c, (unsigned char*)"\x41\xfb", 2);
+ keccak_done(&c, hash);
+ if(compare_testvector(hash, 48,
+ "\x49\x5c\xce\x27\x14\xcd\x72\xc8"
+ "\xc5\x3c\x33\x63\xd2\x2c\x58\xb5"
+ "\x59\x60\xfe\x26\xbe\x0b\xf3\xbb"
+ "\xc7\xa3\x31\x6d\xd5\x63\xad\x1d"
+ "\xb8\x41\x0e\x75\xee\xfe\xa6\x55"
+ "\xe3\x9d\x46\x70\xec\x0b\x17\x92", 48,
+ "KECCAK-384", 1) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ keccak_384_init(&c);
+ keccak_process(&c, (unsigned char*)
+ "\x52\xa6\x08\xab\x21\xcc\xdd\x8a"
+ "\x44\x57\xa5\x7e\xde\x78\x21\x76", 16);
+ keccak_done(&c, hash);
+ if(compare_testvector(hash, 48,
+ "\x18\x42\x2a\xc1\xd3\xa1\xe5\x4b"
+ "\xad\x87\x68\x83\xd2\xd6\xdd\x65"
+ "\xf6\x5c\x1d\x5f\x33\xa7\x12\x5c"
+ "\xc4\xc1\x86\x40\x5a\x12\xed\x64"
+ "\xba\x96\x67\x2e\xed\xda\x8c\x5a"
+ "\x63\x31\xd2\x86\x83\xf4\x88\xeb", 48,
+ "KECCAK-384", 2) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ keccak_384_init(&c);
+ keccak_process(&c, (unsigned char*)
+ "\x43\x3c\x53\x03\x13\x16\x24\xc0"
+ "\x02\x1d\x86\x8a\x30\x82\x54\x75"
+ "\xe8\xd0\xbd\x30\x52\xa0\x22\x18"
+ "\x03\x98\xf4\xca\x44\x23\xb9\x82"
+ "\x14\xb6\xbe\xaa\xc2\x1c\x88\x07"
+ "\xa2\xc3\x3f\x8c\x93\xbd\x42\xb0"
+ "\x92\xcc\x1b\x06\xce\xdf\x32\x24"
+ "\xd5\xed\x1e\xc2\x97\x84\x44\x4f"
+ "\x22\xe0\x8a\x55\xaa\x58\x54\x2b"
+ "\x52\x4b\x02\xcd\x3d\x5d\x5f\x69"
+ "\x07\xaf\xe7\x1c\x5d\x74\x62\x22"
+ "\x4a\x3f\x9d\x9e\x53\xe7\xe0\x84"
+ "\x6d\xcb\xb4\xce", 100);
+ keccak_done(&c, hash);
+ if(compare_testvector(hash, 48,
+ "\x13\x51\x14\x50\x8d\xd6\x3e\x27"
+ "\x9e\x70\x9c\x26\xf7\x81\x7c\x04"
+ "\x82\x76\x6c\xde\x49\x13\x2e\x3e"
+ "\xdf\x2e\xed\xd8\x99\x6f\x4e\x35"
+ "\x96\xd1\x84\x10\x0b\x38\x48\x68"
+ "\x24\x9f\x1d\x8b\x8f\xda\xa2\xc9", 48,
+ "KECCAK-384", 3) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ return CRYPT_OK;
+#endif
+}
+
+int keccak_512_test(void)
+{
+#ifndef LTC_TEST
+ return CRYPT_NOP;
+#else
+ hash_state c;
+ unsigned char hash[MAXBLOCKSIZE];
+
+ keccak_512_init(&c);
+ keccak_process(&c, (unsigned char*) "\xcc", 1);
+ keccak_done(&c, hash);
+ if(compare_testvector(hash, 64,
+ "\x86\x30\xc1\x3c\xbd\x06\x6e\xa7"
+ "\x4b\xbe\x7f\xe4\x68\xfe\xc1\xde"
+ "\xe1\x0e\xdc\x12\x54\xfb\x4c\x1b"
+ "\x7c\x5f\xd6\x9b\x64\x6e\x44\x16"
+ "\x0b\x8c\xe0\x1d\x05\xa0\x90\x8c"
+ "\xa7\x90\xdf\xb0\x80\xf4\xb5\x13"
+ "\xbc\x3b\x62\x25\xec\xe7\xa8\x10"
+ "\x37\x14\x41\xa5\xac\x66\x6e\xb9", 64,
+ "KECCAK-512", 0) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ keccak_512_init(&c);
+ keccak_process(&c, (unsigned char*)"\x41\xfb", 2);
+ keccak_done(&c, hash);
+ if(compare_testvector(hash, 64,
+ "\x55\x1d\xa6\x23\x6f\x8b\x96\xfc"
+ "\xe9\xf9\x7f\x11\x90\xe9\x01\x32"
+ "\x4f\x0b\x45\xe0\x6d\xbb\xb5\xcd"
+ "\xb8\x35\x5d\x6e\xd1\xdc\x34\xb3"
+ "\xf0\xea\xe7\xdc\xb6\x86\x22\xff"
+ "\x23\x2f\xa3\xce\xce\x0d\x46\x16"
+ "\xcd\xeb\x39\x31\xf9\x38\x03\x66"
+ "\x2a\x28\xdf\x1c\xd5\x35\xb7\x31", 64,
+ "KECCAK-512", 1) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ keccak_512_init(&c);
+ keccak_process(&c, (unsigned char*)
+ "\x52\xa6\x08\xab\x21\xcc\xdd\x8a"
+ "\x44\x57\xa5\x7e\xde\x78\x21\x76", 16);
+ keccak_done(&c, hash);
+ if(compare_testvector(hash, 64,
+ "\x4b\x39\xd3\xda\x5b\xcd\xf4\xd9"
+ "\xb7\x69\x01\x59\x95\x64\x43\x11"
+ "\xc1\x4c\x43\x5b\xf7\x2b\x10\x09"
+ "\xd6\xdd\x71\xb0\x1a\x63\xb9\x7c"
+ "\xfb\x59\x64\x18\xe8\xe4\x23\x42"
+ "\xd1\x17\xe0\x74\x71\xa8\x91\x43"
+ "\x14\xba\x7b\x0e\x26\x4d\xad\xf0"
+ "\xce\xa3\x81\x86\x8c\xbd\x43\xd1", 64,
+ "KECCAK-512", 2) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ keccak_512_init(&c);
+ keccak_process(&c, (unsigned char*)
+ "\x43\x3c\x53\x03\x13\x16\x24\xc0"
+ "\x02\x1d\x86\x8a\x30\x82\x54\x75"
+ "\xe8\xd0\xbd\x30\x52\xa0\x22\x18"
+ "\x03\x98\xf4\xca\x44\x23\xb9\x82"
+ "\x14\xb6\xbe\xaa\xc2\x1c\x88\x07"
+ "\xa2\xc3\x3f\x8c\x93\xbd\x42\xb0"
+ "\x92\xcc\x1b\x06\xce\xdf\x32\x24"
+ "\xd5\xed\x1e\xc2\x97\x84\x44\x4f"
+ "\x22\xe0\x8a\x55\xaa\x58\x54\x2b"
+ "\x52\x4b\x02\xcd\x3d\x5d\x5f\x69"
+ "\x07\xaf\xe7\x1c\x5d\x74\x62\x22"
+ "\x4a\x3f\x9d\x9e\x53\xe7\xe0\x84"
+ "\x6d\xcb\xb4\xce", 100);
+ keccak_done(&c, hash);
+ if(compare_testvector(hash, 64,
+ "\x52\x7d\x28\xe3\x41\xe6\xb1\x4f"
+ "\x46\x84\xad\xb4\xb8\x24\xc4\x96"
+ "\xc6\x48\x2e\x51\x14\x95\x65\xd3"
+ "\xd1\x72\x26\x82\x88\x84\x30\x6b"
+ "\x51\xd6\x14\x8a\x72\x62\x2c\x2b"
+ "\x75\xf5\xd3\x51\x0b\x79\x9d\x8b"
+ "\xdc\x03\xea\xed\xe4\x53\x67\x6a"
+ "\x6e\xc8\xfe\x03\xa1\xad\x0e\xab", 64,
+ "KECCAK-512", 3) != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+
+ return CRYPT_OK;
+#endif
+}
+
+#endif
+
/* ref: $Format:%D$ */
/* git commit: $Format:%H$ */
/* commit time: $Format:%ai$ */
diff --git a/src/ltc/headers/tomcrypt.h b/src/ltc/headers/tomcrypt.h
index 9ed77509..1aca366e 100644
--- a/src/ltc/headers/tomcrypt.h
+++ b/src/ltc/headers/tomcrypt.h
@@ -27,13 +27,13 @@ extern "C" {
/* version */
#define CRYPT 0x0118
-#define SCRYPT "1.18.0"
+#define SCRYPT "1.18.1-develop"
/* max size of either a cipher/hash block or symmetric key [largest of the two] */
#define MAXBLOCKSIZE 144
/* descriptor table size */
-#define TAB_SIZE 32
+#define TAB_SIZE 34
/* error codes [will be expanded in future releases] */
enum {
@@ -67,7 +67,7 @@ enum {
CRYPT_OVERFLOW, /* An overflow of a value was detected/prevented */
- CRYPT_UNUSED1, /* UNUSED1 */
+ CRYPT_PK_ASN1_ERROR, /* An error occurred while en- or decoding ASN.1 data */
CRYPT_INPUT_TOO_LONG, /* The input was longer than expected. */
diff --git a/src/ltc/headers/tomcrypt_custom.h b/src/ltc/headers/tomcrypt_custom.h
index 5a218ff3..c4af2165 100644
--- a/src/ltc/headers/tomcrypt_custom.h
+++ b/src/ltc/headers/tomcrypt_custom.h
@@ -248,6 +248,7 @@
#define LTC_CHC_HASH
#define LTC_WHIRLPOOL
#define LTC_SHA3
+#define LTC_KECCAK
#define LTC_SHA512
#define LTC_SHA512_256
#define LTC_SHA512_224
@@ -468,32 +469,39 @@
#ifdef LTC_MECC
/* Supported ECC Key Sizes */
#ifndef LTC_NO_CURVES
+ #define LTC_ECC_BRAINPOOLP160R1
+ #define LTC_ECC_BRAINPOOLP160T1
+ #define LTC_ECC_BRAINPOOLP192R1
+ #define LTC_ECC_BRAINPOOLP192T1
+ #define LTC_ECC_BRAINPOOLP224R1
+ #define LTC_ECC_BRAINPOOLP224T1
+ #define LTC_ECC_BRAINPOOLP256R1
+ #define LTC_ECC_BRAINPOOLP256T1
+ #define LTC_ECC_BRAINPOOLP320R1
+ #define LTC_ECC_BRAINPOOLP320T1
+ #define LTC_ECC_BRAINPOOLP384R1
+ #define LTC_ECC_BRAINPOOLP384T1
+ #define LTC_ECC_BRAINPOOLP512R1
+ #define LTC_ECC_BRAINPOOLP512T1
+ #define LTC_ECC_PRIME192V2
+ #define LTC_ECC_PRIME192V3
+ #define LTC_ECC_PRIME239V1
+ #define LTC_ECC_PRIME239V2
+ #define LTC_ECC_PRIME239V3
#define LTC_ECC_SECP112R1
#define LTC_ECC_SECP112R2
#define LTC_ECC_SECP128R1
#define LTC_ECC_SECP128R2
+ #define LTC_ECC_SECP160K1
#define LTC_ECC_SECP160R1
#define LTC_ECC_SECP160R2
- #define LTC_ECC_SECP160K1
- #define LTC_ECC_BRAINPOOLP160R1
- #define LTC_ECC_SECP192R1
- #define LTC_ECC_PRIME192V2
- #define LTC_ECC_PRIME192V3
#define LTC_ECC_SECP192K1
- #define LTC_ECC_BRAINPOOLP192R1
- #define LTC_ECC_SECP224R1
+ #define LTC_ECC_SECP192R1
#define LTC_ECC_SECP224K1
- #define LTC_ECC_BRAINPOOLP224R1
- #define LTC_ECC_PRIME239V1
- #define LTC_ECC_PRIME239V2
- #define LTC_ECC_PRIME239V3
- #define LTC_ECC_SECP256R1
+ #define LTC_ECC_SECP224R1
#define LTC_ECC_SECP256K1
- #define LTC_ECC_BRAINPOOLP256R1
- #define LTC_ECC_BRAINPOOLP320R1
+ #define LTC_ECC_SECP256R1
#define LTC_ECC_SECP384R1
- #define LTC_ECC_BRAINPOOLP384R1
- #define LTC_ECC_BRAINPOOLP512R1
#define LTC_ECC_SECP521R1
/* OLD deprecated (but still working) defines */
#define LTC_ECC112
diff --git a/src/ltc/headers/tomcrypt_hash.h b/src/ltc/headers/tomcrypt_hash.h
index ef494f72..134085d7 100644
--- a/src/ltc/headers/tomcrypt_hash.h
+++ b/src/ltc/headers/tomcrypt_hash.h
@@ -8,7 +8,7 @@
*/
/* ---- HASH FUNCTIONS ---- */
-#ifdef LTC_SHA3
+#if defined(LTC_SHA3) || defined(LTC_KECCAK)
struct sha3_state {
ulong64 saved; /* the portion of the input message that we didn't consume yet */
ulong64 s[25];
@@ -155,7 +155,7 @@ typedef union Hash_state {
#ifdef LTC_WHIRLPOOL
struct whirlpool_state whirlpool;
#endif
-#ifdef LTC_SHA3
+#if defined(LTC_SHA3) || defined(LTC_KECCAK)
struct sha3_state sha3;
#endif
#ifdef LTC_SHA512
@@ -263,21 +263,25 @@ int whirlpool_test(void);
extern const struct ltc_hash_descriptor whirlpool_desc;
#endif
-#ifdef LTC_SHA3
+#if defined(LTC_SHA3) || defined(LTC_KECCAK)
+/* sha3_NNN_init are shared by SHA3 and KECCAK */
int sha3_512_init(hash_state * md);
+int sha3_384_init(hash_state * md);
+int sha3_256_init(hash_state * md);
+int sha3_224_init(hash_state * md);
+/* sha3_process is the same for all variants of SHA3 + KECCAK */
+int sha3_process(hash_state * md, const unsigned char *in, unsigned long inlen);
+#endif
+
+#ifdef LTC_SHA3
int sha3_512_test(void);
extern const struct ltc_hash_descriptor sha3_512_desc;
-int sha3_384_init(hash_state * md);
int sha3_384_test(void);
extern const struct ltc_hash_descriptor sha3_384_desc;
-int sha3_256_init(hash_state * md);
int sha3_256_test(void);
extern const struct ltc_hash_descriptor sha3_256_desc;
-int sha3_224_init(hash_state * md);
int sha3_224_test(void);
extern const struct ltc_hash_descriptor sha3_224_desc;
-/* process + done are the same for all variants */
-int sha3_process(hash_state * md, const unsigned char *in, unsigned long inlen);
int sha3_done(hash_state *md, unsigned char *hash);
/* SHAKE128 + SHAKE256 */
int sha3_shake_init(hash_state *md, int num);
@@ -287,6 +291,23 @@ int sha3_shake_test(void);
int sha3_shake_memory(int num, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen);
#endif
+#ifdef LTC_KECCAK
+#define keccak_512_init(a) sha3_512_init(a)
+#define keccak_384_init(a) sha3_384_init(a)
+#define keccak_256_init(a) sha3_256_init(a)
+#define keccak_224_init(a) sha3_224_init(a)
+#define keccak_process(a,b,c) sha3_process(a,b,c)
+extern const struct ltc_hash_descriptor keccak_512_desc;
+int keccak_512_test(void);
+extern const struct ltc_hash_descriptor keccak_384_desc;
+int keccak_384_test(void);
+extern const struct ltc_hash_descriptor keccak_256_desc;
+int keccak_256_test(void);
+extern const struct ltc_hash_descriptor keccak_224_desc;
+int keccak_224_test(void);
+int keccak_done(hash_state *md, unsigned char *hash);
+#endif
+
#ifdef LTC_SHA512
int sha512_init(hash_state * md);
int sha512_process(hash_state * md, const unsigned char *in, unsigned long inlen);
diff --git a/src/ltc/headers/tomcrypt_math.h b/src/ltc/headers/tomcrypt_math.h
index d73bb91d..f0e9699f 100644
--- a/src/ltc/headers/tomcrypt_math.h
+++ b/src/ltc/headers/tomcrypt_math.h
@@ -374,48 +374,48 @@ typedef struct {
@param k The integer to multiply the point by
@param G The point to multiply
@param R The destination for kG
- @param a ECC curve parameter a (if NULL we assume a == -3)
+ @param a ECC curve parameter a
@param modulus The modulus for the field
@param map Boolean indicated whether to map back to affine or not
(can be ignored if you work in affine only)
@return CRYPT_OK on success
*/
int (*ecc_ptmul)( void *k,
- ecc_point *G,
- ecc_point *R,
- void *a,
- void *modulus,
- int map);
+ const ecc_point *G,
+ ecc_point *R,
+ void *a,
+ void *modulus,
+ int map);
/** ECC GF(p) point addition
@param P The first point
@param Q The second point
@param R The destination of P + Q
- @param a ECC curve parameter a (if NULL we assume a == -3)
+ @param ma The curve parameter "a" in montgomery form
@param modulus The modulus
@param mp The "b" value from montgomery_setup()
@return CRYPT_OK on success
*/
- int (*ecc_ptadd)(ecc_point *P,
- ecc_point *Q,
- ecc_point *R,
- void *a,
- void *modulus,
- void *mp);
+ int (*ecc_ptadd)(const ecc_point *P,
+ const ecc_point *Q,
+ ecc_point *R,
+ void *ma,
+ void *modulus,
+ void *mp);
/** ECC GF(p) point double
@param P The first point
@param R The destination of 2P
- @param a ECC curve parameter a (if NULL we assume a == -3)
+ @param ma The curve parameter "a" in montgomery form
@param modulus The modulus
@param mp The "b" value from montgomery_setup()
@return CRYPT_OK on success
*/
- int (*ecc_ptdbl)(ecc_point *P,
- ecc_point *R,
- void *a,
- void *modulus,
- void *mp);
+ int (*ecc_ptdbl)(const ecc_point *P,
+ ecc_point *R,
+ void *ma,
+ void *modulus,
+ void *mp);
/** ECC mapping from projective to affine,
currently uses (x,y,z) => (x/z^2, y/z^3, 1)
@@ -435,14 +435,15 @@ typedef struct {
@param B Second point to multiply
@param kB What to multiple B by
@param C [out] Destination point (can overlap with A or B)
+ @param ma The curve parameter "a" in montgomery form
@param modulus Modulus for curve
@return CRYPT_OK on success
*/
- int (*ecc_mul2add)(ecc_point *A, void *kA,
- ecc_point *B, void *kB,
- ecc_point *C,
- void *a,
- void *modulus);
+ int (*ecc_mul2add)(const ecc_point *A, void *kA,
+ const ecc_point *B, void *kB,
+ ecc_point *C,
+ void *ma,
+ void *modulus);
/* ---- (optional) rsa optimized math (for internal CRT) ---- */
diff --git a/src/ltc/headers/tomcrypt_pk.h b/src/ltc/headers/tomcrypt_pk.h
index d12308c0..ac4353ca 100644
--- a/src/ltc/headers/tomcrypt_pk.h
+++ b/src/ltc/headers/tomcrypt_pk.h
@@ -32,17 +32,17 @@ enum public_key_algorithms {
PKA_RSA,
PKA_DSA,
PKA_EC,
- EC_PRIME_FIELD
+ PKA_EC_PRIMEF
};
-#endif /* LTC_SOURCE */
typedef struct Oid {
unsigned long OID[16];
- /** Length of DER encoding */
+ /** Number of OID digits in use */
unsigned long OIDlen;
} oid_st;
int pk_get_oid(int pk, oid_st *st);
+#endif /* LTC_SOURCE */
/* ---- RSA ---- */
#ifdef LTC_MRSA
@@ -254,37 +254,35 @@ int dh_check_pubkey(dh_key *key);
/* max private key size */
#define ECC_MAXSIZE 66
-/** Structure defines a NIST GF(p) curve */
+/** Structure defines a GF(p) curve */
typedef struct {
- /** The size of the curve in octets */
- int size;
-
/** name of curve */
- char *name;
+ const char *name;
/** The prime that defines the field the curve is in (encoded in hex) */
- char *prime;
+ const char *prime;
/** The fields A param (hex) */
- char *A;
+ const char *A;
/** The fields B param (hex) */
- char *B;
+ const char *B;
/** The order of the curve (hex) */
- char *order;
+ const char *order;
/** The x co-ordinate of the base point on the curve (hex) */
- char *Gx;
+ const char *Gx;
/** The y co-ordinate of the base point on the curve (hex) */
- char *Gy;
+ const char *Gy;
/** The co-factor */
unsigned long cofactor;
- /** The OID stucture */
- oid_st oid;
+ /** The OID */
+ unsigned long oid[16];
+ unsigned long oidlen;
} ltc_ecc_set_type;
/** A point on a ECC curve, stored in Jacbobian format such that (x,y,z) => (x/z^2, y/z^3, 1) when interpretted as affine */
@@ -299,18 +297,36 @@ typedef struct {
void *z;
} ecc_point;
+/** ECC key's domain parameters */
+typedef struct {
+ /** The size of the curve in octets */
+ int size;
+ /** The prime that defines the field the curve is in */
+ void *prime;
+ /** The fields A param */
+ void *A;
+ /** The fields B param */
+ void *B;
+ /** The order of the curve */
+ void *order;
+ /** The base point G on the curve */
+ ecc_point base;
+ /** The co-factor */
+ unsigned long cofactor;
+ /** The OID */
+ unsigned long oid[16];
+ unsigned long oidlen;
+} ltc_ecc_dp;
+
/** An ECC key */
typedef struct {
/** Type of key, PK_PRIVATE or PK_PUBLIC */
int type;
- /** Index into the ltc_ecc_sets[] for the parameters of this curve; if -1, then this key is using user supplied curve in dp */
- int idx;
+ /** Structure with domain parameters */
+ ltc_ecc_dp dp;
- /** pointer to domain parameters; either points to NIST curves (identified by idx >= 0) or user supplied curve */
- const ltc_ecc_set_type *dp;
-
- /** The public key */
+ /** Structure with the public key */
ecc_point pubkey;
/** The private key */
@@ -324,12 +340,11 @@ int ecc_test(void);
void ecc_sizes(int *low, int *high);
int ecc_get_size(ecc_key *key);
-int ecc_dp_init(ltc_ecc_set_type *dp);
-int ecc_dp_set(ltc_ecc_set_type *dp, char *ch_prime, char *ch_A, char *ch_B, char *ch_order, char *ch_Gx, char *ch_Gy, unsigned long cofactor, char *ch_name, char *oid);
-int ecc_dp_set_bn(ltc_ecc_set_type *dp, void *a, void *b, void *prime, void *order, void *gx, void *gy, unsigned long cofactor);
-int ecc_dp_set_by_oid(ltc_ecc_set_type *dp, unsigned long *oid, unsigned long oidsize);
-int ecc_dp_fill_from_sets(ltc_ecc_set_type *dp);
-int ecc_dp_clear(ltc_ecc_set_type *dp);
+int ecc_get_set_by_name(const char* name, const ltc_ecc_set_type** dp);
+int ecc_set_dp(const ltc_ecc_set_type *set, ecc_key *key);
+int ecc_generate_key(prng_state *prng, int wprng, ecc_key *key);
+int ecc_set_key(const unsigned char *in, unsigned long inlen, int type, ecc_key *key);
+int ecc_get_key(unsigned char *out, unsigned long *outlen, int type, ecc_key *key);
int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key);
int ecc_make_key_ex(prng_state *prng, int wprng, ecc_key *key, const ltc_ecc_set_type *dp);
@@ -338,15 +353,15 @@ void ecc_free(ecc_key *key);
int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key);
int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key);
int ecc_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, const ltc_ecc_set_type *dp);
-int ecc_import_pkcs8(const unsigned char *in, unsigned long inlen, const void *pwd, unsigned long pwdlen, ecc_key *key, ltc_ecc_set_type *dp);
-int ecc_export_full(unsigned char *out, unsigned long *outlen, int type, ecc_key *key);
-int ecc_import_full(const unsigned char *in, unsigned long inlen, ecc_key *key, ltc_ecc_set_type *dp);
-int ecc_export_raw(unsigned char *out, unsigned long *outlen, int type, ecc_key *key);
-int ecc_import_raw(const unsigned char *in, unsigned long inlen, ecc_key *key, ltc_ecc_set_type *dp);
int ecc_ansi_x963_export(ecc_key *key, unsigned char *out, unsigned long *outlen);
int ecc_ansi_x963_import(const unsigned char *in, unsigned long inlen, ecc_key *key);
-int ecc_ansi_x963_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, ltc_ecc_set_type *dp);
+int ecc_ansi_x963_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, const ltc_ecc_set_type *dp);
+
+int ecc_export_openssl(unsigned char *out, unsigned long *outlen, int type, ecc_key *key);
+int ecc_import_openssl(const unsigned char *in, unsigned long inlen, ecc_key *key);
+int ecc_import_pkcs8(const unsigned char *in, unsigned long inlen, const void *pwd, unsigned long pwdlen, ecc_key *key);
+int ecc_import_x509(const unsigned char *in, unsigned long inlen, ecc_key *key);
int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key,
unsigned char *out, unsigned long *outlen);
@@ -376,24 +391,31 @@ int ecc_verify_hash(const unsigned char *sig, unsigned long siglen,
const unsigned char *hash, unsigned long hashlen,
int *stat, ecc_key *key);
-int ecc_verify_key(ecc_key *key);
+
+#ifdef LTC_SOURCE
+/* INTERNAL ONLY - it should be later moved to src/headers/tomcrypt_internal.h */
+
+int ecc_set_dp_bn(void *a, void *b, void *prime, void *order, void *gx, void *gy, unsigned long cofactor, ecc_key *key);
+int ecc_set_dp_oid(unsigned long *oid, unsigned long oidsize, ecc_key *key);
+int ecc_set_dp_copy(ecc_key *srckey, ecc_key *key);
+int ecc_set_dp_size(int size, ecc_key *key);
/* low level functions */
ecc_point *ltc_ecc_new_point(void);
void ltc_ecc_del_point(ecc_point *p);
-int ltc_ecc_is_valid_idx(int n);
-int ltc_ecc_is_point(const ltc_ecc_set_type *dp, void *x, void *y);
-int ltc_ecc_is_point_at_infinity(ecc_point *p, void *modulus);
+int ltc_ecc_is_point(const ltc_ecc_dp *dp, void *x, void *y);
+int ltc_ecc_is_point_at_infinity(const ecc_point *p, void *modulus);
int ltc_ecc_import_point(const unsigned char *in, unsigned long inlen, void *prime, void *a, void *b, void *x, void *y);
int ltc_ecc_export_point(unsigned char *out, unsigned long *outlen, void *x, void *y, unsigned long size, int compressed);
+int ltc_ecc_verify_key(ecc_key *key);
/* point ops (mp == montgomery digit) */
#if !defined(LTC_MECC_ACCEL) || defined(LTM_DESC) || defined(GMP_DESC)
/* R = 2P */
-int ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *a, void *modulus, void *mp);
+int ltc_ecc_projective_dbl_point(const ecc_point *P, ecc_point *R, void *ma, void *modulus, void *mp);
/* R = P + Q */
-int ltc_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, void *a, void *modulus, void *mp);
+int ltc_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q, ecc_point *R, void *ma, void *modulus, void *mp);
#endif
#if defined(LTC_MECC_FP)
@@ -411,23 +433,23 @@ void ltc_ecc_fp_tablelock(int lock);
#endif
/* R = kG */
-int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *a, void *modulus, int map);
+int ltc_ecc_mulmod(void *k, const ecc_point *G, ecc_point *R, void *a, void *modulus, int map);
#ifdef LTC_ECC_SHAMIR
/* kA*A + kB*B = C */
-int ltc_ecc_mul2add(ecc_point *A, void *kA,
- ecc_point *B, void *kB,
- ecc_point *C,
- void *a,
- void *modulus);
+int ltc_ecc_mul2add(const ecc_point *A, void *kA,
+ const ecc_point *B, void *kB,
+ ecc_point *C,
+ void *ma,
+ void *modulus);
#ifdef LTC_MECC_FP
/* Shamir's trick with optimized point multiplication using fixed point cache */
-int ltc_ecc_fp_mul2add(ecc_point *A, void *kA,
- ecc_point *B, void *kB,
- ecc_point *C,
- void *a,
- void *modulus);
+int ltc_ecc_fp_mul2add(const ecc_point *A, void *kA,
+ const ecc_point *B, void *kB,
+ ecc_point *C,
+ void *ma,
+ void *modulus);
#endif
#endif
@@ -436,6 +458,8 @@ int ltc_ecc_fp_mul2add(ecc_point *A, void *kA,
/* map P to affine from projective */
int ltc_ecc_map(ecc_point *P, void *modulus, void *mp);
+#endif /* LTC_SOURCE */
+
#endif
#ifdef LTC_MDSA
@@ -549,12 +573,22 @@ typedef enum ltc_asn1_type_ {
LTC_ASN1_SETOF,
LTC_ASN1_RAW_BIT_STRING,
LTC_ASN1_TELETEX_STRING,
- LTC_ASN1_CONSTRUCTED,
- LTC_ASN1_CONTEXT_SPECIFIC,
- /* 20 */
LTC_ASN1_GENERALIZEDTIME,
+ LTC_ASN1_CUSTOM_TYPE,
} ltc_asn1_type;
+typedef enum {
+ LTC_ASN1_CL_UNIVERSAL = 0x0,
+ LTC_ASN1_CL_APPLICATION = 0x1,
+ LTC_ASN1_CL_CONTEXT_SPECIFIC = 0x2,
+ LTC_ASN1_CL_PRIVATE = 0x3,
+} ltc_asn1_class;
+
+typedef enum {
+ LTC_ASN1_PC_PRIMITIVE = 0x0,
+ LTC_ASN1_PC_CONSTRUCTED = 0x1,
+} ltc_asn1_pc;
+
/** A LTC ASN.1 list type */
typedef struct ltc_asn1_list_ {
/** The LTC ASN.1 enumerated type identifier */
@@ -563,12 +597,17 @@ typedef struct ltc_asn1_list_ {
void *data;
/** The size of the input or resulting output */
unsigned long size;
- /** The used flag, this is used by the CHOICE ASN.1 type to indicate which choice was made */
+ /** The used flag
+ * 1. This is used by the CHOICE ASN.1 type to indicate which choice was made
+ * 2. This is used by the ASN.1 decoder to indicate if an element is used
+ * 3. This is used by the flexi-decoder to indicate the first byte of the identifier */
int used;
/** Flag used to indicate optional items in ASN.1 sequences */
int optional;
- /** Flag used to indicate context specific tags on ASN.1 sequence items */
- unsigned char tag;
+ /** ASN.1 identifier */
+ ltc_asn1_class class;
+ ltc_asn1_pc pc;
+ ulong64 tag;
/** prev/next entry in the list */
struct ltc_asn1_list_ *prev, *next, *child, *parent;
} ltc_asn1_list;
@@ -581,46 +620,120 @@ typedef struct ltc_asn1_list_ {
LTC_MACRO_list[LTC_MACRO_temp].data = (void*)(Data); \
LTC_MACRO_list[LTC_MACRO_temp].size = (Size); \
LTC_MACRO_list[LTC_MACRO_temp].used = 0; \
- LTC_MACRO_list[LTC_MACRO_temp].tag = 0; \
LTC_MACRO_list[LTC_MACRO_temp].optional = 0; \
+ LTC_MACRO_list[LTC_MACRO_temp].class = 0; \
+ LTC_MACRO_list[LTC_MACRO_temp].pc = 0; \
+ LTC_MACRO_list[LTC_MACRO_temp].tag = 0; \
+ } while (0)
+
+#define __LTC_SET_ASN1_IDENTIFIER(list, index, Class, Pc, Tag) \
+ do { \
+ int LTC_MACRO_temp = (index); \
+ ltc_asn1_list *LTC_MACRO_list = (list); \
+ LTC_MACRO_list[LTC_MACRO_temp].type = LTC_ASN1_CUSTOM_TYPE; \
+ LTC_MACRO_list[LTC_MACRO_temp].class = (Class); \
+ LTC_MACRO_list[LTC_MACRO_temp].pc = (Pc); \
+ LTC_MACRO_list[LTC_MACRO_temp].tag = (Tag); \
+ } while (0)
+
+#define LTC_SET_ASN1_CUSTOM_CONSTRUCTED(list, index, Class, Tag, Data) \
+ do { \
+ int LTC_MACRO_temp##__LINE__ = (index); \
+ LTC_SET_ASN1(list, LTC_MACRO_temp##__LINE__, LTC_ASN1_CUSTOM_TYPE, Data, 1); \
+ __LTC_SET_ASN1_IDENTIFIER(list, LTC_MACRO_temp##__LINE__, Class, LTC_ASN1_PC_CONSTRUCTED, Tag); \
+ } while (0)
+
+#define LTC_SET_ASN1_CUSTOM_PRIMITIVE(list, index, Class, Tag, Type, Data, Size) \
+ do { \
+ int LTC_MACRO_temp##__LINE__ = (index); \
+ LTC_SET_ASN1(list, LTC_MACRO_temp##__LINE__, LTC_ASN1_CUSTOM_TYPE, Data, Size); \
+ __LTC_SET_ASN1_IDENTIFIER(list, LTC_MACRO_temp##__LINE__, Class, LTC_ASN1_PC_PRIMITIVE, Tag); \
+ list[LTC_MACRO_temp##__LINE__].used = (int)(Type); \
} while (0)
+extern const char* der_asn1_class_to_string_map[];
+extern const unsigned long der_asn1_class_to_string_map_sz;
+
+extern const char* der_asn1_pc_to_string_map[];
+extern const unsigned long der_asn1_pc_to_string_map_sz;
+
+extern const char* der_asn1_tag_to_string_map[];
+extern const unsigned long der_asn1_tag_to_string_map_sz;
+
/* SEQUENCE */
int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
unsigned char *out, unsigned long *outlen, int type_of);
#define der_encode_sequence(list, inlen, out, outlen) der_encode_sequence_ex(list, inlen, out, outlen, LTC_ASN1_SEQUENCE)
+/** The supported bitmap for all the
+ * decoders with a `flags` argument.
+ */
+enum ltc_der_seq {
+ LTC_DER_SEQ_ZERO = 0x0u,
+
+ /** Bit0 - [0]=Unordered (SET or SETOF)
+ * [1]=Ordered (SEQUENCE) */
+ LTC_DER_SEQ_UNORDERED = LTC_DER_SEQ_ZERO,
+ LTC_DER_SEQ_ORDERED = 0x1u,
+
+ /** Bit1 - [0]=Relaxed
+ * [1]=Strict */
+ LTC_DER_SEQ_RELAXED = LTC_DER_SEQ_ZERO,
+ LTC_DER_SEQ_STRICT = 0x2u,
+
+ /** Alternative naming */
+ LTC_DER_SEQ_SET = LTC_DER_SEQ_UNORDERED,
+ LTC_DER_SEQ_SEQUENCE = LTC_DER_SEQ_ORDERED,
+};
+
int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen,
- ltc_asn1_list *list, unsigned long outlen, int ordered);
+ ltc_asn1_list *list, unsigned long outlen, unsigned int flags);
-#define der_decode_sequence(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, 1)
+#define der_decode_sequence(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_RELAXED)
+#define der_decode_sequence_strict(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_STRICT)
int der_length_sequence(ltc_asn1_list *list, unsigned long inlen,
unsigned long *outlen);
+/* Custom-types */
+int der_encode_custom_type(const ltc_asn1_list *root,
+ unsigned char *out, unsigned long *outlen);
+
+int der_decode_custom_type(const unsigned char *in, unsigned long inlen,
+ ltc_asn1_list *root);
+
+int der_length_custom_type(const ltc_asn1_list *root,
+ unsigned long *outlen,
+ unsigned long *payloadlen);
+
#ifdef LTC_SOURCE
/* internal helper functions */
+int der_decode_custom_type_ex(const unsigned char *in, unsigned long inlen,
+ ltc_asn1_list *root,
+ ltc_asn1_list *list, unsigned long outlen, unsigned int flags);
+
+int der_encode_asn1_identifier(const ltc_asn1_list *id, unsigned char *out, unsigned long *outlen);
+int der_decode_asn1_identifier(const unsigned char *in, unsigned long *inlen, ltc_asn1_list *id);
+int der_length_asn1_identifier(const ltc_asn1_list *id, unsigned long *idlen);
+
+int der_encode_asn1_length(unsigned long len, unsigned char* out, unsigned long* outlen);
+int der_decode_asn1_length(const unsigned char* len, unsigned long* lenlen, unsigned long* outlen);
+int der_length_asn1_length(unsigned long len, unsigned long *outlen);
+
int der_length_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
unsigned long *outlen, unsigned long *payloadlen);
-/* SUBJECT PUBLIC KEY INFO */
-int der_encode_subject_public_key_info(unsigned char *out, unsigned long *outlen,
- unsigned int algorithm, void* public_key, unsigned long public_key_len,
- unsigned long parameters_type, void* parameters, unsigned long parameters_len);
-int der_decode_subject_public_key_info(const unsigned char *in, unsigned long inlen,
- unsigned int algorithm, void* public_key, unsigned long* public_key_len,
- unsigned long parameters_type, ltc_asn1_list* parameters, unsigned long parameters_len);
+extern const ltc_asn1_type der_asn1_tag_to_type_map[];
+extern const unsigned long der_asn1_tag_to_type_map_sz;
-int der_decode_subject_public_key_info_ex(const unsigned char *in, unsigned long inlen,
- unsigned int algorithm, void* public_key, unsigned long* public_key_len,
- unsigned long parameters_type, void* parameters, unsigned long parameters_len,
- unsigned long *parameters_outsize);
+extern const int der_asn1_type_to_identifier_map[];
+extern const unsigned long der_asn1_type_to_identifier_map_sz;
#endif /* LTC_SOURCE */
/* SET */
-#define der_decode_set(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, 0)
+#define der_decode_set(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, LTC_DER_SEQ_SET)
#define der_length_set der_length_sequence
int der_encode_set(ltc_asn1_list *list, unsigned long inlen,
unsigned char *out, unsigned long *outlen);
@@ -631,6 +744,10 @@ int der_encode_setof(ltc_asn1_list *list, unsigned long inlen,
/* VA list handy helpers with triplets of <type, size, data> */
int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...);
int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...);
+#ifdef LTC_SOURCE
+/* internal helper functions */
+int der_decode_sequence_multi_ex(const unsigned char *in, unsigned long inlen, unsigned int flags, ...);
+#endif /* LTC_SOURCE */
/* FLEXI DECODER handle unknown list decoder */
int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out);
@@ -786,6 +903,17 @@ int der_decode_generalizedtime(const unsigned char *in, unsigned long *inlen,
int der_length_generalizedtime(ltc_generalizedtime *gtime, unsigned long *outlen);
+#ifdef LTC_SOURCE
+/* internal helper functions */
+/* SUBJECT PUBLIC KEY INFO */
+int x509_encode_subject_public_key_info(unsigned char *out, unsigned long *outlen,
+ unsigned int algorithm, void* public_key, unsigned long public_key_len,
+ unsigned long parameters_type, void* parameters, unsigned long parameters_len);
+
+int x509_decode_subject_public_key_info(const unsigned char *in, unsigned long inlen,
+ unsigned int algorithm, void* public_key, unsigned long* public_key_len,
+ unsigned long parameters_type, void* parameters, unsigned long *parameters_len);
+#endif /* LTC_SOURCE */
#endif
diff --git a/src/ltc/mac/blake2/blake2bmac_file.c b/src/ltc/mac/blake2/blake2bmac_file.c
index 64c9e4d1..c1e9c6b5 100644
--- a/src/ltc/mac/blake2/blake2bmac_file.c
+++ b/src/ltc/mac/blake2/blake2bmac_file.c
@@ -23,6 +23,11 @@
int blake2bmac_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen)
{
#ifdef LTC_NO_FILE
+ LTC_UNUSED_PARAM(fname);
+ LTC_UNUSED_PARAM(key);
+ LTC_UNUSED_PARAM(keylen);
+ LTC_UNUSED_PARAM(mac);
+ LTC_UNUSED_PARAM(maclen);
return CRYPT_NOP;
#else
blake2bmac_state st;
diff --git a/src/ltc/mac/blake2/blake2smac_file.c b/src/ltc/mac/blake2/blake2smac_file.c
index c5248a29..1ac66797 100644
--- a/src/ltc/mac/blake2/blake2smac_file.c
+++ b/src/ltc/mac/blake2/blake2smac_file.c
@@ -23,6 +23,11 @@
int blake2smac_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen)
{
#ifdef LTC_NO_FILE
+ LTC_UNUSED_PARAM(fname);
+ LTC_UNUSED_PARAM(key);
+ LTC_UNUSED_PARAM(keylen);
+ LTC_UNUSED_PARAM(mac);
+ LTC_UNUSED_PARAM(maclen);
return CRYPT_NOP;
#else
blake2smac_state st;
diff --git a/src/ltc/mac/f9/f9_file.c b/src/ltc/mac/f9/f9_file.c
index a6e6532c..04d509bf 100644
--- a/src/ltc/mac/f9/f9_file.c
+++ b/src/ltc/mac/f9/f9_file.c
@@ -31,6 +31,12 @@ int f9_file(int cipher,
unsigned char *out, unsigned long *outlen)
{
#ifdef LTC_NO_FILE
+ LTC_UNUSED_PARAM(cipher);
+ LTC_UNUSED_PARAM(key);
+ LTC_UNUSED_PARAM(keylen);
+ LTC_UNUSED_PARAM(fname);
+ LTC_UNUSED_PARAM(out);
+ LTC_UNUSED_PARAM(outlen);
return CRYPT_NOP;
#else
size_t x;
diff --git a/src/ltc/mac/hmac/hmac_file.c b/src/ltc/mac/hmac/hmac_file.c
index 2d10e21c..0e1a1631 100644
--- a/src/ltc/mac/hmac/hmac_file.c
+++ b/src/ltc/mac/hmac/hmac_file.c
@@ -30,6 +30,12 @@ int hmac_file(int hash, const char *fname,
unsigned char *out, unsigned long *outlen)
{
#ifdef LTC_NO_FILE
+ LTC_UNUSED_PARAM(hash);
+ LTC_UNUSED_PARAM(fname);
+ LTC_UNUSED_PARAM(key);
+ LTC_UNUSED_PARAM(keylen);
+ LTC_UNUSED_PARAM(out);
+ LTC_UNUSED_PARAM(outlen);
return CRYPT_NOP;
#else
hmac_state hmac;
diff --git a/src/ltc/mac/omac/omac_file.c b/src/ltc/mac/omac/omac_file.c
index a9104e8e..3f6a85d0 100644
--- a/src/ltc/mac/omac/omac_file.c
+++ b/src/ltc/mac/omac/omac_file.c
@@ -31,6 +31,12 @@ int omac_file(int cipher,
unsigned char *out, unsigned long *outlen)
{
#ifdef LTC_NO_FILE
+ LTC_UNUSED_PARAM(cipher);
+ LTC_UNUSED_PARAM(key);
+ LTC_UNUSED_PARAM(keylen);
+ LTC_UNUSED_PARAM(filename);
+ LTC_UNUSED_PARAM(out);
+ LTC_UNUSED_PARAM(outlen);
return CRYPT_NOP;
#else
size_t x;
diff --git a/src/ltc/mac/pmac/pmac_file.c b/src/ltc/mac/pmac/pmac_file.c
index abe04f1e..fe202a2f 100644
--- a/src/ltc/mac/pmac/pmac_file.c
+++ b/src/ltc/mac/pmac/pmac_file.c
@@ -31,6 +31,12 @@ int pmac_file(int cipher,
unsigned char *out, unsigned long *outlen)
{
#ifdef LTC_NO_FILE
+ LTC_UNUSED_PARAM(cipher);
+ LTC_UNUSED_PARAM(key);
+ LTC_UNUSED_PARAM(keylen);
+ LTC_UNUSED_PARAM(filename);
+ LTC_UNUSED_PARAM(out);
+ LTC_UNUSED_PARAM(outlen);
return CRYPT_NOP;
#else
size_t x;
diff --git a/src/ltc/mac/poly1305/poly1305_file.c b/src/ltc/mac/poly1305/poly1305_file.c
index 77263056..e57437b3 100644
--- a/src/ltc/mac/poly1305/poly1305_file.c
+++ b/src/ltc/mac/poly1305/poly1305_file.c
@@ -28,6 +28,11 @@
int poly1305_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen)
{
#ifdef LTC_NO_FILE
+ LTC_UNUSED_PARAM(fname);
+ LTC_UNUSED_PARAM(key);
+ LTC_UNUSED_PARAM(keylen);
+ LTC_UNUSED_PARAM(mac);
+ LTC_UNUSED_PARAM(maclen);
return CRYPT_NOP;
#else
poly1305_state st;
diff --git a/src/ltc/mac/xcbc/xcbc_file.c b/src/ltc/mac/xcbc/xcbc_file.c
index f121cd0e..27eb0dec 100644
--- a/src/ltc/mac/xcbc/xcbc_file.c
+++ b/src/ltc/mac/xcbc/xcbc_file.c
@@ -31,6 +31,12 @@ int xcbc_file(int cipher,
unsigned char *out, unsigned long *outlen)
{
#ifdef LTC_NO_FILE
+ LTC_UNUSED_PARAM(cipher);
+ LTC_UNUSED_PARAM(key);
+ LTC_UNUSED_PARAM(keylen);
+ LTC_UNUSED_PARAM(filename);
+ LTC_UNUSED_PARAM(out);
+ LTC_UNUSED_PARAM(outlen);
return CRYPT_NOP;
#else
size_t x;
diff --git a/src/ltc/math/rand_bn.c b/src/ltc/math/rand_bn.c
index a42ba642..aa6539cc 100644
--- a/src/ltc/math/rand_bn.c
+++ b/src/ltc/math/rand_bn.c
@@ -8,7 +8,7 @@
*/
#include "tomcrypt.h"
-#ifdef LTC_MDSA
+#if defined(LTC_MDSA) || defined(LTC_MECC)
/**
Generate a random number N with given bitlength (note: MSB can be 0)
*/
diff --git a/src/ltc/math/tfm_desc.c b/src/ltc/math/tfm_desc.c
index 2a5a57d9..9247db65 100644
--- a/src/ltc/math/tfm_desc.c
+++ b/src/ltc/math/tfm_desc.c
@@ -265,6 +265,16 @@ static int sqr(void *a, void *b)
return CRYPT_OK;
}
+/* sqrtmod_prime */
+static int sqrtmod_prime(void *a, void *b, void *c)
+{
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(c != NULL);
+ fprintf(stderr, "TFM does not support sqrtmod_prime\n"); /* XXX-FIXME */
+ return CRYPT_ERROR;
+}
+
/* div */
static int divide(void *a, void *b, void *c, void *d)
{
@@ -424,7 +434,7 @@ static int isprime(void *a, int b, int *c)
#if defined(LTC_MECC) && defined(LTC_MECC_ACCEL)
-static int tfm_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *modulus, void *Mp)
+static int tfm_ecc_projective_dbl_point(const ecc_point *P, ecc_point *R, void *ma, void *modulus, void *Mp)
{
fp_int t1, t2;
fp_digit mp;
@@ -445,6 +455,14 @@ static int tfm_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *modulu
fp_copy(P->z, R->z);
}
+ if (ltc_ecc_is_point_at_infinity(P, modulus)) {
+ /* if P is point at infinity >> Result = point at infinity */
+ ltc_mp.set_int(R->x, 1);
+ ltc_mp.set_int(R->y, 1);
+ ltc_mp.set_int(R->z, 0);
+ return CRYPT_OK;
+ }
+
/* t1 = Z * Z */
fp_sqr(R->z, &t1);
fp_montgomery_reduce(&t1, modulus, mp);
@@ -457,28 +475,56 @@ static int tfm_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *modulu
fp_sub(R->z, modulus, R->z);
}
- /* &t2 = X - T1 */
- fp_sub(R->x, &t1, &t2);
- if (fp_cmp_d(&t2, 0) == FP_LT) {
- fp_add(&t2, modulus, &t2);
- }
- /* T1 = X + T1 */
- fp_add(&t1, R->x, &t1);
- if (fp_cmp(&t1, modulus) != FP_LT) {
- fp_sub(&t1, modulus, &t1);
- }
- /* T2 = T1 * T2 */
- fp_mul(&t1, &t2, &t2);
- fp_montgomery_reduce(&t2, modulus, mp);
- /* T1 = 2T2 */
- fp_add(&t2, &t2, &t1);
- if (fp_cmp(&t1, modulus) != FP_LT) {
- fp_sub(&t1, modulus, &t1);
- }
- /* T1 = T1 + T2 */
- fp_add(&t1, &t2, &t1);
- if (fp_cmp(&t1, modulus) != FP_LT) {
- fp_sub(&t1, modulus, &t1);
+ if (ma == NULL) { /* special case for curves with a == -3 (10% faster than general case) */
+ /* T2 = X - T1 */
+ fp_sub(R->x, &t1, &t2);
+ if (fp_cmp_d(&t2, 0) == LTC_MP_LT) {
+ fp_add(&t2, modulus, &t2);
+ }
+ /* T1 = X + T1 */
+ fp_add(&t1, R->x, &t1);
+ if (fp_cmp(&t1, modulus) != FP_LT) {
+ fp_sub(&t1, modulus, &t1);
+ }
+ /* T2 = T1 * T2 */
+ fp_mul(&t1, &t2, &t2);
+ fp_montgomery_reduce(&t2, modulus, mp);
+ /* T1 = 2T2 */
+ fp_add(&t2, &t2, &t1);
+ if (fp_cmp(&t1, modulus) != FP_LT) {
+ fp_sub(&t1, modulus, &t1);
+ }
+ /* T1 = T1 + T2 */
+ fp_add(&t1, &t2, &t1);
+ if (fp_cmp(&t1, modulus) != FP_LT) {
+ fp_sub(&t1, modulus, &t1);
+ }
+ }
+ else {
+ /* T2 = T1 * T1 */
+ fp_sqr(&t1, &t2);
+ fp_montgomery_reduce(&t2, modulus, mp);
+ /* T1 = T2 * a */
+ fp_mul(&t2, ma, &t1);
+ fp_montgomery_reduce(&t1, modulus, mp);
+ /* T2 = X * X */
+ fp_sqr(R->x, &t2);
+ fp_montgomery_reduce(&t2, modulus, mp);
+ /* T1 = T1 + T2 */
+ fp_add(&t1, &t2, &t1);
+ if (fp_cmp(&t1, modulus) != FP_LT) {
+ fp_sub(&t1, modulus, &t1);
+ }
+ /* T1 = T1 + T2 */
+ fp_add(&t1, &t2, &t1);
+ if (fp_cmp(&t1, modulus) != FP_LT) {
+ fp_sub(&t1, modulus, &t1);
+ }
+ /* T1 = T1 + T2 */
+ fp_add(&t1, &t2, &t1);
+ if (fp_cmp(&t1, modulus) != FP_LT) {
+ fp_sub(&t1, modulus, &t1);
+ }
}
/* Y = 2Y */
@@ -541,7 +587,7 @@ static int tfm_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *modulu
@param Mp The "b" value from montgomery_setup()
@return CRYPT_OK on success
*/
-static int tfm_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, void *modulus, void *Mp)
+static int tfm_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q, ecc_point *R, void *ma, void *modulus, void *Mp)
{
fp_int t1, t2, x, y, z;
fp_digit mp;
@@ -560,12 +606,28 @@ static int tfm_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R
fp_init(&y);
fp_init(&z);
+ if (ltc_ecc_is_point_at_infinity(P, modulus)) {
+ /* P is point at infinity >> Result = Q */
+ ltc_mp.copy(Q->x, R->x);
+ ltc_mp.copy(Q->y, R->y);
+ ltc_mp.copy(Q->z, R->z);
+ return CRYPT_OK;
+ }
+
+ if (ltc_ecc_is_point_at_infinity(Q, modulus)) {
+ /* Q is point at infinity >> Result = P */
+ ltc_mp.copy(P->x, R->x);
+ ltc_mp.copy(P->y, R->y);
+ ltc_mp.copy(P->z, R->z);
+ return CRYPT_OK;
+ }
+
/* should we dbl instead? */
fp_sub(modulus, Q->y, &t1);
if ( (fp_cmp(P->x, Q->x) == FP_EQ) &&
(Q->z != NULL && fp_cmp(P->z, Q->z) == FP_EQ) &&
(fp_cmp(P->y, Q->y) == FP_EQ || fp_cmp(P->y, &t1) == FP_EQ)) {
- return tfm_ecc_projective_dbl_point(P, R, modulus, Mp);
+ return tfm_ecc_projective_dbl_point(P, R, ma, modulus, Mp);
}
fp_copy(P->x, &x);
@@ -741,6 +803,7 @@ const ltc_math_descriptor tfm_desc = {
&mul,
&muli,
&sqr,
+ &sqrtmod_prime,
&divide,
&div_2,
&modi,
diff --git a/src/ltc/misc/crypt/crypt.c b/src/ltc/misc/crypt/crypt.c
index bd656325..bd57a0aa 100644
--- a/src/ltc/misc/crypt/crypt.c
+++ b/src/ltc/misc/crypt/crypt.c
@@ -152,6 +152,9 @@ const char *crypt_build_settings =
#if defined(LTC_SHA3)
" SHA3\n"
#endif
+#if defined(LTC_KECCAK)
+ " KECCAK\n"
+#endif
#if defined(LTC_SHA512)
" SHA-512\n"
#endif
diff --git a/src/ltc/misc/crypt/crypt_constants.c b/src/ltc/misc/crypt/crypt_constants.c
index a7418d5e..9e76322c 100644
--- a/src/ltc/misc/crypt/crypt_constants.c
+++ b/src/ltc/misc/crypt/crypt_constants.c
@@ -47,7 +47,7 @@ static const crypt_constant _crypt_constants[] = {
_C_STRINGIFY(CRYPT_FILE_NOTFOUND),
_C_STRINGIFY(CRYPT_PK_INVALID_TYPE),
_C_STRINGIFY(CRYPT_OVERFLOW),
- _C_STRINGIFY(CRYPT_UNUSED1),
+ _C_STRINGIFY(CRYPT_PK_ASN1_ERROR),
_C_STRINGIFY(CRYPT_INPUT_TOO_LONG),
_C_STRINGIFY(CRYPT_PK_INVALID_SIZE),
_C_STRINGIFY(CRYPT_INVALID_PRIME_SIZE),
@@ -129,9 +129,8 @@ static const crypt_constant _crypt_constants[] = {
_C_STRINGIFY(LTC_ASN1_SETOF),
_C_STRINGIFY(LTC_ASN1_RAW_BIT_STRING),
_C_STRINGIFY(LTC_ASN1_TELETEX_STRING),
- _C_STRINGIFY(LTC_ASN1_CONSTRUCTED),
- _C_STRINGIFY(LTC_ASN1_CONTEXT_SPECIFIC),
_C_STRINGIFY(LTC_ASN1_GENERALIZEDTIME),
+ _C_STRINGIFY(LTC_ASN1_CUSTOM_TYPE),
#endif
#ifdef LTC_CTR_MODE
diff --git a/src/ltc/misc/crypt/crypt_register_all_hashes.c b/src/ltc/misc/crypt/crypt_register_all_hashes.c
index b5293894..585b9b61 100644
--- a/src/ltc/misc/crypt/crypt_register_all_hashes.c
+++ b/src/ltc/misc/crypt/crypt_register_all_hashes.c
@@ -60,6 +60,12 @@ int register_all_hashes(void)
REGISTER_HASH(&sha3_384_desc);
REGISTER_HASH(&sha3_512_desc);
#endif
+#ifdef LTC_KECCAK
+ REGISTER_HASH(&keccak_224_desc);
+ REGISTER_HASH(&keccak_256_desc);
+ REGISTER_HASH(&keccak_384_desc);
+ REGISTER_HASH(&keccak_512_desc);
+#endif
#ifdef LTC_RIPEMD128
REGISTER_HASH(&rmd128_desc);
#endif
diff --git a/src/ltc/misc/error_to_string.c b/src/ltc/misc/error_to_string.c
index 707f8359..3d168286 100644
--- a/src/ltc/misc/error_to_string.c
+++ b/src/ltc/misc/error_to_string.c
@@ -46,7 +46,7 @@ static const char * const err_2_str[] =
"An overflow of a value was detected/prevented.",
- "UNUSED1.",
+ "An ASN.1 decoding error occurred.",
"The input was longer than expected.",
diff --git a/src/ltc/misc/pk_get_oid.c b/src/ltc/misc/pk_get_oid.c
index 8ea3e075..003925aa 100644
--- a/src/ltc/misc/pk_get_oid.c
+++ b/src/ltc/misc/pk_get_oid.c
@@ -45,7 +45,7 @@ int pk_get_oid(int pk, oid_st *st)
case PKA_EC:
XMEMCPY(st, &ec_oid, sizeof(*st));
break;
- case EC_PRIME_FIELD:
+ case PKA_EC_PRIMEF:
XMEMCPY(st, &ec_primef, sizeof(*st));
break;
default:
diff --git a/src/ltc/modes/ctr/ctr_encrypt.c b/src/ltc/modes/ctr/ctr_encrypt.c
index ecc7b01b..7319cf53 100644
--- a/src/ltc/modes/ctr/ctr_encrypt.c
+++ b/src/ltc/modes/ctr/ctr_encrypt.c
@@ -53,6 +53,8 @@ int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, s
if ((err = cipher_descriptor[ctr->cipher].accel_ctr_encrypt(pt, ct, len/ctr->blocklen, ctr->ctr, ctr->mode, &ctr->key)) != CRYPT_OK) {
return err;
}
+ pt += (len / ctr->blocklen) * ctr->blocklen;
+ ct += (len / ctr->blocklen) * ctr->blocklen;
len %= ctr->blocklen;
}
diff --git a/src/ltc/pk/asn1/der/bit/der_decode_bit_string.c b/src/ltc/pk/asn1/der/bit/der_decode_bit_string.c
index 5203fcfd..6f25cd9a 100644
--- a/src/ltc/pk/asn1/der/bit/der_decode_bit_string.c
+++ b/src/ltc/pk/asn1/der/bit/der_decode_bit_string.c
@@ -28,6 +28,7 @@ int der_decode_bit_string(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen)
{
unsigned long dlen, blen, x, y;
+ int err;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(out != NULL);
@@ -47,27 +48,13 @@ int der_decode_bit_string(const unsigned char *in, unsigned long inlen,
x = 1;
/* get the length of the data */
- if (in[x] & 0x80) {
- /* long format get number of length bytes */
- y = in[x++] & 0x7F;
-
- /* invalid if 0 or > 2 */
- if (y == 0 || y > 2) {
- return CRYPT_INVALID_PACKET;
- }
-
- /* read the data len */
- dlen = 0;
- while (y--) {
- dlen = (dlen << 8) | (unsigned long)in[x++];
- }
- } else {
- /* short format */
- dlen = in[x++] & 0x7F;
+ y = inlen - 1;
+ if ((err = der_decode_asn1_length(in + x, &y, &dlen)) != CRYPT_OK) {
+ return err;
}
-
+ x += y;
/* is the data len too long or too short? */
- if ((dlen == 0) || (dlen + x > inlen)) {
+ if ((dlen == 0) || (dlen > (inlen - x))) {
return CRYPT_INVALID_PACKET;
}
diff --git a/src/ltc/pk/asn1/der/bit/der_decode_raw_bit_string.c b/src/ltc/pk/asn1/der/bit/der_decode_raw_bit_string.c
index 223899b3..7e7a4608 100644
--- a/src/ltc/pk/asn1/der/bit/der_decode_raw_bit_string.c
+++ b/src/ltc/pk/asn1/der/bit/der_decode_raw_bit_string.c
@@ -31,6 +31,7 @@ int der_decode_raw_bit_string(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen)
{
unsigned long dlen, blen, x, y;
+ int err;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(out != NULL);
@@ -50,27 +51,13 @@ int der_decode_raw_bit_string(const unsigned char *in, unsigned long inlen,
x = 1;
/* get the length of the data */
- if (in[x] & 0x80) {
- /* long format get number of length bytes */
- y = in[x++] & 0x7F;
-
- /* invalid if 0 or > 2 */
- if (y == 0 || y > 2) {
- return CRYPT_INVALID_PACKET;
- }
-
- /* read the data len */
- dlen = 0;
- while (y--) {
- dlen = (dlen << 8) | (unsigned long)in[x++];
- }
- } else {
- /* short format */
- dlen = in[x++] & 0x7F;
+ y = inlen - 1;
+ if ((err = der_decode_asn1_length(in + x, &y, &dlen)) != CRYPT_OK) {
+ return err;
}
-
+ x += y;
/* is the data len too long or too short? */
- if ((dlen == 0) || (dlen + x > inlen)) {
+ if ((dlen == 0) || (dlen > (inlen - x))) {
return CRYPT_INVALID_PACKET;
}
diff --git a/src/ltc/pk/asn1/der/bit/der_encode_bit_string.c b/src/ltc/pk/asn1/der/bit/der_encode_bit_string.c
index 2a674790..7b2c6afa 100644
--- a/src/ltc/pk/asn1/der/bit/der_encode_bit_string.c
+++ b/src/ltc/pk/asn1/der/bit/der_encode_bit_string.c
@@ -50,16 +50,11 @@ int der_encode_bit_string(const unsigned char *in, unsigned long inlen,
y = ((inlen + 7) >> 3) + 1;
out[x++] = 0x03;
- if (y < 128) {
- out[x++] = (unsigned char)y;
- } else if (y < 256) {
- out[x++] = 0x81;
- out[x++] = (unsigned char)y;
- } else if (y < 65536) {
- out[x++] = 0x82;
- out[x++] = (unsigned char)((y>>8)&255);
- out[x++] = (unsigned char)(y&255);
+ len = *outlen - x;
+ if ((err = der_encode_asn1_length(y, out + x, &len)) != CRYPT_OK) {
+ return err;
}
+ x += len;
/* store number of zero padding bits */
out[x++] = (unsigned char)((8 - inlen) & 7);
diff --git a/src/ltc/pk/asn1/der/bit/der_encode_raw_bit_string.c b/src/ltc/pk/asn1/der/bit/der_encode_raw_bit_string.c
index 4101a1da..e884dabe 100644
--- a/src/ltc/pk/asn1/der/bit/der_encode_raw_bit_string.c
+++ b/src/ltc/pk/asn1/der/bit/der_encode_raw_bit_string.c
@@ -52,16 +52,11 @@ int der_encode_raw_bit_string(const unsigned char *in, unsigned long inlen,
y = ((inlen + 7) >> 3) + 1;
out[x++] = 0x03;
- if (y < 128) {
- out[x++] = (unsigned char)y;
- } else if (y < 256) {
- out[x++] = 0x81;
- out[x++] = (unsigned char)y;
- } else if (y < 65536) {
- out[x++] = 0x82;
- out[x++] = (unsigned char)((y>>8)&255);
- out[x++] = (unsigned char)(y&255);
+ len = *outlen - x;
+ if ((err = der_encode_asn1_length(y, out + x, &len)) != CRYPT_OK) {
+ return err;
}
+ x += len;
/* store number of zero padding bits */
out[x++] = (unsigned char)((8 - inlen) & 7);
diff --git a/src/ltc/pk/asn1/der/bit/der_length_bit_string.c b/src/ltc/pk/asn1/der/bit/der_length_bit_string.c
index b9c99fb1..7a652084 100644
--- a/src/ltc/pk/asn1/der/bit/der_length_bit_string.c
+++ b/src/ltc/pk/asn1/der/bit/der_length_bit_string.c
@@ -22,24 +22,18 @@
*/
int der_length_bit_string(unsigned long nbits, unsigned long *outlen)
{
- unsigned long nbytes;
+ unsigned long nbytes, x;
+ int err;
+
LTC_ARGCHK(outlen != NULL);
/* get the number of the bytes */
nbytes = (nbits >> 3) + ((nbits & 7) ? 1 : 0) + 1;
- if (nbytes < 128) {
- /* 03 LL PP DD DD DD ... */
- *outlen = 2 + nbytes;
- } else if (nbytes < 256) {
- /* 03 81 LL PP DD DD DD ... */
- *outlen = 3 + nbytes;
- } else if (nbytes < 65536) {
- /* 03 82 LL LL PP DD DD DD ... */
- *outlen = 4 + nbytes;
- } else {
- return CRYPT_INVALID_ARG;
+ if ((err = der_length_asn1_length(nbytes, &x)) != CRYPT_OK) {
+ return err;
}
+ *outlen = 1 + x + nbytes;
return CRYPT_OK;
}
diff --git a/src/ltc/pk/asn1/der/choice/der_decode_choice.c b/src/ltc/pk/asn1/der/choice/der_decode_choice.c
index 0bfd3bb6..6e17a4b7 100644
--- a/src/ltc/pk/asn1/der/choice/der_decode_choice.c
+++ b/src/ltc/pk/asn1/der/choice/der_decode_choice.c
@@ -205,9 +205,17 @@ int der_decode_choice(const unsigned char *in, unsigned long *inlen,
}
break;
+ case LTC_ASN1_CUSTOM_TYPE:
+ if (der_decode_custom_type(in, *inlen, &list[x]) == CRYPT_OK) {
+ if (der_length_custom_type(&list[x], &z, NULL) == CRYPT_OK) {
+ list[x].used = 1;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
case LTC_ASN1_CHOICE:
- case LTC_ASN1_CONSTRUCTED:
- case LTC_ASN1_CONTEXT_SPECIFIC:
case LTC_ASN1_EOL:
return CRYPT_INVALID_ARG;
}
diff --git a/src/ltc/pk/asn1/der/custom_type/der_decode_custom_type.c b/src/ltc/pk/asn1/der/custom_type/der_decode_custom_type.c
new file mode 100644
index 00000000..9bc34312
--- /dev/null
+++ b/src/ltc/pk/asn1/der/custom_type/der_decode_custom_type.c
@@ -0,0 +1,420 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+#include "tomcrypt.h"
+
+
+/**
+ @file der_decode_custom_type.c
+ ASN.1 DER, decode a Custom type, Steffen Jaeckel
+*/
+
+#ifdef LTC_DER
+
+/**
+ Decode a Custom type
+ @param in The DER encoded input
+ @param inlen The size of the input
+ @param root The item that defines the custom type to decode
+ @return CRYPT_OK on success
+*/
+int der_decode_custom_type(const unsigned char *in, unsigned long inlen,
+ ltc_asn1_list *root)
+{
+ LTC_ARGCHK(root != NULL);
+ return der_decode_custom_type_ex(in, inlen, root, NULL, 0, LTC_DER_SEQ_ORDERED | LTC_DER_SEQ_RELAXED);
+}
+
+/**
+ Extended-decode a Custom type
+
+ This function is used to decode custom types and sequences/sets
+ For custom types root is used
+ For sequences/sets list and outlen are used
+
+ @param in The DER encoded input
+ @param inlen The size of the input
+ @param root The item that defines the custom type to decode
+ @param list The list of items to decode
+ @param outlen The number of items in the list
+ @param flags c.f. enum ltc_der_seq
+ @return CRYPT_OK on success
+*/
+int der_decode_custom_type_ex(const unsigned char *in, unsigned long inlen,
+ ltc_asn1_list *root,
+ ltc_asn1_list *list, unsigned long outlen,
+ unsigned int flags)
+{
+ int err, seq_err, i, ordered;
+ ltc_asn1_type type;
+ ltc_asn1_list ident;
+ unsigned long size, x, y, z, blksize;
+ unsigned char* in_new = NULL;
+ void *data;
+
+ LTC_ARGCHK(in != NULL);
+
+ /* get blk size */
+ if (inlen < 2) {
+ return CRYPT_INVALID_PACKET;
+ }
+ x = 0;
+
+ if (root == NULL) {
+ LTC_ARGCHK(list != NULL);
+
+ /* sequence type? We allow 0x30 SEQUENCE and 0x31 SET since fundamentally they're the same structure */
+ if (in[x] != 0x30 && in[x] != 0x31) {
+ return CRYPT_INVALID_PACKET;
+ }
+ ++x;
+ } else {
+ if (root->type != LTC_ASN1_CUSTOM_TYPE) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* Alloc a copy of the data for primitive handling. */
+ if (root->pc == LTC_ASN1_PC_PRIMITIVE) {
+ in_new = XMALLOC(inlen);
+ if (in_new == NULL) {
+ return CRYPT_MEM;
+ }
+ XMEMCPY(in_new, in, inlen);
+ in = in_new;
+ }
+
+ y = inlen;
+ if ((err = der_decode_asn1_identifier(in, &y, &ident)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((ident.type != root->type) ||
+ (ident.class != root->class) ||
+ (ident.pc != root->pc) ||
+ (ident.tag != root->tag)) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+ x += y;
+
+ list = root->data;
+ outlen = root->size;
+ }
+
+ if (root != NULL && root->pc == LTC_ASN1_PC_PRIMITIVE) {
+ if (((unsigned long)root->used >= der_asn1_type_to_identifier_map_sz) ||
+ (der_asn1_type_to_identifier_map[root->used] == -1)) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+
+ root->type = (ltc_asn1_type)root->used;
+ list = root;
+ outlen = 1;
+
+ x -= 1;
+ in_new[x] = (unsigned char)der_asn1_type_to_identifier_map[list[0].type];
+ blksize = inlen - x;
+ } else {
+
+ y = inlen - x;
+ if ((err = der_decode_asn1_length(&in[x], &y, &blksize)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += y;
+ }
+
+ /* would this blksize overflow? */
+ if (blksize > (inlen - x)) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+
+ /* mark all as unused */
+ for (i = 0; i < (int)outlen; i++) {
+ list[i].used = 0;
+ }
+ ordered = flags & LTC_DER_SEQ_ORDERED;
+
+ /* ok read data */
+ seq_err = CRYPT_OK;
+ blksize += x;
+ inlen -= x;
+ for (i = 0; i < (int)outlen; i++) {
+ z = 0;
+ type = list[i].type;
+ size = list[i].size;
+ data = list[i].data;
+ if (!ordered && list[i].used == 1) { continue; }
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ if (root != NULL && root->pc == LTC_ASN1_PC_PRIMITIVE && i != 0) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto LBL_ERR;
+ }
+
+ switch (type) {
+ case LTC_ASN1_BOOLEAN:
+ z = inlen;
+ if ((err = der_decode_boolean(in + x, z, ((int *)data))) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ if ((err = der_length_boolean(&z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_INTEGER:
+ z = inlen;
+ if ((err = der_decode_integer(in + x, z, data)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ if ((err = der_length_integer(data, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_SHORT_INTEGER:
+ z = inlen;
+ if ((err = der_decode_short_integer(in + x, z, data)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ if ((err = der_length_short_integer(((unsigned long*)data)[0], &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ break;
+
+ case LTC_ASN1_BIT_STRING:
+ z = inlen;
+ if ((err = der_decode_bit_string(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_bit_string(size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_RAW_BIT_STRING:
+ z = inlen;
+ if ((err = der_decode_raw_bit_string(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_bit_string(size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_OCTET_STRING:
+ z = inlen;
+ if ((err = der_decode_octet_string(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_octet_string(size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_NULL:
+ if (inlen < 2 || in[x] != 0x05 || in[x+1] != 0x00) {
+ if (!ordered || list[i].optional) { continue; }
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+ z = 2;
+ break;
+
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ z = inlen;
+ if ((err = der_decode_object_identifier(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_object_identifier(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_TELETEX_STRING:
+ z = inlen;
+ if ((err = der_decode_teletex_string(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_teletex_string(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_IA5_STRING:
+ z = inlen;
+ if ((err = der_decode_ia5_string(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_ia5_string(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_PRINTABLE_STRING:
+ z = inlen;
+ if ((err = der_decode_printable_string(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_printable_string(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_UTF8_STRING:
+ z = inlen;
+ if ((err = der_decode_utf8_string(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_utf8_string(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_UTCTIME:
+ z = inlen;
+ if ((err = der_decode_utctime(in + x, &z, data)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_GENERALIZEDTIME:
+ z = inlen;
+ if ((err = der_decode_generalizedtime(in + x, &z, data)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_SET:
+ z = inlen;
+ if ((err = der_decode_set(in + x, z, data, size)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_SETOF:
+ case LTC_ASN1_SEQUENCE:
+ /* detect if we have the right type */
+ if ((type == LTC_ASN1_SETOF && (in[x] & 0x3F) != 0x31) || (type == LTC_ASN1_SEQUENCE && (in[x] & 0x3F) != 0x30)) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+
+ z = inlen;
+ err = der_decode_sequence_ex(in + x, z, data, size, flags);
+ if (err == CRYPT_INPUT_TOO_LONG) {
+ seq_err = CRYPT_INPUT_TOO_LONG;
+ err = CRYPT_OK;
+ }
+ if (err != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_CUSTOM_TYPE:
+ z = inlen;
+ err = der_decode_custom_type(in + x, z, &list[i]);
+ if (err == CRYPT_INPUT_TOO_LONG) {
+ seq_err = CRYPT_INPUT_TOO_LONG;
+ err = CRYPT_OK;
+ }
+ if (err != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ if ((err = der_length_custom_type(&list[i], &z, NULL)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_CHOICE:
+ z = inlen;
+ if ((err = der_decode_choice(in + x, &z, data, size)) != CRYPT_OK) {
+ if (!ordered || list[i].optional) { continue; }
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_EOL:
+ err = CRYPT_INVALID_ARG;
+ goto LBL_ERR;
+ }
+ x += z;
+ inlen -= z;
+ list[i].used = 1;
+ if (!ordered) {
+ /* restart the decoder */
+ i = -1;
+ }
+ }
+
+ for (i = 0; i < (int)outlen; i++) {
+ if (list[i].used == 0 && list[i].optional == 0) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+ }
+
+ if (blksize == x && seq_err == CRYPT_OK && inlen == 0) {
+ /* everything decoded and no errors in nested sequences */
+ err = CRYPT_OK;
+ } else if (blksize == x && seq_err == CRYPT_INPUT_TOO_LONG && inlen == 0) {
+ /* a sequence reported too-long input, but now we've decoded everything */
+ err = CRYPT_OK;
+ } else if (blksize != x && ((flags & LTC_DER_SEQ_STRICT) == LTC_DER_SEQ_STRICT)) {
+ err = CRYPT_INVALID_PACKET;
+ } else {
+ err = CRYPT_INPUT_TOO_LONG;
+ }
+
+LBL_ERR:
+ if (in_new != NULL) {
+ XFREE(in_new);
+ }
+ return err;
+}
+
+#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/asn1/der/custom_type/der_encode_custom_type.c b/src/ltc/pk/asn1/der/custom_type/der_encode_custom_type.c
new file mode 100644
index 00000000..d19774c4
--- /dev/null
+++ b/src/ltc/pk/asn1/der/custom_type/der_encode_custom_type.c
@@ -0,0 +1,238 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+#include "tomcrypt.h"
+
+
+/**
+ @file der_encode_custom_type.c
+ ASN.1 DER, encode a Custom Type, Steffen Jaeckel
+*/
+
+#ifdef LTC_DER
+
+/**
+ Encode a Custom Type
+
+ This function is a bit special compared to the others, as it requires the
+ root-ltc_asn1_list where the type is defined.
+
+ @param root The root of the list of items to encode
+ @param out [out] The destination
+ @param outlen [in/out] The size of the output
+ @return CRYPT_OK on success
+*/
+int der_encode_custom_type(const ltc_asn1_list *root,
+ unsigned char *out, unsigned long *outlen)
+{
+ int err;
+ ltc_asn1_type type;
+ const ltc_asn1_list *list;
+ unsigned long size, x, y, z, i, inlen, id_len;
+ void *data;
+
+ LTC_ARGCHK(root != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* get size of output that will be required */
+ y = 0; z = 0;
+ if ((err = der_length_custom_type(root, &y, &z)) != CRYPT_OK) return CRYPT_INVALID_ARG;
+
+ /* too big ? */
+ if (*outlen < y) {
+ *outlen = y;
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto LBL_ERR;
+ }
+
+ /* get length of the identifier, so we know the offset where to start writing */
+ if ((err = der_length_asn1_identifier(root, &id_len)) != CRYPT_OK) return CRYPT_INVALID_ARG;
+ x = id_len;
+
+
+ if (root->pc == LTC_ASN1_PC_PRIMITIVE) {
+ list = root;
+ inlen = 1;
+ /* In case it's a PRIMITIVE type we encode directly to the output
+ * but leave space for a potentially longer identifier as it will
+ * simply be replaced afterwards.
+ */
+ x -= 1;
+ } else {
+ list = root->data;
+ inlen = root->size;
+ /* store length, identifier will be added later */
+ y = *outlen - x;
+ if ((err = der_encode_asn1_length(z, &out[x], &y)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += y;
+ }
+
+ /* store data */
+ *outlen -= x;
+ for (i = 0; i < inlen; i++) {
+ if (root->pc == LTC_ASN1_PC_PRIMITIVE) {
+ type = (ltc_asn1_type)list[i].used;
+ } else {
+ type = list[i].type;
+ }
+ size = list[i].size;
+ data = list[i].data;
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ switch (type) {
+ case LTC_ASN1_BOOLEAN:
+ z = *outlen;
+ if ((err = der_encode_boolean(*((int *)data), out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_INTEGER:
+ z = *outlen;
+ if ((err = der_encode_integer(data, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_SHORT_INTEGER:
+ z = *outlen;
+ if ((err = der_encode_short_integer(*((unsigned long*)data), out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_BIT_STRING:
+ z = *outlen;
+ if ((err = der_encode_bit_string(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_RAW_BIT_STRING:
+ z = *outlen;
+ if ((err = der_encode_raw_bit_string(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_OCTET_STRING:
+ z = *outlen;
+ if ((err = der_encode_octet_string(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_NULL:
+ out[x] = 0x05;
+ out[x+1] = 0x00;
+ z = 2;
+ break;
+
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ z = *outlen;
+ if ((err = der_encode_object_identifier(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_IA5_STRING:
+ z = *outlen;
+ if ((err = der_encode_ia5_string(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_PRINTABLE_STRING:
+ z = *outlen;
+ if ((err = der_encode_printable_string(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_UTF8_STRING:
+ z = *outlen;
+ if ((err = der_encode_utf8_string(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_UTCTIME:
+ z = *outlen;
+ if ((err = der_encode_utctime(data, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_GENERALIZEDTIME:
+ z = *outlen;
+ if ((err = der_encode_generalizedtime(data, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_SET:
+ z = *outlen;
+ if ((err = der_encode_set(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_SETOF:
+ z = *outlen;
+ if ((err = der_encode_setof(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_SEQUENCE:
+ z = *outlen;
+ if ((err = der_encode_sequence_ex(data, size, out + x, &z, type)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_CUSTOM_TYPE:
+ z = *outlen;
+ if ((err = der_encode_custom_type(&list[i], out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_CHOICE:
+ case LTC_ASN1_EOL:
+ case LTC_ASN1_TELETEX_STRING:
+ err = CRYPT_INVALID_ARG;
+ goto LBL_ERR;
+ }
+
+
+ x += z;
+ *outlen -= z;
+ }
+
+ if ((err = der_encode_asn1_identifier(root, out, &id_len)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ *outlen = x;
+ err = CRYPT_OK;
+
+LBL_ERR:
+ return err;
+}
+
+#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/asn1/der/custom_type/der_length_custom_type.c b/src/ltc/pk/asn1/der/custom_type/der_length_custom_type.c
new file mode 100644
index 00000000..aecc4647
--- /dev/null
+++ b/src/ltc/pk/asn1/der/custom_type/der_length_custom_type.c
@@ -0,0 +1,213 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_length_custom_type.c
+ ASN.1 DER, length of a custom type, Steffen Jaeckel
+*/
+
+#ifdef LTC_DER
+
+/**
+ Get the length of a DER custom type
+
+ This function is a bit special compared to the others, as it requires the
+ root-ltc_asn1_list where the type is defined.
+
+ @param root The root of the struct to encode
+ @param outlen [out] The length required in octets to store it
+ @param payloadlen [out] The length of the payload in octets
+ @return CRYPT_OK on success
+*/
+int der_length_custom_type(const ltc_asn1_list *root, unsigned long *outlen, unsigned long *payloadlen)
+{
+ int err;
+ const ltc_asn1_list *list;
+ ltc_asn1_type type;
+ unsigned long size, x, y, i, inlen, id_len;
+ void *data;
+
+ LTC_ARGCHK(root != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* get size of output that will be required */
+ if ((err = der_length_asn1_identifier(root, &id_len)) != CRYPT_OK) {
+ return err;
+ }
+ y = id_len;
+
+ if (root->pc == LTC_ASN1_PC_PRIMITIVE) {
+ list = root;
+ inlen = 1;
+ } else {
+ list = root->data;
+ inlen = root->size;
+ }
+ for (i = 0; i < inlen; i++) {
+ if (root->pc == LTC_ASN1_PC_PRIMITIVE) {
+ type = (ltc_asn1_type)list[i].used;
+ } else {
+ type = list[i].type;
+ }
+ size = list[i].size;
+ data = list[i].data;
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ /* some items may be optional during import */
+ if (!list[i].used && list[i].optional) continue;
+
+ switch (type) {
+ case LTC_ASN1_BOOLEAN:
+ if ((err = der_length_boolean(&x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_INTEGER:
+ if ((err = der_length_integer(data, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_SHORT_INTEGER:
+ if ((err = der_length_short_integer(*((unsigned long *)data), &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_BIT_STRING:
+ case LTC_ASN1_RAW_BIT_STRING:
+ if ((err = der_length_bit_string(size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_OCTET_STRING:
+ if ((err = der_length_octet_string(size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_NULL:
+ y += 2;
+ break;
+
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ if ((err = der_length_object_identifier(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_IA5_STRING:
+ if ((err = der_length_ia5_string(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_TELETEX_STRING:
+ if ((err = der_length_teletex_string(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_PRINTABLE_STRING:
+ if ((err = der_length_printable_string(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_UTCTIME:
+ if ((err = der_length_utctime(data, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_GENERALIZEDTIME:
+ if ((err = der_length_generalizedtime(data, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_UTF8_STRING:
+ if ((err = der_length_utf8_string(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_CUSTOM_TYPE:
+ if ((err = der_length_custom_type(&list[i], &x, NULL)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_SET:
+ case LTC_ASN1_SETOF:
+ case LTC_ASN1_SEQUENCE:
+ if ((err = der_length_sequence(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_CHOICE:
+ case LTC_ASN1_EOL:
+ err = CRYPT_INVALID_ARG;
+ goto LBL_ERR;
+ }
+ }
+
+ if (root->pc == LTC_ASN1_PC_PRIMITIVE) {
+ /* In case it's a PRIMITIVE element we're going
+ * to only replace the identifier of the one element
+ * by the custom identifier.
+ */
+ y -= 1;
+ if (payloadlen != NULL) {
+ *payloadlen = y - id_len;
+ }
+ } else {
+ /* calc length of length */
+ if ((err = der_length_asn1_length(y, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if (payloadlen != NULL) {
+ *payloadlen = y - id_len;
+ }
+ y += x;
+ }
+
+ /* store size */
+ *outlen = y;
+
+LBL_ERR:
+ return err;
+}
+
+#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/asn1/der/general/der_asn1_maps.c b/src/ltc/pk/asn1/der/general/der_asn1_maps.c
new file mode 100644
index 00000000..ba9820f4
--- /dev/null
+++ b/src/ltc/pk/asn1/der/general/der_asn1_maps.c
@@ -0,0 +1,167 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_asn1_maps.c
+ ASN.1 DER, a collection of maps to convert between different representations, Steffen Jaeckel
+*/
+
+#ifdef LTC_DER
+
+/**
+ A Map from ltc_asn1_type to the regularly used ASN.1 identifier
+*/
+const int der_asn1_type_to_identifier_map[] =
+{
+ /* 0 */
+ -1, /* LTC_ASN1_EOL, */
+ 1, /* LTC_ASN1_BOOLEAN, */
+ 2, /* LTC_ASN1_INTEGER, */
+ 2, /* LTC_ASN1_SHORT_INTEGER, */
+ 3, /* LTC_ASN1_BIT_STRING, */
+ /* 5 */
+ 4, /* LTC_ASN1_OCTET_STRING, */
+ 5, /* LTC_ASN1_NULL, */
+ 6, /* LTC_ASN1_OBJECT_IDENTIFIER, */
+ 22, /* LTC_ASN1_IA5_STRING, */
+ 19, /* LTC_ASN1_PRINTABLE_STRING, */
+ /* 10 */
+ 12, /* LTC_ASN1_UTF8_STRING, */
+ 23, /* LTC_ASN1_UTCTIME, */
+ -1, /* LTC_ASN1_CHOICE, */
+ 48, /* LTC_ASN1_SEQUENCE, */
+ 49, /* LTC_ASN1_SET, */
+ /* 15 */
+ 49, /* LTC_ASN1_SETOF, */
+ 3, /* LTC_ASN1_RAW_BIT_STRING, */
+ 20, /* LTC_ASN1_TELETEX_STRING, */
+ 24, /* LTC_ASN1_GENERALIZEDTIME, */
+ -1, /* LTC_ASN1_CUSTOM_TYPE, */
+};
+const unsigned long der_asn1_type_to_identifier_map_sz = sizeof(der_asn1_type_to_identifier_map)/sizeof(der_asn1_type_to_identifier_map[0]);
+
+/**
+ A Map from the ASN.1 Class to its string
+*/
+const char* der_asn1_class_to_string_map[] =
+{
+ "UNIVERSAL",
+ "APPLICATION",
+ "CONTEXT-SPECIFIC",
+ "PRIVATE",
+};
+const unsigned long der_asn1_class_to_string_map_sz = sizeof(der_asn1_class_to_string_map)/sizeof(der_asn1_class_to_string_map[0]);
+
+/**
+ A Map from the ASN.1 P/C-bit to its string
+*/
+const char* der_asn1_pc_to_string_map[] =
+{
+ "PRIMITIVE",
+ "CONSTRUCTED",
+};
+const unsigned long der_asn1_pc_to_string_map_sz = sizeof(der_asn1_pc_to_string_map)/sizeof(der_asn1_pc_to_string_map[0]);
+
+/**
+ A Map from the ASN.1 tag to its string
+*/
+const char* der_asn1_tag_to_string_map[] =
+{
+ "Reserved for use by the encoding rules",
+ "Boolean type",
+ "Integer type",
+ "Bitstring type",
+ "Octetstring type",
+ "Null type",
+ "Object identifier type",
+ "Object descriptor type",
+ "External type and Instance-of type",
+ "Real type",
+ "Enumerated type",
+ "Embedded-pdv type",
+ "UTF8String type",
+ "Relative object identifier type",
+ "The time type",
+ "Reserved for future editions of this Recommendation | International Standard",
+ "Sequence and Sequence-of types",
+ "Set and Set-of types",
+ "NumericString type",
+ "PrintableString type",
+ "TeletexString (T61String) type",
+ "VideotexString type",
+ "IA5String type",
+ "UTCTime type",
+ "GeneralizedTime type",
+ "GraphicString type",
+ "VisibleString (ISO646String) type",
+ "GeneralString type",
+ "UniversalString type",
+ "UnrestrictedCharacterString type",
+ "BMPString type",
+ "Date type",
+ "TimeOfDay type",
+ "DateTime type",
+ "Duration type",
+ "OID internationalized resource identifier type",
+ "Relative OID internationalized resource identifier type",
+};
+const unsigned long der_asn1_tag_to_string_map_sz = sizeof(der_asn1_tag_to_string_map)/sizeof(der_asn1_tag_to_string_map[0]);
+
+/**
+ A Map from ASN.1 Tags to ltc_asn1_type
+*/
+const ltc_asn1_type der_asn1_tag_to_type_map[] =
+{
+ /* 0 */
+ LTC_ASN1_EOL, /* Reserved for use by the encoding rules */
+ LTC_ASN1_BOOLEAN, /* Boolean type */
+ LTC_ASN1_INTEGER, /* Integer type */
+ LTC_ASN1_BIT_STRING, /* Bitstring type */
+ LTC_ASN1_OCTET_STRING, /* Octetstring type */
+ /* 5 */
+ LTC_ASN1_NULL, /* Null type */
+ LTC_ASN1_OBJECT_IDENTIFIER, /* Object identifier type */
+ LTC_ASN1_CUSTOM_TYPE, /* Object descriptor type */
+ LTC_ASN1_CUSTOM_TYPE, /* External type and Instance-of type */
+ LTC_ASN1_CUSTOM_TYPE, /* Real type */
+ /* 10 */
+ LTC_ASN1_CUSTOM_TYPE, /* Enumerated type */
+ LTC_ASN1_CUSTOM_TYPE, /* Embedded-pdv type */
+ LTC_ASN1_UTF8_STRING, /* UTF8String type */
+ LTC_ASN1_CUSTOM_TYPE, /* Relative object identifier type */
+ LTC_ASN1_CUSTOM_TYPE, /* The time type */
+ /* 15 */
+ LTC_ASN1_EOL, /* Reserved for future editions of this Recommendation | International Standard */
+ LTC_ASN1_SEQUENCE, /* Sequence and Sequence-of types */
+ LTC_ASN1_SET, /* Set and Set-of types */
+ LTC_ASN1_CUSTOM_TYPE, /* NumericString types */
+ LTC_ASN1_PRINTABLE_STRING, /* PrintableString types */
+ /* 20 */
+ LTC_ASN1_TELETEX_STRING, /* TeletexString (T61String) types */
+ LTC_ASN1_CUSTOM_TYPE, /* VideotexString types */
+ LTC_ASN1_IA5_STRING, /* IA5String types */
+ LTC_ASN1_UTCTIME, /* UTCTime types */
+ LTC_ASN1_GENERALIZEDTIME, /* GeneralizedTime types */
+ /* 25 */
+ LTC_ASN1_CUSTOM_TYPE, /* GraphicString types */
+ LTC_ASN1_CUSTOM_TYPE, /* VisibleString (ISO646String) types */
+ LTC_ASN1_CUSTOM_TYPE, /* GeneralString types */
+ LTC_ASN1_CUSTOM_TYPE, /* UniversalString types */
+ LTC_ASN1_CUSTOM_TYPE, /* UnrestrictedCharacterString types */
+ /* 30 */
+ LTC_ASN1_CUSTOM_TYPE, /* BMPString types */
+};
+const unsigned long der_asn1_tag_to_type_map_sz = sizeof(der_asn1_tag_to_type_map)/sizeof(der_asn1_tag_to_type_map[0]);
+
+#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/asn1/der/general/der_decode_asn1_identifier.c b/src/ltc/pk/asn1/der/general/der_decode_asn1_identifier.c
new file mode 100644
index 00000000..b4689f6a
--- /dev/null
+++ b/src/ltc/pk/asn1/der/general/der_decode_asn1_identifier.c
@@ -0,0 +1,133 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_decode_asn1_identifier.c
+ ASN.1 DER, decode the ASN.1 Identifier, Steffen Jaeckel
+*/
+
+#ifdef LTC_DER
+/* c.f. X.680 & X.690, some decisions backed by X.690 ch. 10.2 */
+static const unsigned char tag_constructed_map[] =
+{
+ /* 0 */
+ 255,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ /* 5 */
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ /* 10 */
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ /* 15 */
+ 255,
+ LTC_ASN1_PC_CONSTRUCTED,
+ LTC_ASN1_PC_CONSTRUCTED,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ /* 20 */
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ /* 25 */
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+ LTC_ASN1_PC_PRIMITIVE,
+};
+ static const unsigned long tag_constructed_map_sz = sizeof(tag_constructed_map)/sizeof(tag_constructed_map[0]);
+
+/**
+ Decode the ASN.1 Identifier
+ @param id Where to store the decoded Identifier
+ @param in Where to read the Identifier from
+ @param inlen [in/out] The size of in available/read
+ @return CRYPT_OK if successful
+*/
+int der_decode_asn1_identifier(const unsigned char *in, unsigned long *inlen, ltc_asn1_list *id)
+{
+ ulong64 tmp;
+ unsigned long tag_len;
+ int err;
+
+ LTC_ARGCHK(id != NULL);
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(inlen != NULL);
+
+ if (*inlen == 0) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ tag_len = 1;
+ id->class = (in[0] >> 6) & 0x3;
+ id->pc = (in[0] >> 5) & 0x1;
+ id->tag = in[0] & 0x1f;
+
+ err = CRYPT_OK;
+ if (id->tag == 0x1f) {
+ id->tag = 0;
+ do {
+ if (*inlen < tag_len) {
+ /* break the loop and trigger the BOF error-code */
+ tmp = 0xff;
+ break;
+ }
+ id->tag <<= 7;
+ id->tag |= in[tag_len] & 0x7f;
+ tmp = in[tag_len] & 0x80;
+ tag_len++;
+ } while ((tmp != 0) && (tag_len < 10));
+
+ if (tmp != 0) {
+ err = CRYPT_BUFFER_OVERFLOW;
+ } else if (id->tag < 0x1f) {
+ err = CRYPT_PK_ASN1_ERROR;
+ }
+ }
+
+ if (err != CRYPT_OK) {
+ id->pc = 0;
+ id->class = 0;
+ id->tag = 0;
+ } else {
+ *inlen = tag_len;
+ if ((id->class == LTC_ASN1_CL_UNIVERSAL) &&
+ (id->tag < der_asn1_tag_to_type_map_sz) &&
+ (id->tag < tag_constructed_map_sz) &&
+ (id->pc == tag_constructed_map[id->tag])) {
+ id->type = der_asn1_tag_to_type_map[id->tag];
+ } else {
+ if ((id->class == LTC_ASN1_CL_UNIVERSAL) && (id->tag == 0)) {
+ id->type = LTC_ASN1_EOL;
+ } else {
+ id->type = LTC_ASN1_CUSTOM_TYPE;
+ }
+ }
+ }
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/asn1/der/general/der_decode_asn1_length.c b/src/ltc/pk/asn1/der/general/der_decode_asn1_length.c
new file mode 100644
index 00000000..0e1bc6c2
--- /dev/null
+++ b/src/ltc/pk/asn1/der/general/der_decode_asn1_length.c
@@ -0,0 +1,67 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_decode_asn1_length.c
+ ASN.1 DER, decode the ASN.1 Length field, Steffen Jaeckel
+*/
+
+#ifdef LTC_DER
+/**
+ Decode the ASN.1 Length field
+ @param in Where to read the length field from
+ @param inlen [in/out] The size of in available/read
+ @param outlen [out] The decoded ASN.1 length
+ @return CRYPT_OK if successful
+*/
+int der_decode_asn1_length(const unsigned char *in, unsigned long *inlen, unsigned long *outlen)
+{
+ unsigned long real_len, decoded_len, offset, i;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(inlen != NULL);
+
+ if (*inlen < 1) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ real_len = in[0];
+
+ if (real_len < 128) {
+ decoded_len = real_len;
+ offset = 1;
+ } else {
+ real_len &= 0x7F;
+ if (real_len == 0) {
+ return CRYPT_PK_ASN1_ERROR;
+ } else if (real_len > sizeof(decoded_len)) {
+ return CRYPT_OVERFLOW;
+ } else if (real_len > (*inlen - 1)) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+ decoded_len = 0;
+ offset = 1 + real_len;
+ for (i = 0; i < real_len; i++) {
+ decoded_len = (decoded_len << 8) | in[1 + i];
+ }
+ }
+
+ if (outlen != NULL) *outlen = decoded_len;
+ if (decoded_len > (*inlen - offset)) return CRYPT_OVERFLOW;
+ *inlen = offset;
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/asn1/der/general/der_encode_asn1_identifier.c b/src/ltc/pk/asn1/der/general/der_encode_asn1_identifier.c
new file mode 100644
index 00000000..367bb699
--- /dev/null
+++ b/src/ltc/pk/asn1/der/general/der_encode_asn1_identifier.c
@@ -0,0 +1,97 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_encode_asn1_identifier.c
+ ASN.1 DER, encode the ASN.1 Identifier, Steffen Jaeckel
+*/
+
+#ifdef LTC_DER
+/**
+ Encode the ASN.1 Identifier
+ @param id The ASN.1 Identifer to encode
+ @param out Where to write the identifier to
+ @param outlen [in/out] The size of out available/written
+ @return CRYPT_OK if successful
+*/
+int der_encode_asn1_identifier(const ltc_asn1_list *id, unsigned char *out, unsigned long *outlen)
+{
+ ulong64 tmp;
+ unsigned long tag_len;
+
+ LTC_ARGCHK(id != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ if (id->type != LTC_ASN1_CUSTOM_TYPE) {
+ if ((unsigned)id->type >= der_asn1_type_to_identifier_map_sz) {
+ return CRYPT_INVALID_ARG;
+ }
+ if (der_asn1_type_to_identifier_map[id->type] == -1) {
+ return CRYPT_INVALID_ARG;
+ }
+ if (out != NULL) {
+ *out = der_asn1_type_to_identifier_map[id->type];
+ }
+ *outlen = 1;
+ return CRYPT_OK;
+ } else {
+ if (id->class < LTC_ASN1_CL_UNIVERSAL || id->class > LTC_ASN1_CL_PRIVATE) {
+ return CRYPT_INVALID_ARG;
+ }
+ if (id->pc < LTC_ASN1_PC_PRIMITIVE || id->pc > LTC_ASN1_PC_CONSTRUCTED) {
+ return CRYPT_INVALID_ARG;
+ }
+ if (id->tag > (ULONG_MAX >> (8 + 7))) {
+ return CRYPT_INVALID_ARG;
+ }
+ }
+
+ if (out != NULL) {
+ if (*outlen < 1) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ out[0] = id->class << 6 | id->pc << 5;
+ }
+
+ if (id->tag < 0x1f) {
+ if (out != NULL) {
+ out[0] |= id->tag & 0x1f;
+ }
+ *outlen = 1;
+ } else {
+ tag_len = 0;
+ tmp = id->tag;
+ do {
+ tag_len++;
+ tmp >>= 7;
+ } while (tmp);
+
+ if (out != NULL) {
+ if (*outlen < tag_len + 1) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+ out[0] |= 0x1f;
+ for (tmp = 1; tmp <= tag_len; ++tmp) {
+ out[tmp] = ((id->tag >> (7 * (tag_len - tmp))) & 0x7f) | 0x80;
+ }
+ out[tag_len] &= ~0x80;
+ }
+ *outlen = tag_len + 1;
+ }
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/asn1/der/general/der_encode_asn1_length.c b/src/ltc/pk/asn1/der/general/der_encode_asn1_length.c
new file mode 100644
index 00000000..0d871afe
--- /dev/null
+++ b/src/ltc/pk/asn1/der/general/der_encode_asn1_length.c
@@ -0,0 +1,127 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_encode_asn1_length.c
+ ASN.1 DER, encode the ASN.1 length field, Steffen Jaeckel
+*/
+
+#ifdef LTC_DER
+/**
+ Encode the ASN.1 length field
+ @param len The length to encode
+ @param out Where to write the length field to
+ @param outlen [in/out] The size of out available/written
+ @return CRYPT_OK if successful
+*/
+int der_encode_asn1_length(unsigned long len, unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x, y;
+
+ LTC_ARGCHK(outlen != NULL);
+
+ x = len;
+ y = 0;
+
+ while(x != 0) {
+ y++;
+ x >>= 8;
+ }
+ if (y == 0) {
+ return CRYPT_PK_ASN1_ERROR;
+ }
+
+ if (out == NULL) {
+ if (len < 128) {
+ x = y;
+ } else {
+ x = y + 1;
+ }
+ } else {
+ if (*outlen < y) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+ x = 0;
+ if (len < 128) {
+ out[x++] = (unsigned char)len;
+ } else if (len <= 0xffUL) {
+ out[x++] = 0x81;
+ out[x++] = (unsigned char)len;
+ } else if (len <= 0xffffUL) {
+ out[x++] = 0x82;
+ out[x++] = (unsigned char)((len>>8UL)&255);
+ out[x++] = (unsigned char)(len&255);
+ } else if (len <= 0xffffffUL) {
+ out[x++] = 0x83;
+ out[x++] = (unsigned char)((len>>16UL)&255);
+ out[x++] = (unsigned char)((len>>8UL)&255);
+ out[x++] = (unsigned char)(len&255);
+ #if ULONG_MAX != ULLONG_MAX
+ } else {
+ out[x++] = 0x84;
+ out[x++] = (unsigned char)((len>>24UL)&255);
+ out[x++] = (unsigned char)((len>>16UL)&255);
+ out[x++] = (unsigned char)((len>>8UL)&255);
+ out[x++] = (unsigned char)(len&255);
+ }
+ #else
+ } else if (len <= 0xffffffffUL) {
+ out[x++] = 0x84;
+ out[x++] = (unsigned char)((len>>24UL)&255);
+ out[x++] = (unsigned char)((len>>16UL)&255);
+ out[x++] = (unsigned char)((len>>8UL)&255);
+ out[x++] = (unsigned char)(len&255);
+ } else if (len <= 0xffffffffffULL) {
+ out[x++] = 0x85;
+ out[x++] = (unsigned char)((len>>32ULL)&255);
+ out[x++] = (unsigned char)((len>>24ULL)&255);
+ out[x++] = (unsigned char)((len>>16ULL)&255);
+ out[x++] = (unsigned char)((len>>8ULL)&255);
+ out[x++] = (unsigned char)(len&255);
+ } else if (len <= 0xffffffffffffULL) {
+ out[x++] = 0x86;
+ out[x++] = (unsigned char)((len>>40ULL)&255);
+ out[x++] = (unsigned char)((len>>32ULL)&255);
+ out[x++] = (unsigned char)((len>>24ULL)&255);
+ out[x++] = (unsigned char)((len>>16ULL)&255);
+ out[x++] = (unsigned char)((len>>8ULL)&255);
+ out[x++] = (unsigned char)(len&255);
+ } else if (len <= 0xffffffffffffffULL) {
+ out[x++] = 0x87;
+ out[x++] = (unsigned char)((len>>48ULL)&255);
+ out[x++] = (unsigned char)((len>>40ULL)&255);
+ out[x++] = (unsigned char)((len>>32ULL)&255);
+ out[x++] = (unsigned char)((len>>24ULL)&255);
+ out[x++] = (unsigned char)((len>>16ULL)&255);
+ out[x++] = (unsigned char)((len>>8ULL)&255);
+ out[x++] = (unsigned char)(len&255);
+ } else {
+ out[x++] = 0x88;
+ out[x++] = (unsigned char)((len>>56ULL)&255);
+ out[x++] = (unsigned char)((len>>48ULL)&255);
+ out[x++] = (unsigned char)((len>>40ULL)&255);
+ out[x++] = (unsigned char)((len>>32ULL)&255);
+ out[x++] = (unsigned char)((len>>24ULL)&255);
+ out[x++] = (unsigned char)((len>>16ULL)&255);
+ out[x++] = (unsigned char)((len>>8ULL)&255);
+ out[x++] = (unsigned char)(len&255);
+ }
+ #endif
+ }
+ *outlen = x;
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/asn1/der/general/der_length_asn1_identifier.c b/src/ltc/pk/asn1/der/general/der_length_asn1_identifier.c
new file mode 100644
index 00000000..40e76f02
--- /dev/null
+++ b/src/ltc/pk/asn1/der/general/der_length_asn1_identifier.c
@@ -0,0 +1,33 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_length_asn1_identifier.c
+ ASN.1 DER, determine the length when encoding the ASN.1 Identifier, Steffen Jaeckel
+*/
+
+#ifdef LTC_DER
+/**
+ Determine the length required when encoding the ASN.1 Identifier
+ @param id The ASN.1 identifier to encode
+ @param idlen [out] The required length to encode list
+ @return CRYPT_OK if successful
+*/
+
+int der_length_asn1_identifier(const ltc_asn1_list *id, unsigned long *idlen)
+{
+ return der_encode_asn1_identifier(id, NULL, idlen);
+}
+
+#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/asn1/der/general/der_length_asn1_length.c b/src/ltc/pk/asn1/der/general/der_length_asn1_length.c
new file mode 100644
index 00000000..1271e1cb
--- /dev/null
+++ b/src/ltc/pk/asn1/der/general/der_length_asn1_length.c
@@ -0,0 +1,32 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_length_asn1_length.c
+ ASN.1 DER, determine the length of the ASN.1 length field, Steffen Jaeckel
+*/
+
+#ifdef LTC_DER
+/**
+ Determine the length required to encode len in the ASN.1 length field
+ @param len The length to encode
+ @param outlen [out] The length that's required to store len
+ @return CRYPT_OK if successful
+*/
+int der_length_asn1_length(unsigned long len, unsigned long *outlen)
+{
+ return der_encode_asn1_length(len, NULL, outlen);
+}
+
+#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/asn1/der/ia5/der_decode_ia5_string.c b/src/ltc/pk/asn1/der/ia5/der_decode_ia5_string.c
index c3472519..15e90f88 100644
--- a/src/ltc/pk/asn1/der/ia5/der_decode_ia5_string.c
+++ b/src/ltc/pk/asn1/der/ia5/der_decode_ia5_string.c
@@ -28,7 +28,7 @@ int der_decode_ia5_string(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen)
{
unsigned long x, y, len;
- int t;
+ int t, err;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(out != NULL);
@@ -45,23 +45,12 @@ int der_decode_ia5_string(const unsigned char *in, unsigned long inlen,
}
x = 1;
- /* decode the length */
- if (in[x] & 0x80) {
- /* valid # of bytes in length are 1,2,3 */
- y = in[x] & 0x7F;
- if ((y == 0) || (y > 3) || ((x + y) > inlen)) {
- return CRYPT_INVALID_PACKET;
- }
-
- /* read the length in */
- len = 0;
- ++x;
- while (y--) {
- len = (len << 8) | in[x++];
- }
- } else {
- len = in[x++] & 0x7F;
+ /* get the length of the data */
+ y = inlen - x;
+ if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) {
+ return err;
}
+ x += y;
/* is it too long? */
if (len > *outlen) {
@@ -69,7 +58,7 @@ int der_decode_ia5_string(const unsigned char *in, unsigned long inlen,
return CRYPT_BUFFER_OVERFLOW;
}
- if (len + x > inlen) {
+ if (len > (inlen - x)) {
return CRYPT_INVALID_PACKET;
}
diff --git a/src/ltc/pk/asn1/der/ia5/der_encode_ia5_string.c b/src/ltc/pk/asn1/der/ia5/der_encode_ia5_string.c
index 18b926ea..fee1c703 100644
--- a/src/ltc/pk/asn1/der/ia5/der_encode_ia5_string.c
+++ b/src/ltc/pk/asn1/der/ia5/der_encode_ia5_string.c
@@ -47,23 +47,11 @@ int der_encode_ia5_string(const unsigned char *in, unsigned long inlen,
/* encode the header+len */
x = 0;
out[x++] = 0x16;
- if (inlen < 128) {
- out[x++] = (unsigned char)inlen;
- } else if (inlen < 256) {
- out[x++] = 0x81;
- out[x++] = (unsigned char)inlen;
- } else if (inlen < 65536UL) {
- out[x++] = 0x82;
- out[x++] = (unsigned char)((inlen>>8)&255);
- out[x++] = (unsigned char)(inlen&255);
- } else if (inlen < 16777216UL) {
- out[x++] = 0x83;
- out[x++] = (unsigned char)((inlen>>16)&255);
- out[x++] = (unsigned char)((inlen>>8)&255);
- out[x++] = (unsigned char)(inlen&255);
- } else {
- return CRYPT_INVALID_ARG;
+ len = *outlen - x;
+ if ((err = der_encode_asn1_length(inlen, out + x, &len)) != CRYPT_OK) {
+ return err;
}
+ x += len;
/* store octets */
for (y = 0; y < inlen; y++) {
diff --git a/src/ltc/pk/asn1/der/ia5/der_length_ia5_string.c b/src/ltc/pk/asn1/der/ia5/der_length_ia5_string.c
index 5f1a78d1..422c4d33 100644
--- a/src/ltc/pk/asn1/der/ia5/der_length_ia5_string.c
+++ b/src/ltc/pk/asn1/der/ia5/der_length_ia5_string.c
@@ -154,6 +154,7 @@ int der_ia5_value_decode(int v)
int der_length_ia5_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen)
{
unsigned long x;
+ int err;
LTC_ARGCHK(outlen != NULL);
LTC_ARGCHK(octets != NULL);
@@ -165,21 +166,10 @@ int der_length_ia5_string(const unsigned char *octets, unsigned long noctets, un
}
}
- if (noctets < 128) {
- /* 16 LL DD DD DD ... */
- *outlen = 2 + noctets;
- } else if (noctets < 256) {
- /* 16 81 LL DD DD DD ... */
- *outlen = 3 + noctets;
- } else if (noctets < 65536UL) {
- /* 16 82 LL LL DD DD DD ... */
- *outlen = 4 + noctets;
- } else if (noctets < 16777216UL) {
- /* 16 83 LL LL LL DD DD DD ... */
- *outlen = 5 + noctets;
- } else {
- return CRYPT_INVALID_ARG;
+ if ((err = der_length_asn1_length(noctets, &x)) != CRYPT_OK) {
+ return err;
}
+ *outlen = 1 + x + noctets;
return CRYPT_OK;
}
diff --git a/src/ltc/pk/asn1/der/integer/der_decode_integer.c b/src/ltc/pk/asn1/der/integer/der_decode_integer.c
index 88cf93f3..e5c5c122 100644
--- a/src/ltc/pk/asn1/der/integer/der_decode_integer.c
+++ b/src/ltc/pk/asn1/der/integer/der_decode_integer.c
@@ -25,7 +25,7 @@
*/
int der_decode_integer(const unsigned char *in, unsigned long inlen, void *num)
{
- unsigned long x, y, z;
+ unsigned long x, y;
int err;
LTC_ARGCHK(num != NULL);
@@ -42,45 +42,15 @@ int der_decode_integer(const unsigned char *in, unsigned long inlen, void *num)
return CRYPT_INVALID_PACKET;
}
- /* now decode the len stuff */
- z = in[x++];
-
- if ((z & 0x80) == 0x00) {
- /* short form */
-
- /* will it overflow? */
- if (x + z > inlen) {
- return CRYPT_INVALID_PACKET;
- }
-
- /* no so read it */
- if ((err = mp_read_unsigned_bin(num, (unsigned char *)in + x, z)) != CRYPT_OK) {
- return err;
- }
- } else {
- /* long form */
- z &= 0x7F;
-
- /* will number of length bytes overflow? (or > 4) */
- if (((x + z) > inlen) || (z > 4) || (z == 0)) {
- return CRYPT_INVALID_PACKET;
- }
-
- /* now read it in */
- y = 0;
- while (z--) {
- y = ((unsigned long)(in[x++])) | (y << 8);
- }
-
- /* now will reading y bytes overrun? */
- if ((x + y) > inlen) {
- return CRYPT_INVALID_PACKET;
- }
+ /* get the length of the data */
+ inlen -= x;
+ if ((err = der_decode_asn1_length(in + x, &inlen, &y)) != CRYPT_OK) {
+ return err;
+ }
+ x += inlen;
- /* no so read it */
- if ((err = mp_read_unsigned_bin(num, (unsigned char *)in + x, y)) != CRYPT_OK) {
- return err;
- }
+ if ((err = mp_read_unsigned_bin(num, (unsigned char *)in + x, y)) != CRYPT_OK) {
+ return err;
}
/* see if it's negative */
diff --git a/src/ltc/pk/asn1/der/integer/der_encode_integer.c b/src/ltc/pk/asn1/der/integer/der_encode_integer.c
index a8bada55..3bd95932 100644
--- a/src/ltc/pk/asn1/der/integer/der_encode_integer.c
+++ b/src/ltc/pk/asn1/der/integer/der_encode_integer.c
@@ -26,7 +26,7 @@
*/
int der_encode_integer(void *num, unsigned char *out, unsigned long *outlen)
{
- unsigned long tmplen, y;
+ unsigned long tmplen, y, len;
int err, leading_zero;
LTC_ARGCHK(num != NULL);
@@ -63,24 +63,11 @@ int der_encode_integer(void *num, unsigned char *out, unsigned long *outlen)
/* now store initial data */
*out++ = 0x02;
- if (y < 128) {
- /* short form */
- *out++ = (unsigned char)y;
- } else if (y < 256) {
- *out++ = 0x81;
- *out++ = (unsigned char)y;
- } else if (y < 65536UL) {
- *out++ = 0x82;
- *out++ = (unsigned char)((y>>8)&255);
- *out++ = (unsigned char)y;
- } else if (y < 16777216UL) {
- *out++ = 0x83;
- *out++ = (unsigned char)((y>>16)&255);
- *out++ = (unsigned char)((y>>8)&255);
- *out++ = (unsigned char)y;
- } else {
- return CRYPT_INVALID_ARG;
+ len = *outlen - 1;
+ if ((err = der_encode_asn1_length(y, out, &len)) != CRYPT_OK) {
+ return err;
}
+ out += len;
/* now store msbyte of zero if num is non-zero */
if (leading_zero) {
diff --git a/src/ltc/pk/asn1/der/integer/der_length_integer.c b/src/ltc/pk/asn1/der/integer/der_length_integer.c
index 753ef0e0..60daffa7 100644
--- a/src/ltc/pk/asn1/der/integer/der_length_integer.c
+++ b/src/ltc/pk/asn1/der/integer/der_length_integer.c
@@ -24,7 +24,7 @@
int der_length_integer(void *num, unsigned long *outlen)
{
unsigned long z, len;
- int leading_zero;
+ int leading_zero, err;
LTC_ARGCHK(num != NULL);
LTC_ARGCHK(outlen != NULL);
@@ -40,35 +40,21 @@ int der_length_integer(void *num, unsigned long *outlen)
}
/* size for bignum */
- z = len = leading_zero + mp_unsigned_bin_size(num);
+ len = leading_zero + mp_unsigned_bin_size(num);
} else {
/* it's negative */
/* find power of 2 that is a multiple of eight and greater than count bits */
z = mp_count_bits(num);
z = z + (8 - (z & 7));
if (((mp_cnt_lsb(num)+1)==mp_count_bits(num)) && ((mp_count_bits(num)&7)==0)) --z;
- len = z = z >> 3;
+ len = z >> 3;
}
- /* now we need a length */
- if (z < 128) {
- /* short form */
- ++len;
- } else {
- /* long form (relies on z != 0), assumes length bytes < 128 */
- ++len;
-
- while (z) {
- ++len;
- z >>= 8;
- }
+ if ((err = der_length_asn1_length(len, &z)) != CRYPT_OK) {
+ return err;
}
+ *outlen = 1 + z + len;
- /* we need a 0x02 to indicate it's INTEGER */
- ++len;
-
- /* return length */
- *outlen = len;
return CRYPT_OK;
}
diff --git a/src/ltc/pk/asn1/der/object_identifier/der_decode_object_identifier.c b/src/ltc/pk/asn1/der/object_identifier/der_decode_object_identifier.c
index c957565d..48a95473 100644
--- a/src/ltc/pk/asn1/der/object_identifier/der_decode_object_identifier.c
+++ b/src/ltc/pk/asn1/der/object_identifier/der_decode_object_identifier.c
@@ -26,6 +26,7 @@ int der_decode_object_identifier(const unsigned char *in, unsigned long inle
unsigned long *words, unsigned long *outlen)
{
unsigned long x, y, t, len;
+ int err;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(words != NULL);
@@ -38,6 +39,7 @@ int der_decode_object_identifier(const unsigned char *in, unsigned long inle
/* must be room for at least two words */
if (*outlen < 2) {
+ *outlen = 2;
return CRYPT_BUFFER_OVERFLOW;
}
@@ -47,21 +49,14 @@ int der_decode_object_identifier(const unsigned char *in, unsigned long inle
return CRYPT_INVALID_PACKET;
}
- /* get the length */
- if (in[x] < 128) {
- len = in[x++];
- } else {
- if (in[x] < 0x81 || in[x] > 0x82) {
- return CRYPT_INVALID_PACKET;
- }
- y = in[x++] & 0x7F;
- len = 0;
- while (y--) {
- len = (len << 8) | (unsigned long)in[x++];
- }
+ /* get the length of the data */
+ y = inlen - x;
+ if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) {
+ return err;
}
+ x += y;
- if (len < 1 || (len + x) > inlen) {
+ if ((len == 0) || (len > (inlen - x))) {
return CRYPT_INVALID_PACKET;
}
@@ -73,21 +68,28 @@ int der_decode_object_identifier(const unsigned char *in, unsigned long inle
if (!(in[x++] & 0x80)) {
/* store t */
if (y >= *outlen) {
- return CRYPT_BUFFER_OVERFLOW;
- }
- if (y == 0) {
- words[0] = t / 40;
- words[1] = t % 40;
- y = 2;
+ y++;
} else {
- words[y++] = t;
+ if (y == 0) {
+ words[0] = t / 40;
+ words[1] = t % 40;
+ y = 2;
+ } else {
+ words[y++] = t;
+ }
}
- t = 0;
+ t = 0;
}
}
+ if (y > *outlen) {
+ err = CRYPT_BUFFER_OVERFLOW;
+ } else {
+ err = CRYPT_OK;
+ }
+
*outlen = y;
- return CRYPT_OK;
+ return err;
}
#endif
diff --git a/src/ltc/pk/asn1/der/object_identifier/der_encode_object_identifier.c b/src/ltc/pk/asn1/der/object_identifier/der_encode_object_identifier.c
index b1ce62c9..4b397b64 100644
--- a/src/ltc/pk/asn1/der/object_identifier/der_encode_object_identifier.c
+++ b/src/ltc/pk/asn1/der/object_identifier/der_encode_object_identifier.c
@@ -55,18 +55,11 @@ int der_encode_object_identifier(unsigned long *words, unsigned long nwords,
/* store header + length */
x = 0;
out[x++] = 0x06;
- if (z < 128) {
- out[x++] = (unsigned char)z;
- } else if (z < 256) {
- out[x++] = 0x81;
- out[x++] = (unsigned char)z;
- } else if (z < 65536UL) {
- out[x++] = 0x82;
- out[x++] = (unsigned char)((z>>8)&255);
- out[x++] = (unsigned char)(z&255);
- } else {
- return CRYPT_INVALID_ARG;
+ y = *outlen - x;
+ if ((err = der_encode_asn1_length(z, out + x, &y)) != CRYPT_OK) {
+ return err;
}
+ x += y;
/* store first byte */
wordbuf = words[0] * 40 + words[1];
diff --git a/src/ltc/pk/asn1/der/octet/der_decode_octet_string.c b/src/ltc/pk/asn1/der/octet/der_decode_octet_string.c
index 02859dca..a9b3cdc5 100644
--- a/src/ltc/pk/asn1/der/octet/der_decode_octet_string.c
+++ b/src/ltc/pk/asn1/der/octet/der_decode_octet_string.c
@@ -28,6 +28,7 @@ int der_decode_octet_string(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen)
{
unsigned long x, y, len;
+ int err;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(out != NULL);
@@ -44,23 +45,12 @@ int der_decode_octet_string(const unsigned char *in, unsigned long inlen,
}
x = 1;
- /* decode the length */
- if (in[x] & 0x80) {
- /* valid # of bytes in length are 1,2,3 */
- y = in[x] & 0x7F;
- if ((y == 0) || (y > 3) || ((x + y) > inlen)) {
- return CRYPT_INVALID_PACKET;
- }
-
- /* read the length in */
- len = 0;
- ++x;
- while (y--) {
- len = (len << 8) | in[x++];
- }
- } else {
- len = in[x++] & 0x7F;
+ /* get the length of the data */
+ y = inlen - x;
+ if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) {
+ return err;
}
+ x += y;
/* is it too long? */
if (len > *outlen) {
@@ -68,7 +58,7 @@ int der_decode_octet_string(const unsigned char *in, unsigned long inlen,
return CRYPT_BUFFER_OVERFLOW;
}
- if (len + x > inlen) {
+ if (len > (inlen - x)) {
return CRYPT_INVALID_PACKET;
}
diff --git a/src/ltc/pk/asn1/der/octet/der_encode_octet_string.c b/src/ltc/pk/asn1/der/octet/der_encode_octet_string.c
index 9c9d1a65..fd79c673 100644
--- a/src/ltc/pk/asn1/der/octet/der_encode_octet_string.c
+++ b/src/ltc/pk/asn1/der/octet/der_encode_octet_string.c
@@ -48,23 +48,11 @@ int der_encode_octet_string(const unsigned char *in, unsigned long inlen,
/* encode the header+len */
x = 0;
out[x++] = 0x04;
- if (inlen < 128) {
- out[x++] = (unsigned char)inlen;
- } else if (inlen < 256) {
- out[x++] = 0x81;
- out[x++] = (unsigned char)inlen;
- } else if (inlen < 65536UL) {
- out[x++] = 0x82;
- out[x++] = (unsigned char)((inlen>>8)&255);
- out[x++] = (unsigned char)(inlen&255);
- } else if (inlen < 16777216UL) {
- out[x++] = 0x83;
- out[x++] = (unsigned char)((inlen>>16)&255);
- out[x++] = (unsigned char)((inlen>>8)&255);
- out[x++] = (unsigned char)(inlen&255);
- } else {
- return CRYPT_INVALID_ARG;
+ len = *outlen - x;
+ if ((err = der_encode_asn1_length(inlen, out + x, &len)) != CRYPT_OK) {
+ return err;
}
+ x += len;
/* store octets */
for (y = 0; y < inlen; y++) {
diff --git a/src/ltc/pk/asn1/der/octet/der_length_octet_string.c b/src/ltc/pk/asn1/der/octet/der_length_octet_string.c
index 10c9e892..9e5386a3 100644
--- a/src/ltc/pk/asn1/der/octet/der_length_octet_string.c
+++ b/src/ltc/pk/asn1/der/octet/der_length_octet_string.c
@@ -22,23 +22,15 @@
*/
int der_length_octet_string(unsigned long noctets, unsigned long *outlen)
{
+ unsigned long x;
+ int err;
+
LTC_ARGCHK(outlen != NULL);
- if (noctets < 128) {
- /* 04 LL DD DD DD ... */
- *outlen = 2 + noctets;
- } else if (noctets < 256) {
- /* 04 81 LL DD DD DD ... */
- *outlen = 3 + noctets;
- } else if (noctets < 65536UL) {
- /* 04 82 LL LL DD DD DD ... */
- *outlen = 4 + noctets;
- } else if (noctets < 16777216UL) {
- /* 04 83 LL LL LL DD DD DD ... */
- *outlen = 5 + noctets;
- } else {
- return CRYPT_INVALID_ARG;
+ if ((err = der_length_asn1_length(noctets, &x)) != CRYPT_OK) {
+ return err;
}
+ *outlen = 1 + x + noctets;
return CRYPT_OK;
}
diff --git a/src/ltc/pk/asn1/der/printable_string/der_decode_printable_string.c b/src/ltc/pk/asn1/der/printable_string/der_decode_printable_string.c
index 69474292..1ec9e3c7 100644
--- a/src/ltc/pk/asn1/der/printable_string/der_decode_printable_string.c
+++ b/src/ltc/pk/asn1/der/printable_string/der_decode_printable_string.c
@@ -28,7 +28,7 @@ int der_decode_printable_string(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen)
{
unsigned long x, y, len;
- int t;
+ int t, err;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(out != NULL);
@@ -45,23 +45,12 @@ int der_decode_printable_string(const unsigned char *in, unsigned long inlen,
}
x = 1;
- /* decode the length */
- if (in[x] & 0x80) {
- /* valid # of bytes in length are 1,2,3 */
- y = in[x] & 0x7F;
- if ((y == 0) || (y > 3) || ((x + y) > inlen)) {
- return CRYPT_INVALID_PACKET;
- }
-
- /* read the length in */
- len = 0;
- ++x;
- while (y--) {
- len = (len << 8) | in[x++];
- }
- } else {
- len = in[x++] & 0x7F;
+ /* get the length of the data */
+ y = inlen - x;
+ if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) {
+ return err;
}
+ x += y;
/* is it too long? */
if (len > *outlen) {
@@ -69,7 +58,7 @@ int der_decode_printable_string(const unsigned char *in, unsigned long inlen,
return CRYPT_BUFFER_OVERFLOW;
}
- if (len + x > inlen) {
+ if (len > (inlen - x)) {
return CRYPT_INVALID_PACKET;
}
diff --git a/src/ltc/pk/asn1/der/printable_string/der_encode_printable_string.c b/src/ltc/pk/asn1/der/printable_string/der_encode_printable_string.c
index ee54e48f..bd593916 100644
--- a/src/ltc/pk/asn1/der/printable_string/der_encode_printable_string.c
+++ b/src/ltc/pk/asn1/der/printable_string/der_encode_printable_string.c
@@ -47,23 +47,11 @@ int der_encode_printable_string(const unsigned char *in, unsigned long inlen,
/* encode the header+len */
x = 0;
out[x++] = 0x13;
- if (inlen < 128) {
- out[x++] = (unsigned char)inlen;
- } else if (inlen < 256) {
- out[x++] = 0x81;
- out[x++] = (unsigned char)inlen;
- } else if (inlen < 65536UL) {
- out[x++] = 0x82;
- out[x++] = (unsigned char)((inlen>>8)&255);
- out[x++] = (unsigned char)(inlen&255);
- } else if (inlen < 16777216UL) {
- out[x++] = 0x83;
- out[x++] = (unsigned char)((inlen>>16)&255);
- out[x++] = (unsigned char)((inlen>>8)&255);
- out[x++] = (unsigned char)(inlen&255);
- } else {
- return CRYPT_INVALID_ARG;
+ len = *outlen - x;
+ if ((err = der_encode_asn1_length(inlen, out + x, &len)) != CRYPT_OK) {
+ return err;
}
+ x += len;
/* store octets */
for (y = 0; y < inlen; y++) {
diff --git a/src/ltc/pk/asn1/der/printable_string/der_length_printable_string.c b/src/ltc/pk/asn1/der/printable_string/der_length_printable_string.c
index 40f0beb4..b6eb8502 100644
--- a/src/ltc/pk/asn1/der/printable_string/der_length_printable_string.c
+++ b/src/ltc/pk/asn1/der/printable_string/der_length_printable_string.c
@@ -126,6 +126,7 @@ int der_printable_value_decode(int v)
int der_length_printable_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen)
{
unsigned long x;
+ int err;
LTC_ARGCHK(outlen != NULL);
LTC_ARGCHK(octets != NULL);
@@ -137,21 +138,10 @@ int der_length_printable_string(const unsigned char *octets, unsigned long nocte
}
}
- if (noctets < 128) {
- /* 16 LL DD DD DD ... */
- *outlen = 2 + noctets;
- } else if (noctets < 256) {
- /* 16 81 LL DD DD DD ... */
- *outlen = 3 + noctets;
- } else if (noctets < 65536UL) {
- /* 16 82 LL LL DD DD DD ... */
- *outlen = 4 + noctets;
- } else if (noctets < 16777216UL) {
- /* 16 83 LL LL LL DD DD DD ... */
- *outlen = 5 + noctets;
- } else {
- return CRYPT_INVALID_ARG;
+ if ((err = der_length_asn1_length(noctets, &x)) != CRYPT_OK) {
+ return err;
}
+ *outlen = 1 + x + noctets;
return CRYPT_OK;
}
diff --git a/src/ltc/pk/asn1/der/sequence/der_decode_sequence_ex.c b/src/ltc/pk/asn1/der/sequence/der_decode_sequence_ex.c
index b1473819..10cfd218 100644
--- a/src/ltc/pk/asn1/der/sequence/der_decode_sequence_ex.c
+++ b/src/ltc/pk/asn1/der/sequence/der_decode_sequence_ex.c
@@ -22,317 +22,13 @@
@param inlen The size of the input
@param list The list of items to decode
@param outlen The number of items in the list
- @param ordered Search an unordeded or ordered list
+ @param flags c.f. enum ltc_der_seq
@return CRYPT_OK on success
*/
int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen,
- ltc_asn1_list *list, unsigned long outlen, int ordered)
+ ltc_asn1_list *list, unsigned long outlen, unsigned int flags)
{
- int err, i;
- ltc_asn1_type type;
- unsigned long size, x, y, z, blksize;
- void *data;
-
- LTC_ARGCHK(in != NULL);
- LTC_ARGCHK(list != NULL);
-
- /* get blk size */
- if (inlen < 2) {
- return CRYPT_INVALID_PACKET;
- }
-
- /* sequence type? We allow 0x30 SEQUENCE and 0x31 SET since fundamentally they're the same structure */
- x = 0;
- if (in[x] != 0x30 && in[x] != 0x31) {
- return CRYPT_INVALID_PACKET;
- }
- ++x;
-
- /* check if the msb is set, which signals that the
- * 7 lsb bits represent the number of bytes of the length
- */
- if (in[x] < 128) {
- blksize = in[x++];
- } else {
- if (in[x] < 0x81 || in[x] > 0x83) {
- return CRYPT_INVALID_PACKET;
- }
- y = in[x++] & 0x7F;
-
- /* would reading the len bytes overrun? */
- if (x + y > inlen) {
- return CRYPT_INVALID_PACKET;
- }
-
- /* read len */
- blksize = 0;
- while (y--) {
- blksize = (blksize << 8) | (unsigned long)in[x++];
- }
- }
-
- /* would this blksize overflow? */
- if (x + blksize > inlen) {
- return CRYPT_INVALID_PACKET;
- }
-
- /* mark all as unused */
- for (i = 0; i < (int)outlen; i++) {
- list[i].used = 0;
- }
-
- /* ok read data */
- inlen = blksize;
- for (i = 0; i < (int)outlen; i++) {
- z = 0;
- type = list[i].type;
- size = list[i].size;
- data = list[i].data;
- if (!ordered && list[i].used == 1) { continue; }
-
- if (type == LTC_ASN1_EOL) {
- break;
- }
-
- /* handle context specific tags - just skip the tag + len bytes */
- z = 0;
- if (list[i].tag > 0 && list[i].tag == in[x + z++]) {
- if (in[x+z] & 0x80) {
- y = in[x + z++] & 0x7F;
- if (y == 0 || y > 2) { return CRYPT_INVALID_PACKET; }
- z += y;
- } else {
- z++;
- }
- x += z;
- inlen -= z;
- }
-
- switch (type) {
- case LTC_ASN1_BOOLEAN:
- z = inlen;
- if ((err = der_decode_boolean(in + x, z, ((int *)data))) != CRYPT_OK) {
- if (!ordered || list[i].optional) { continue; }
- goto LBL_ERR;
- }
- if ((err = der_length_boolean(&z)) != CRYPT_OK) {
- goto LBL_ERR;
- }
- break;
-
- case LTC_ASN1_INTEGER:
- z = inlen;
- if ((err = der_decode_integer(in + x, z, data)) != CRYPT_OK) {
- if (!ordered || list[i].optional) { continue; }
- goto LBL_ERR;
- }
- if ((err = der_length_integer(data, &z)) != CRYPT_OK) {
- goto LBL_ERR;
- }
- break;
-
- case LTC_ASN1_SHORT_INTEGER:
- z = inlen;
- if ((err = der_decode_short_integer(in + x, z, data)) != CRYPT_OK) {
- if (!ordered || list[i].optional) { continue; }
- goto LBL_ERR;
- }
- if ((err = der_length_short_integer(((unsigned long*)data)[0], &z)) != CRYPT_OK) {
- goto LBL_ERR;
- }
-
- break;
-
- case LTC_ASN1_BIT_STRING:
- z = inlen;
- if ((err = der_decode_bit_string(in + x, z, data, &size)) != CRYPT_OK) {
- if (!ordered || list[i].optional) { continue; }
- goto LBL_ERR;
- }
- list[i].size = size;
- if ((err = der_length_bit_string(size, &z)) != CRYPT_OK) {
- goto LBL_ERR;
- }
- break;
-
- case LTC_ASN1_RAW_BIT_STRING:
- z = inlen;
- if ((err = der_decode_raw_bit_string(in + x, z, data, &size)) != CRYPT_OK) {
- if (!ordered || list[i].optional) { continue; }
- goto LBL_ERR;
- }
- list[i].size = size;
- if ((err = der_length_bit_string(size, &z)) != CRYPT_OK) {
- goto LBL_ERR;
- }
- break;
-
- case LTC_ASN1_OCTET_STRING:
- z = inlen;
- if ((err = der_decode_octet_string(in + x, z, data, &size)) != CRYPT_OK) {
- if (!ordered || list[i].optional) { continue; }
- goto LBL_ERR;
- }
- list[i].size = size;
- if ((err = der_length_octet_string(size, &z)) != CRYPT_OK) {
- goto LBL_ERR;
- }
- break;
-
- case LTC_ASN1_NULL:
- if (inlen < 2 || in[x] != 0x05 || in[x+1] != 0x00) {
- if (!ordered || list[i].optional) { continue; }
- err = CRYPT_INVALID_PACKET;
- goto LBL_ERR;
- }
- z = 2;
- break;
-
- case LTC_ASN1_OBJECT_IDENTIFIER:
- z = inlen;
- if ((err = der_decode_object_identifier(in + x, z, data, &size)) != CRYPT_OK) {
- if (!ordered || list[i].optional) { continue; }
- goto LBL_ERR;
- }
- list[i].size = size;
- if ((err = der_length_object_identifier(data, size, &z)) != CRYPT_OK) {
- goto LBL_ERR;
- }
- break;
-
- case LTC_ASN1_TELETEX_STRING:
- z = inlen;
- if ((err = der_decode_teletex_string(in + x, z, data, &size)) != CRYPT_OK) {
- if (!ordered || list[i].optional) { continue; }
- goto LBL_ERR;
- }
- list[i].size = size;
- if ((err = der_length_teletex_string(data, size, &z)) != CRYPT_OK) {
- goto LBL_ERR;
- }
- break;
-
- case LTC_ASN1_IA5_STRING:
- z = inlen;
- if ((err = der_decode_ia5_string(in + x, z, data, &size)) != CRYPT_OK) {
- if (!ordered || list[i].optional) { continue; }
- goto LBL_ERR;
- }
- list[i].size = size;
- if ((err = der_length_ia5_string(data, size, &z)) != CRYPT_OK) {
- goto LBL_ERR;
- }
- break;
-
-
- case LTC_ASN1_PRINTABLE_STRING:
- z = inlen;
- if ((err = der_decode_printable_string(in + x, z, data, &size)) != CRYPT_OK) {
- if (!ordered || list[i].optional) { continue; }
- goto LBL_ERR;
- }
- list[i].size = size;
- if ((err = der_length_printable_string(data, size, &z)) != CRYPT_OK) {
- goto LBL_ERR;
- }
- break;
-
- case LTC_ASN1_UTF8_STRING:
- z = inlen;
- if ((err = der_decode_utf8_string(in + x, z, data, &size)) != CRYPT_OK) {
- if (!ordered || list[i].optional) { continue; }
- goto LBL_ERR;
- }
- list[i].size = size;
- if ((err = der_length_utf8_string(data, size, &z)) != CRYPT_OK) {
- goto LBL_ERR;
- }
- break;
-
- case LTC_ASN1_UTCTIME:
- z = inlen;
- if ((err = der_decode_utctime(in + x, &z, data)) != CRYPT_OK) {
- if (!ordered || list[i].optional) { continue; }
- goto LBL_ERR;
- }
- break;
-
- case LTC_ASN1_GENERALIZEDTIME:
- z = inlen;
- if ((err = der_decode_generalizedtime(in + x, &z, data)) != CRYPT_OK) {
- if (!ordered) { continue; }
- goto LBL_ERR;
- }
- break;
-
- case LTC_ASN1_SET:
- z = inlen;
- if ((err = der_decode_set(in + x, z, data, size)) != CRYPT_OK) {
- if (!ordered || list[i].optional) { continue; }
- goto LBL_ERR;
- }
- if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) {
- goto LBL_ERR;
- }
- break;
-
- case LTC_ASN1_SETOF:
- case LTC_ASN1_SEQUENCE:
- /* detect if we have the right type */
- if ((type == LTC_ASN1_SETOF && (in[x] & 0x3F) != 0x31) || (type == LTC_ASN1_SEQUENCE && (in[x] & 0x3F) != 0x30)) {
- err = CRYPT_INVALID_PACKET;
- goto LBL_ERR;
- }
-
- z = inlen;
- if ((err = der_decode_sequence(in + x, z, data, size)) != CRYPT_OK) {
- if (!ordered || list[i].optional) { continue; }
- goto LBL_ERR;
- }
- if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) {
- goto LBL_ERR;
- }
- break;
-
-
- case LTC_ASN1_CHOICE:
- z = inlen;
- if ((err = der_decode_choice(in + x, &z, data, size)) != CRYPT_OK) {
- if (!ordered || list[i].optional) { continue; }
- goto LBL_ERR;
- }
- break;
-
- case LTC_ASN1_CONSTRUCTED:
- case LTC_ASN1_CONTEXT_SPECIFIC:
- case LTC_ASN1_EOL:
- err = CRYPT_INVALID_ARG;
- goto LBL_ERR;
- }
- x += z;
- inlen -= z;
- list[i].used = 1;
- if (!ordered) {
- /* restart the decoder */
- i = -1;
- }
- }
-
- for (i = 0; i < (int)outlen; i++) {
- if (list[i].used == 0 && list[i].optional == 0) {
- err = CRYPT_INVALID_PACKET;
- goto LBL_ERR;
- }
- }
-
- if (inlen == 0) {
- err = CRYPT_OK;
- } else {
- err = CRYPT_INPUT_TOO_LONG;
- }
-
-LBL_ERR:
- return err;
+ return der_decode_custom_type_ex(in, inlen, NULL, list, outlen, flags);
}
#endif
diff --git a/src/ltc/pk/asn1/der/sequence/der_decode_sequence_flexi.c b/src/ltc/pk/asn1/der/sequence/der_decode_sequence_flexi.c
index 142ef95a..44c9c478 100644
--- a/src/ltc/pk/asn1/der/sequence/der_decode_sequence_flexi.c
+++ b/src/ltc/pk/asn1/der/sequence/der_decode_sequence_flexi.c
@@ -15,42 +15,6 @@
#ifdef LTC_DER
-static unsigned long _fetch_length(const unsigned char *in, unsigned long inlen, unsigned long *data_offset)
-{
- unsigned long x, z;
-
- *data_offset = 0;
-
- /* skip type and read len */
- if (inlen < 2) {
- return 0xFFFFFFFF;
- }
- ++in; ++(*data_offset);
-
- /* read len */
- x = *in++; ++(*data_offset);
-
- /* <128 means literal */
- if (x < 128) {
- return x+*data_offset;
- }
- x &= 0x7F; /* the lower 7 bits are the length of the length */
- inlen -= 2;
-
- /* len means len of len! */
- if (x == 0 || x > 4 || x > inlen) {
- return 0xFFFFFFFF;
- }
-
- *data_offset += x;
- z = 0;
- while (x--) {
- z = (z<<8) | ((unsigned long)*in);
- ++in;
- }
- return z+*data_offset;
-}
-
static int _new_element(ltc_asn1_list **l)
{
/* alloc new link */
@@ -80,7 +44,7 @@ static int _new_element(ltc_asn1_list **l)
int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out)
{
ltc_asn1_list *l;
- unsigned long err, type, len, totlen, data_offset;
+ unsigned long err, identifier, len, totlen, data_offset, id_len, len_len;
void *realloc_tmp;
LTC_ARGCHK(in != NULL);
@@ -99,38 +63,77 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
/* scan the input and and get lengths and what not */
while (*inlen) {
- /* read the type byte */
- type = *in;
-
- /* fetch length */
- len = _fetch_length(in, *inlen, &data_offset);
- if (len > *inlen) {
- err = CRYPT_INVALID_PACKET;
- goto error;
- }
-
/* alloc new link */
if ((err = _new_element(&l)) != CRYPT_OK) {
goto error;
}
- if ((type & 0x20) && (type != 0x30) && (type != 0x31)) {
- /* constructed, use the 'used' field to store the original identifier */
- l->used = type;
- /* treat constructed elements like SETs */
- type = 0x20;
+ id_len = *inlen;
+ if ((err = der_decode_asn1_identifier(in, &id_len, l)) != CRYPT_OK) {
+ goto error;
}
- else if ((type & 0xC0) == 0x80) {
- /* context-specific, use the 'used' field to store the original identifier */
- l->used = type;
- /* context-specific elements are treated as opaque data */
- type = 0x80;
+ /* read the type byte */
+ identifier = *in;
+
+ if (l->type != LTC_ASN1_EOL) {
+ /* fetch length */
+ len_len = *inlen - id_len;
+#if defined(LTC_TEST_DBG)
+ data_offset = 666;
+ len = 0;
+#endif
+ if ((err = der_decode_asn1_length(&in[id_len], &len_len, &len)) != CRYPT_OK) {
+#if defined(LTC_TEST_DBG)
+ fprintf(stderr, "E1 %02lx: hl=%4lu l=%4lu - %s (%s)\n", identifier, data_offset, len, der_asn1_tag_to_string_map[l->tag], error_to_string(err));
+#endif
+ goto error;
+ } else if (len > (*inlen - id_len - len_len)) {
+ err = CRYPT_INVALID_PACKET;
+#if defined(LTC_TEST_DBG)
+ fprintf(stderr, "E2 %02lx: hl=%4lu l=%4lu - %s (%s)\n", identifier, data_offset, len, der_asn1_tag_to_string_map[l->tag], error_to_string(err));
+#endif
+ goto error;
+ }
+ data_offset = id_len + len_len;
+#if defined(LTC_TEST_DBG) && LTC_TEST_DBG > 1
+ if (l->type == LTC_ASN1_CUSTOM_TYPE && l->class == LTC_ASN1_CL_CONTEXT_SPECIFIC) {
+ fprintf(stderr, "OK %02lx: hl=%4lu l=%4lu - Context Specific[%s %llu]\n", identifier, data_offset, len, der_asn1_pc_to_string_map[l->pc], l->tag);
+ } else {
+ fprintf(stderr, "OK %02lx: hl=%4lu l=%4lu - %s\n", identifier, data_offset, len, der_asn1_tag_to_string_map[l->tag]);
+ }
+#endif
+ len += data_offset;
+
+ if (l->type == LTC_ASN1_CUSTOM_TYPE) {
+ /* Custom type, use the 'used' field to store the original identifier */
+ l->used = identifier;
+ if (l->pc == LTC_ASN1_PC_CONSTRUCTED) {
+ /* treat constructed elements like SEQUENCEs */
+ identifier = 0x20;
+ } else {
+ /* primitive elements are treated as opaque data */
+ identifier = 0x80;
+ }
+ }
+ } else {
+ /* Init this so gcc won't complain,
+ * as this case will only be hit when we
+ * can't decode the identifier so the
+ * switch-case should go to default anyway...
+ */
+ data_offset = 0;
+ len = 0;
}
/* now switch on type */
- switch (type) {
+ switch (identifier) {
case 0x01: /* BOOLEAN */
- l->type = LTC_ASN1_BOOLEAN;
+ if (l->type != LTC_ASN1_BOOLEAN) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
+
+ /* init field */
l->size = 1;
l->data = XCALLOC(1, sizeof(int));
@@ -144,8 +147,12 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
break;
case 0x02: /* INTEGER */
+ if (l->type != LTC_ASN1_INTEGER) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
+
/* init field */
- l->type = LTC_ASN1_INTEGER;
l->size = 1;
if ((err = mp_init(&l->data)) != CRYPT_OK) {
goto error;
@@ -163,8 +170,12 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
break;
case 0x03: /* BIT */
+ if (l->type != LTC_ASN1_BIT_STRING) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
+
/* init field */
- l->type = LTC_ASN1_BIT_STRING;
l->size = len * 8; /* *8 because we store decoded bits one per char and they are encoded 8 per char. */
if ((l->data = XCALLOC(1, l->size)) == NULL) {
@@ -182,9 +193,12 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
break;
case 0x04: /* OCTET */
+ if (l->type != LTC_ASN1_OCTET_STRING) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
/* init field */
- l->type = LTC_ASN1_OCTET_STRING;
l->size = len;
if ((l->data = XCALLOC(1, l->size)) == NULL) {
@@ -202,6 +216,10 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
break;
case 0x05: /* NULL */
+ if (l->type != LTC_ASN1_NULL) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
/* valid NULL is 0x05 0x00 */
if (in[0] != 0x05 || in[1] != 0x00) {
@@ -210,7 +228,6 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
}
/* simple to store ;-) */
- l->type = LTC_ASN1_NULL;
l->data = NULL;
l->size = 0;
len = 2;
@@ -218,9 +235,12 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
break;
case 0x06: /* OID */
+ if (l->type != LTC_ASN1_OBJECT_IDENTIFIER) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
/* init field */
- l->type = LTC_ASN1_OBJECT_IDENTIFIER;
l->size = len;
if ((l->data = XCALLOC(len, sizeof(unsigned long))) == NULL) {
@@ -247,7 +267,10 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
case 0x0C: /* UTF8 */
/* init field */
- l->type = LTC_ASN1_UTF8_STRING;
+ if (l->type != LTC_ASN1_UTF8_STRING) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
l->size = len;
if ((l->data = XCALLOC(sizeof(wchar_t), l->size)) == NULL) {
@@ -265,9 +288,12 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
break;
case 0x13: /* PRINTABLE */
+ if (l->type != LTC_ASN1_PRINTABLE_STRING) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
/* init field */
- l->type = LTC_ASN1_PRINTABLE_STRING;
l->size = len;
if ((l->data = XCALLOC(1, l->size)) == NULL) {
@@ -285,9 +311,12 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
break;
case 0x14: /* TELETEXT */
+ if (l->type != LTC_ASN1_TELETEX_STRING) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
/* init field */
- l->type = LTC_ASN1_TELETEX_STRING;
l->size = len;
if ((l->data = XCALLOC(1, l->size)) == NULL) {
@@ -305,9 +334,12 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
break;
case 0x16: /* IA5 */
+ if (l->type != LTC_ASN1_IA5_STRING) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
/* init field */
- l->type = LTC_ASN1_IA5_STRING;
l->size = len;
if ((l->data = XCALLOC(1, l->size)) == NULL) {
@@ -325,9 +357,12 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
break;
case 0x17: /* UTC TIME */
+ if (l->type != LTC_ASN1_UTCTIME) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
/* init field */
- l->type = LTC_ASN1_UTCTIME;
l->size = 1;
if ((l->data = XCALLOC(1, sizeof(ltc_utctime))) == NULL) {
@@ -346,7 +381,12 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
break;
case 0x18:
- l->type = LTC_ASN1_GENERALIZEDTIME;
+ if (l->type != LTC_ASN1_GENERALIZEDTIME) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
+
+ /* init field */
l->size = len;
if ((l->data = XCALLOC(1, sizeof(ltc_generalizedtime))) == NULL) {
@@ -369,14 +409,23 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
case 0x31: /* SET */
/* init field */
- if (type == 0x20) {
- l->type = LTC_ASN1_CONSTRUCTED;
+ if (identifier == 0x20) {
+ if (l->type != LTC_ASN1_CUSTOM_TYPE) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
}
- else if (type == 0x30) {
- l->type = LTC_ASN1_SEQUENCE;
+ else if (identifier == 0x30) {
+ if (l->type != LTC_ASN1_SEQUENCE) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
}
else {
- l->type = LTC_ASN1_SET;
+ if (l->type != LTC_ASN1_SET) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
}
if ((l->data = XMALLOC(len)) == NULL) {
@@ -391,12 +440,19 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
/* jump to the start of the data */
in += data_offset;
*inlen -= data_offset;
- len = len - data_offset;
+ len -= data_offset;
+
+ /* save the decoded ASN.1 len */
+ len_len = len;
/* Sequence elements go as child */
if ((err = der_decode_sequence_flexi(in, &len, &(l->child))) != CRYPT_OK) {
goto error;
}
+ if (len_len != len) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
/* len update */
totlen += data_offset;
@@ -410,7 +466,10 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
break;
case 0x80: /* Context-specific */
- l->type = LTC_ASN1_CONTEXT_SPECIFIC;
+ if (l->type != LTC_ASN1_CUSTOM_TYPE) {
+ err = CRYPT_PK_ASN1_ERROR;
+ goto error;
+ }
if ((l->data = XCALLOC(1, len - data_offset)) == NULL) {
err = CRYPT_MEM;
diff --git a/src/ltc/pk/asn1/der/sequence/der_decode_sequence_multi.c b/src/ltc/pk/asn1/der/sequence/der_decode_sequence_multi.c
index 1361b761..280d7cdb 100644
--- a/src/ltc/pk/asn1/der/sequence/der_decode_sequence_multi.c
+++ b/src/ltc/pk/asn1/der/sequence/der_decode_sequence_multi.c
@@ -21,27 +21,27 @@
Decode a SEQUENCE type using a VA list
@param in Input buffer
@param inlen Length of input in octets
- @remark <...> is of the form <type, size, data> (int, unsigned long, void*)
+ @param a1 Initialized argument list #1
+ @param a2 Initialized argument list #2 (copy of #1)
+ @param flags c.f. enum ltc_der_seq
@return CRYPT_OK on success
*/
-int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
+static int _der_decode_sequence_va(const unsigned char *in, unsigned long inlen, va_list a1, va_list a2, unsigned int flags)
{
int err;
ltc_asn1_type type;
unsigned long size, x;
void *data;
- va_list args;
ltc_asn1_list *list;
LTC_ARGCHK(in != NULL);
/* get size of output that will be required */
- va_start(args, inlen);
x = 0;
for (;;) {
- type = (ltc_asn1_type)va_arg(args, int);
- size = va_arg(args, unsigned long);
- data = va_arg(args, void*);
+ type = (ltc_asn1_type)va_arg(a1, int);
+ size = va_arg(a1, unsigned long);
+ data = va_arg(a1, void*);
LTC_UNUSED_PARAM(size);
LTC_UNUSED_PARAM(data);
@@ -72,13 +72,10 @@ int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
break;
case LTC_ASN1_EOL:
- case LTC_ASN1_CONSTRUCTED:
- case LTC_ASN1_CONTEXT_SPECIFIC:
- va_end(args);
+ case LTC_ASN1_CUSTOM_TYPE:
return CRYPT_INVALID_ARG;
}
}
- va_end(args);
/* allocate structure for x elements */
if (x == 0) {
@@ -91,12 +88,11 @@ int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
}
/* fill in the structure */
- va_start(args, inlen);
x = 0;
for (;;) {
- type = (ltc_asn1_type)va_arg(args, int);
- size = va_arg(args, unsigned long);
- data = va_arg(args, void*);
+ type = (ltc_asn1_type)va_arg(a2, int);
+ size = va_arg(a2, unsigned long);
+ data = va_arg(a2, void*);
if (type == LTC_ASN1_EOL) {
break;
@@ -125,18 +121,67 @@ int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
break;
/* coverity[dead_error_line] */
case LTC_ASN1_EOL:
- case LTC_ASN1_CONSTRUCTED:
- case LTC_ASN1_CONTEXT_SPECIFIC:
+ case LTC_ASN1_CUSTOM_TYPE:
break;
}
}
- va_end(args);
- err = der_decode_sequence(in, inlen, list, x);
+ err = der_decode_sequence_ex(in, inlen, list, x, flags);
XFREE(list);
return err;
}
+/**
+ Decode a SEQUENCE type using a VA list
+ @param in Input buffer
+ @param inlen Length of input in octets
+ @remark <...> is of the form <type, size, data> (int, unsigned long, void*)
+ @return CRYPT_OK on success
+*/
+int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
+{
+ va_list a1, a2;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+
+ va_start(a1, inlen);
+ va_start(a2, inlen);
+
+ err = _der_decode_sequence_va(in, inlen, a1, a2, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_RELAXED);
+
+ va_end(a2);
+ va_end(a1);
+
+ return err;
+}
+
+/**
+ Decode a SEQUENCE type using a VA list
+ @param in Input buffer
+ @param inlen Length of input in octets
+ @param flags c.f. enum ltc_der_seq
+ @remark <...> is of the form <type, size, data> (int, unsigned long, void*)
+ @return CRYPT_OK on success
+*/
+int der_decode_sequence_multi_ex(const unsigned char *in, unsigned long inlen, unsigned int flags, ...)
+{
+ va_list a1, a2;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+
+ va_start(a1, flags);
+ va_start(a2, flags);
+
+ err = _der_decode_sequence_va(in, inlen, a1, a2, flags);
+
+ va_end(a2);
+ va_end(a1);
+
+ return err;
+}
+
#endif
diff --git a/src/ltc/pk/asn1/der/sequence/der_encode_sequence_ex.c b/src/ltc/pk/asn1/der/sequence/der_encode_sequence_ex.c
index d8ad196c..1a5d9681 100644
--- a/src/ltc/pk/asn1/der/sequence/der_encode_sequence_ex.c
+++ b/src/ltc/pk/asn1/der/sequence/der_encode_sequence_ex.c
@@ -31,7 +31,6 @@ int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
int err;
ltc_asn1_type type;
unsigned long size, x, y, z, i;
- unsigned char tmptag[6];
void *data;
LTC_ARGCHK(list != NULL);
@@ -53,21 +52,11 @@ int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
x = 0;
out[x++] = (type_of == LTC_ASN1_SEQUENCE) ? 0x30 : 0x31;
- if (z < 128) {
- out[x++] = (unsigned char)z;
- } else if (z < 256) {
- out[x++] = 0x81;
- out[x++] = (unsigned char)z;
- } else if (z < 65536UL) {
- out[x++] = 0x82;
- out[x++] = (unsigned char)((z>>8UL)&255);
- out[x++] = (unsigned char)(z&255);
- } else if (z < 16777216UL) {
- out[x++] = 0x83;
- out[x++] = (unsigned char)((z>>16UL)&255);
- out[x++] = (unsigned char)((z>>8UL)&255);
- out[x++] = (unsigned char)(z&255);
+ y = *outlen - x;
+ if ((err = der_encode_asn1_length(z, &out[x], &y)) != CRYPT_OK) {
+ goto LBL_ERR;
}
+ x += y;
/* store data */
*outlen -= x;
@@ -192,43 +181,20 @@ int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
}
break;
+ case LTC_ASN1_CUSTOM_TYPE:
+ z = *outlen;
+ if ((err = der_encode_custom_type(&list[i], out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
case LTC_ASN1_CHOICE:
- case LTC_ASN1_CONSTRUCTED:
- case LTC_ASN1_CONTEXT_SPECIFIC:
case LTC_ASN1_EOL:
case LTC_ASN1_TELETEX_STRING:
err = CRYPT_INVALID_ARG;
goto LBL_ERR;
}
- if (list[i].tag > 0) {
- tmptag[0] = list[i].tag;
- y = 0;
- if (z < 128) {
- tmptag[1] = (unsigned char)z;
- y = 2;
- } else if (z < 256) {
- tmptag[1] = 0x81;
- tmptag[2] = (unsigned char)z;
- y = 3;
- } else if (z < 65536UL) {
- tmptag[1] = 0x82;
- tmptag[2] = (unsigned char)((z>>8UL)&255);
- tmptag[3] = (unsigned char)(z&255);
- y = 4;
- } else if (z < 16777216UL) {
- tmptag[1] = 0x83;
- tmptag[2] = (unsigned char)((z>>16UL)&255);
- tmptag[3] = (unsigned char)((z>>8UL)&255);
- tmptag[4] = (unsigned char)(z&255);
- y = 5;
- }
- XMEMMOVE(out + x + y, out + x, z);
- XMEMCPY(out + x, tmptag, y);
-
- z += y;
- }
-
x += z;
*outlen -= z;
}
diff --git a/src/ltc/pk/asn1/der/sequence/der_encode_sequence_multi.c b/src/ltc/pk/asn1/der/sequence/der_encode_sequence_multi.c
index c1b40c77..c8ec59a9 100644
--- a/src/ltc/pk/asn1/der/sequence/der_encode_sequence_multi.c
+++ b/src/ltc/pk/asn1/der/sequence/der_encode_sequence_multi.c
@@ -71,8 +71,7 @@ int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...)
break;
case LTC_ASN1_CHOICE:
- case LTC_ASN1_CONSTRUCTED:
- case LTC_ASN1_CONTEXT_SPECIFIC:
+ case LTC_ASN1_CUSTOM_TYPE:
case LTC_ASN1_EOL:
case LTC_ASN1_TELETEX_STRING:
va_end(args);
@@ -124,8 +123,7 @@ int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...)
break;
case LTC_ASN1_CHOICE:
- case LTC_ASN1_CONSTRUCTED:
- case LTC_ASN1_CONTEXT_SPECIFIC:
+ case LTC_ASN1_CUSTOM_TYPE:
case LTC_ASN1_EOL:
case LTC_ASN1_TELETEX_STRING:
va_end(args);
diff --git a/src/ltc/pk/asn1/der/sequence/der_length_sequence.c b/src/ltc/pk/asn1/der/sequence/der_length_sequence.c
index 7908c5b3..a80f96b0 100644
--- a/src/ltc/pk/asn1/der/sequence/der_length_sequence.c
+++ b/src/ltc/pk/asn1/der/sequence/der_length_sequence.c
@@ -33,7 +33,7 @@ int der_length_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
{
int err;
ltc_asn1_type type;
- unsigned long size, x, y, i, z;
+ unsigned long size, x, y, i;
void *data;
LTC_ARGCHK(list != NULL);
@@ -143,6 +143,13 @@ int der_length_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
y += x;
break;
+ case LTC_ASN1_CUSTOM_TYPE:
+ if ((err = der_length_custom_type(&list[i], &x, NULL)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
case LTC_ASN1_SET:
case LTC_ASN1_SETOF:
case LTC_ASN1_SEQUENCE:
@@ -152,53 +159,23 @@ int der_length_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
y += x;
break;
-
case LTC_ASN1_CHOICE:
- case LTC_ASN1_CONSTRUCTED:
- case LTC_ASN1_CONTEXT_SPECIFIC:
case LTC_ASN1_EOL:
err = CRYPT_INVALID_ARG;
goto LBL_ERR;
}
-
- /* handle context specific tags size */
- if (list[i].tag > 0) {
- if (x < 128) {
- y += 2;
- } else if (x < 256) {
- y += 3;
- } else if (x < 65536UL) {
- y += 4;
- } else if (x < 16777216UL) {
- y += 5;
- } else {
- err = CRYPT_INVALID_ARG;
- goto LBL_ERR;
- }
- }
}
- /* calc header size */
- z = y;
- if (y < 128) {
- y += 2;
- } else if (y < 256) {
- /* 0x30 0x81 LL */
- y += 3;
- } else if (y < 65536UL) {
- /* 0x30 0x82 LL LL */
- y += 4;
- } else if (y < 16777216UL) {
- /* 0x30 0x83 LL LL LL */
- y += 5;
- } else {
- err = CRYPT_INVALID_ARG;
+ if ((err = der_length_asn1_length(y, &x)) != CRYPT_OK) {
goto LBL_ERR;
}
+ if (payloadlen != NULL) {
+ *payloadlen = y;
+ }
+
/* store size */
- if (payloadlen) *payloadlen = z;
- *outlen = y;
+ *outlen = y + x + 1;
err = CRYPT_OK;
LBL_ERR:
diff --git a/src/ltc/pk/asn1/der/sequence/der_sequence_shrink.c b/src/ltc/pk/asn1/der/sequence/der_sequence_shrink.c
index 9b9e036a..fdfe91bb 100644
--- a/src/ltc/pk/asn1/der/sequence/der_sequence_shrink.c
+++ b/src/ltc/pk/asn1/der/sequence/der_sequence_shrink.c
@@ -32,7 +32,7 @@ void der_sequence_shrink(ltc_asn1_list *in)
}
switch (in->type) {
- case LTC_ASN1_CONSTRUCTED:
+ case LTC_ASN1_CUSTOM_TYPE:
case LTC_ASN1_SET:
case LTC_ASN1_SEQUENCE : if (in->data != NULL) { XFREE(in->data); in->data = NULL; } break;
default: break;
diff --git a/src/ltc/pk/asn1/der/set/der_encode_set.c b/src/ltc/pk/asn1/der/set/der_encode_set.c
index fef3092b..a3485f2d 100644
--- a/src/ltc/pk/asn1/der/set/der_encode_set.c
+++ b/src/ltc/pk/asn1/der/set/der_encode_set.c
@@ -18,30 +18,7 @@
/* LTC define to ASN.1 TAG */
static int _ltc_to_asn1(ltc_asn1_type v)
{
- switch (v) {
- case LTC_ASN1_BOOLEAN: return 0x01;
- case LTC_ASN1_INTEGER:
- case LTC_ASN1_SHORT_INTEGER: return 0x02;
- case LTC_ASN1_RAW_BIT_STRING:
- case LTC_ASN1_BIT_STRING: return 0x03;
- case LTC_ASN1_OCTET_STRING: return 0x04;
- case LTC_ASN1_NULL: return 0x05;
- case LTC_ASN1_OBJECT_IDENTIFIER: return 0x06;
- case LTC_ASN1_UTF8_STRING: return 0x0C;
- case LTC_ASN1_PRINTABLE_STRING: return 0x13;
- case LTC_ASN1_TELETEX_STRING: return 0x14;
- case LTC_ASN1_IA5_STRING: return 0x16;
- case LTC_ASN1_UTCTIME: return 0x17;
- case LTC_ASN1_GENERALIZEDTIME: return 0x18;
- case LTC_ASN1_SEQUENCE: return 0x30;
- case LTC_ASN1_SET:
- case LTC_ASN1_SETOF: return 0x31;
- case LTC_ASN1_CHOICE:
- case LTC_ASN1_CONSTRUCTED:
- case LTC_ASN1_CONTEXT_SPECIFIC:
- case LTC_ASN1_EOL: return -1;
- }
- return -1;
+ return der_asn1_type_to_identifier_map[v];
}
diff --git a/src/ltc/pk/asn1/der/short_integer/der_length_short_integer.c b/src/ltc/pk/asn1/der/short_integer/der_length_short_integer.c
index 52d0e1ae..8c1de289 100644
--- a/src/ltc/pk/asn1/der/short_integer/der_length_short_integer.c
+++ b/src/ltc/pk/asn1/der/short_integer/der_length_short_integer.c
@@ -23,7 +23,8 @@
*/
int der_length_short_integer(unsigned long num, unsigned long *outlen)
{
- unsigned long z, y, len;
+ unsigned long z, y;
+ int err;
LTC_ARGCHK(outlen != NULL);
@@ -41,22 +42,15 @@ int der_length_short_integer(unsigned long num, unsigned long *outlen)
/* handle zero */
if (z == 0) {
z = 1;
+ } else if ((num&(1UL<<((z<<3) - 1))) != 0) {
+ /* in case msb is set */
+ ++z;
}
- /* we need a 0x02 to indicate it's INTEGER */
- len = 1;
-
- /* length byte */
- ++len;
-
- /* bytes in value */
- len += z;
-
- /* see if msb is set */
- len += (num&(1UL<<((z<<3) - 1))) ? 1 : 0;
-
- /* return length */
- *outlen = len;
+ if ((err = der_length_asn1_length(z, &y)) != CRYPT_OK) {
+ return err;
+ }
+ *outlen = 1 + y + z;
return CRYPT_OK;
}
diff --git a/src/ltc/pk/asn1/der/teletex_string/der_decode_teletex_string.c b/src/ltc/pk/asn1/der/teletex_string/der_decode_teletex_string.c
index 0c7c3c8f..cd530a2b 100644
--- a/src/ltc/pk/asn1/der/teletex_string/der_decode_teletex_string.c
+++ b/src/ltc/pk/asn1/der/teletex_string/der_decode_teletex_string.c
@@ -27,7 +27,7 @@ int der_decode_teletex_string(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen)
{
unsigned long x, y, len;
- int t;
+ int t, err;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(out != NULL);
@@ -44,23 +44,12 @@ int der_decode_teletex_string(const unsigned char *in, unsigned long inlen,
}
x = 1;
- /* decode the length */
- if (in[x] & 0x80) {
- /* valid # of bytes in length are 1,2,3 */
- y = in[x] & 0x7F;
- if ((y == 0) || (y > 3) || ((x + y) > inlen)) {
- return CRYPT_INVALID_PACKET;
- }
-
- /* read the length in */
- len = 0;
- ++x;
- while (y--) {
- len = (len << 8) | in[x++];
- }
- } else {
- len = in[x++] & 0x7F;
+ /* get the length of the data */
+ y = inlen - x;
+ if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) {
+ return err;
}
+ x += y;
/* is it too long? */
if (len > *outlen) {
@@ -68,7 +57,7 @@ int der_decode_teletex_string(const unsigned char *in, unsigned long inlen,
return CRYPT_BUFFER_OVERFLOW;
}
- if (len + x > inlen) {
+ if (len > (inlen - x)) {
return CRYPT_INVALID_PACKET;
}
diff --git a/src/ltc/pk/asn1/der/teletex_string/der_length_teletex_string.c b/src/ltc/pk/asn1/der/teletex_string/der_length_teletex_string.c
index 29fe5b0b..a35c6d76 100644
--- a/src/ltc/pk/asn1/der/teletex_string/der_length_teletex_string.c
+++ b/src/ltc/pk/asn1/der/teletex_string/der_length_teletex_string.c
@@ -170,6 +170,7 @@ int der_teletex_value_decode(int v)
int der_length_teletex_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen)
{
unsigned long x;
+ int err;
LTC_ARGCHK(outlen != NULL);
LTC_ARGCHK(octets != NULL);
@@ -181,21 +182,10 @@ int der_length_teletex_string(const unsigned char *octets, unsigned long noctets
}
}
- if (noctets < 128) {
- /* 16 LL DD DD DD ... */
- *outlen = 2 + noctets;
- } else if (noctets < 256) {
- /* 16 81 LL DD DD DD ... */
- *outlen = 3 + noctets;
- } else if (noctets < 65536UL) {
- /* 16 82 LL LL DD DD DD ... */
- *outlen = 4 + noctets;
- } else if (noctets < 16777216UL) {
- /* 16 83 LL LL LL DD DD DD ... */
- *outlen = 5 + noctets;
- } else {
- return CRYPT_INVALID_ARG;
+ if ((err = der_length_asn1_length(noctets, &x)) != CRYPT_OK) {
+ return err;
}
+ *outlen = 1 + x + noctets;
return CRYPT_OK;
}
diff --git a/src/ltc/pk/asn1/der/utf8/der_decode_utf8_string.c b/src/ltc/pk/asn1/der/utf8/der_decode_utf8_string.c
index d857ce95..c86d6603 100644
--- a/src/ltc/pk/asn1/der/utf8/der_decode_utf8_string.c
+++ b/src/ltc/pk/asn1/der/utf8/der_decode_utf8_string.c
@@ -29,6 +29,7 @@ int der_decode_utf8_string(const unsigned char *in, unsigned long inlen,
{
wchar_t tmp;
unsigned long x, y, z, len;
+ int err;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(out != NULL);
@@ -45,25 +46,14 @@ int der_decode_utf8_string(const unsigned char *in, unsigned long inlen,
}
x = 1;
- /* decode the length */
- if (in[x] & 0x80) {
- /* valid # of bytes in length are 1,2,3 */
- y = in[x] & 0x7F;
- if ((y == 0) || (y > 3) || ((x + y) > inlen)) {
- return CRYPT_INVALID_PACKET;
- }
-
- /* read the length in */
- len = 0;
- ++x;
- while (y--) {
- len = (len << 8) | in[x++];
- }
- } else {
- len = in[x++] & 0x7F;
+ /* get the length of the data */
+ y = inlen - x;
+ if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) {
+ return err;
}
+ x += y;
- if (len + x > inlen) {
+ if (len > (inlen - x)) {
return CRYPT_INVALID_PACKET;
}
@@ -91,15 +81,19 @@ int der_decode_utf8_string(const unsigned char *in, unsigned long inlen,
tmp = (tmp << 6) | ((wchar_t)in[x++] & 0x3F);
}
- if (y > *outlen) {
- *outlen = y;
- return CRYPT_BUFFER_OVERFLOW;
+ if (y < *outlen) {
+ out[y] = tmp;
}
- out[y++] = tmp;
+ y++;
+ }
+ if (y > *outlen) {
+ err = CRYPT_BUFFER_OVERFLOW;
+ } else {
+ err = CRYPT_OK;
}
*outlen = y;
- return CRYPT_OK;
+ return err;
}
#endif
diff --git a/src/ltc/pk/asn1/der/utf8/der_encode_utf8_string.c b/src/ltc/pk/asn1/der/utf8/der_encode_utf8_string.c
index 63ad840f..1c6e09b5 100644
--- a/src/ltc/pk/asn1/der/utf8/der_encode_utf8_string.c
+++ b/src/ltc/pk/asn1/der/utf8/der_encode_utf8_string.c
@@ -28,6 +28,7 @@ int der_encode_utf8_string(const wchar_t *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen)
{
unsigned long x, y, len;
+ int err;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(out != NULL);
@@ -38,46 +39,26 @@ int der_encode_utf8_string(const wchar_t *in, unsigned long inlen,
if (!der_utf8_valid_char(in[x])) return CRYPT_INVALID_ARG;
len += der_utf8_charsize(in[x]);
}
-
- if (len < 128) {
- y = 2 + len;
- } else if (len < 256) {
- y = 3 + len;
- } else if (len < 65536UL) {
- y = 4 + len;
- } else if (len < 16777216UL) {
- y = 5 + len;
- } else {
- return CRYPT_INVALID_ARG;
+ if ((err = der_length_asn1_length(len, &x)) != CRYPT_OK) {
+ return err;
}
+ x += len + 1;
/* too big? */
- if (y > *outlen) {
- *outlen = len;
+ if (x > *outlen) {
+ *outlen = x;
return CRYPT_BUFFER_OVERFLOW;
}
/* encode the header+len */
x = 0;
out[x++] = 0x0C;
- if (len < 128) {
- out[x++] = (unsigned char)len;
- } else if (len < 256) {
- out[x++] = 0x81;
- out[x++] = (unsigned char)len;
- } else if (len < 65536UL) {
- out[x++] = 0x82;
- out[x++] = (unsigned char)((len>>8)&255);
- out[x++] = (unsigned char)(len&255);
- } else if (len < 16777216UL) {
- out[x++] = 0x83;
- out[x++] = (unsigned char)((len>>16)&255);
- out[x++] = (unsigned char)((len>>8)&255);
- out[x++] = (unsigned char)(len&255);
- } else {
- /* coverity[dead_error_line] */
- return CRYPT_INVALID_ARG;
+
+ y = *outlen - x;
+ if ((err = der_encode_asn1_length(len, out + x, &y)) != CRYPT_OK) {
+ return err;
}
+ x += y;
/* store UTF8 */
for (y = 0; y < inlen; y++) {
@@ -91,7 +72,7 @@ int der_encode_utf8_string(const wchar_t *in, unsigned long inlen,
}
}
- /* retun length */
+ /* return length */
*outlen = x;
return CRYPT_OK;
diff --git a/src/ltc/pk/asn1/der/utf8/der_length_utf8_string.c b/src/ltc/pk/asn1/der/utf8/der_length_utf8_string.c
index 88f4355e..b4292846 100644
--- a/src/ltc/pk/asn1/der/utf8/der_length_utf8_string.c
+++ b/src/ltc/pk/asn1/der/utf8/der_length_utf8_string.c
@@ -65,6 +65,7 @@ int der_utf8_valid_char(const wchar_t c)
int der_length_utf8_string(const wchar_t *in, unsigned long noctets, unsigned long *outlen)
{
unsigned long x, len;
+ int err;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(outlen != NULL);
@@ -75,21 +76,10 @@ int der_length_utf8_string(const wchar_t *in, unsigned long noctets, unsigned lo
len += der_utf8_charsize(in[x]);
}
- if (len < 128) {
- /* 0C LL DD DD DD ... */
- *outlen = 2 + len;
- } else if (len < 256) {
- /* 0C 81 LL DD DD DD ... */
- *outlen = 3 + len;
- } else if (len < 65536UL) {
- /* 0C 82 LL LL DD DD DD ... */
- *outlen = 4 + len;
- } else if (len < 16777216UL) {
- /* 0C 83 LL LL LL DD DD DD ... */
- *outlen = 5 + len;
- } else {
- return CRYPT_INVALID_ARG;
+ if ((err = der_length_asn1_length(len, &x)) != CRYPT_OK) {
+ return err;
}
+ *outlen = 1 + x + len;
return CRYPT_OK;
}
diff --git a/src/ltc/pk/asn1/der/sequence/der_decode_subject_public_key_info.c b/src/ltc/pk/asn1/x509/x509_decode_subject_public_key_info.c
index 51bf37c5..c68b4a3b 100644
--- a/src/ltc/pk/asn1/der/sequence/der_decode_subject_public_key_info.c
+++ b/src/ltc/pk/asn1/x509/x509_decode_subject_public_key_info.c
@@ -7,9 +7,10 @@
* guarantee it works.
*/
#include "tomcrypt.h"
+
/**
- @file der_decode_subject_public_key_info.c
- ASN.1 DER, encode a Subject Public Key structure --nmav
+ @file x509_decode_subject_public_key_info.c
+ ASN.1 DER/X.509, encode a SubjectPublicKeyInfo structure --nmav
*/
#ifdef LTC_DER
@@ -25,7 +26,7 @@
* }
*/
/**
- Decode a subject public key info
+ Decode a SubjectPublicKeyInfo
@param in The input buffer
@param inlen The length of the input buffer
@param algorithm One out of the enum #public_key_algorithms
@@ -33,21 +34,12 @@
@param public_key_len [in/out] The length of the public key buffer and the written length
@param parameters_type The parameters' type out of the enum ltc_asn1_type
@param parameters The parameters to include
- @param parameters_len The number of parameters to include
+ @param parameters_len [in/out]The number of parameters to include
@return CRYPT_OK on success
*/
-int der_decode_subject_public_key_info(const unsigned char *in, unsigned long inlen,
- unsigned int algorithm, void* public_key, unsigned long* public_key_len,
- unsigned long parameters_type, ltc_asn1_list* parameters, unsigned long parameters_len)
-{
- return der_decode_subject_public_key_info_ex(in, inlen, algorithm, public_key, public_key_len,
- parameters_type, parameters, parameters_len, NULL);
-}
-
-int der_decode_subject_public_key_info_ex(const unsigned char *in, unsigned long inlen,
+int x509_decode_subject_public_key_info(const unsigned char *in, unsigned long inlen,
unsigned int algorithm, void* public_key, unsigned long* public_key_len,
- unsigned long parameters_type, void* parameters, unsigned long parameters_len,
- unsigned long *parameters_outsize)
+ unsigned long parameters_type, void* parameters, unsigned long *parameters_len)
{
int err;
unsigned long len;
@@ -60,6 +52,7 @@ int der_decode_subject_public_key_info_ex(const unsigned char *in, unsigned long
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(inlen != 0);
LTC_ARGCHK(public_key_len != NULL);
+ LTC_ARGCHK(parameters_len != NULL);
err = pk_get_oid(algorithm, &oid);
if (err != CRYPT_OK) {
@@ -75,7 +68,7 @@ int der_decode_subject_public_key_info_ex(const unsigned char *in, unsigned long
/* this includes the internal hash ID and optional params (NULL in this case) */
LTC_SET_ASN1(alg_id, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, sizeof(tmpoid)/sizeof(tmpoid[0]));
- LTC_SET_ASN1(alg_id, 1, (ltc_asn1_type)parameters_type, parameters, parameters_len);
+ LTC_SET_ASN1(alg_id, 1, (ltc_asn1_type)parameters_type, parameters, *parameters_len);
/* the actual format of the SSL DER key is odd, it stores a RSAPublicKey
* in a **BIT** string ... so we have to extract it then proceed to convert bit to octet
@@ -88,7 +81,7 @@ int der_decode_subject_public_key_info_ex(const unsigned char *in, unsigned long
goto LBL_ERR;
}
- if (parameters_outsize) *parameters_outsize = alg_id[1].size;
+ *parameters_len = alg_id[1].size;
if ((alg_id[0].size != oid.OIDlen) ||
XMEMCMP(oid.OID, alg_id[0].data, oid.OIDlen * sizeof(oid.OID[0]))) {
diff --git a/src/ltc/pk/asn1/der/sequence/der_encode_subject_public_key_info.c b/src/ltc/pk/asn1/x509/x509_encode_subject_public_key_info.c
index dcb869a9..8148a185 100644
--- a/src/ltc/pk/asn1/der/sequence/der_encode_subject_public_key_info.c
+++ b/src/ltc/pk/asn1/x509/x509_encode_subject_public_key_info.c
@@ -9,8 +9,8 @@
#include "tomcrypt.h"
/**
- @file der_encode_subject_public_key_info.c
- ASN.1 DER, encode a Subject Public Key structure --nmav
+ @file x509_encode_subject_public_key_info.c
+ ASN.1 DER/X.509, encode a SubjectPublicKeyInfo structure --nmav
*/
#ifdef LTC_DER
@@ -26,7 +26,7 @@
* }
*/
/**
- Encode a subject public key info
+ Encode a SubjectPublicKeyInfo
@param out The output buffer
@param outlen [in/out] Length of buffer and resulting length of output
@param algorithm One out of the enum #public_key_algorithms
@@ -37,7 +37,7 @@
@param parameters_len The number of parameters to include
@return CRYPT_OK on success
*/
-int der_encode_subject_public_key_info(unsigned char *out, unsigned long *outlen,
+int x509_encode_subject_public_key_info(unsigned char *out, unsigned long *outlen,
unsigned int algorithm, void* public_key, unsigned long public_key_len,
unsigned long parameters_type, void* parameters, unsigned long parameters_len)
{
diff --git a/src/ltc/pk/dsa/dsa_export.c b/src/ltc/pk/dsa/dsa_export.c
index 1f6bb5a3..dde54583 100644
--- a/src/ltc/pk/dsa/dsa_export.c
+++ b/src/ltc/pk/dsa/dsa_export.c
@@ -86,7 +86,7 @@ int dsa_export(unsigned char *out, unsigned long *outlen, int type, dsa_key *key
LTC_SET_ASN1(int_list, 1, LTC_ASN1_INTEGER, key->q, 1UL);
LTC_SET_ASN1(int_list, 2, LTC_ASN1_INTEGER, key->g, 1UL);
- err = der_encode_subject_public_key_info(out, outlen, PKA_DSA, tmp,
+ err = x509_encode_subject_public_key_info(out, outlen, PKA_DSA, tmp,
tmplen, LTC_ASN1_SEQUENCE, int_list,
sizeof(int_list) / sizeof(int_list[0]));
diff --git a/src/ltc/pk/dsa/dsa_import.c b/src/ltc/pk/dsa/dsa_import.c
index e6a75602..5e77b1e7 100644
--- a/src/ltc/pk/dsa/dsa_import.c
+++ b/src/ltc/pk/dsa/dsa_import.c
@@ -25,7 +25,7 @@
int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key)
{
int err, stat;
- unsigned long zero = 0;
+ unsigned long zero = 0, len;
unsigned char* tmpbuf = NULL;
unsigned char flags[1];
@@ -102,9 +102,10 @@ int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key)
goto LBL_ERR;
}
- err = der_decode_subject_public_key_info(in, inlen, PKA_DSA,
+ len = 3;
+ err = x509_decode_subject_public_key_info(in, inlen, PKA_DSA,
tmpbuf, &tmpbuf_len,
- LTC_ASN1_SEQUENCE, params, 3);
+ LTC_ASN1_SEQUENCE, params, &len);
if (err != CRYPT_OK) {
XFREE(tmpbuf);
goto LBL_ERR;
diff --git a/src/ltc/pk/dsa/dsa_verify_hash.c b/src/ltc/pk/dsa/dsa_verify_hash.c
index 3d3fab5f..eb642d5b 100644
--- a/src/ltc/pk/dsa/dsa_verify_hash.c
+++ b/src/ltc/pk/dsa/dsa_verify_hash.c
@@ -111,7 +111,7 @@ int dsa_verify_hash(const unsigned char *sig, unsigned long siglen,
LTC_SET_ASN1(sig_seq, 0, LTC_ASN1_INTEGER, r, 1UL);
LTC_SET_ASN1(sig_seq, 1, LTC_ASN1_INTEGER, s, 1UL);
- err = der_decode_sequence(sig, siglen, sig_seq, 2);
+ err = der_decode_sequence_strict(sig, siglen, sig_seq, 2);
if (err != CRYPT_OK) {
goto LBL_ERR;
}
diff --git a/src/ltc/pk/ecc/ecc.c b/src/ltc/pk/ecc/ecc.c
index 0eb55023..b90afc71 100644
--- a/src/ltc/pk/ecc/ecc.c
+++ b/src/ltc/pk/ecc/ecc.c
@@ -7,9 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
#include "tomcrypt.h"
/**
@@ -19,10 +16,7 @@
#ifdef LTC_MECC
-/* This array holds the curve parameters:
- * - it ***MUST*** be organized by size from smallest to largest
- * - due to curve lookup by keysize the ordering is very important
- * - be careful when adding/removing items to/from this list
+/* This array holds the curve parameters.
* Curves (prime field only) are taken from:
* - http://www.secg.org/collateral/sec2_final.pdf (named: SECP*)
* - http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf (named: NISTP*)
@@ -31,8 +25,7 @@
*/
const ltc_ecc_set_type ltc_ecc_sets[] = {
#if defined(LTC_ECC_SECP112R1) || defined(LTC_ECC112)
-{ /* this curve ***MUST*** be the first from all with size 14 (backward compatibility reasons) */
- /* size/bytes */ 14,
+{
/* curve name */ "SECP112R1",
/* prime */ "DB7C2ABF62E35E668076BEAD208B",
/* A */ "DB7C2ABF62E35E668076BEAD2088",
@@ -41,12 +34,11 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
/* Gx */ "09487239995A5EE76B55F9C2F098",
/* Gy */ "A89CE5AF8724C0A23E0E0FF77500",
/* cofactor */ 1,
- /* OID struct */ { {1,3,132,0,6}, 5 }
+ /* OID */ { 1,3,132,0,6 }, 5
},
#endif
#ifdef LTC_ECC_SECP112R2
{
- /* size/bytes */ 14,
/* curve name */ "SECP112R2",
/* prime */ "DB7C2ABF62E35E668076BEAD208B",
/* A */ "6127C24C05F38A0AAAF65C0EF02C",
@@ -55,12 +47,11 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
/* Gx */ "4BA30AB5E892B4E1649DD0928643",
/* Gy */ "ADCD46F5882E3747DEF36E956E97",
/* cofactor */ 4,
- /* OID struct */ { {1,3,132,0,7}, 5 }
+ /* OID */ { 1,3,132,0,7 }, 5
},
#endif
#if defined(LTC_ECC_SECP128R1) || defined(LTC_ECC128)
-{ /* this curve ***MUST*** be the first from all with size 16 (backward compatibility reasons) */
- /* size/bytes */ 16,
+{
/* curve name */ "SECP128R1",
/* prime */ "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF",
/* A */ "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC",
@@ -69,12 +60,11 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
/* Gx */ "161FF7528B899B2D0C28607CA52C5B86",
/* Gy */ "CF5AC8395BAFEB13C02DA292DDED7A83",
/* cofactor */ 1,
- /* OID struct */ { {1,3,132,0,28}, 5 }
+ /* OID */ { 1,3,132,0,28 }, 5
},
#endif
#ifdef LTC_ECC_SECP128R2
{
- /* size/bytes */ 16,
/* curve name */ "SECP128R2",
/* prime */ "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF",
/* A */ "D6031998D1B3BBFEBF59CC9BBFF9AEE1",
@@ -83,12 +73,11 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
/* Gx */ "7B6AA5D85E572983E6FB32A7CDEBC140",
/* Gy */ "27B6916A894D3AEE7106FE805FC34B44",
/* cofactor */ 4,
- /* OID struct */ { {1,3,132,0,29}, 5 }
+ /* OID */ { 1,3,132,0,29 }, 5
},
#endif
#if defined(LTC_ECC_SECP160R1) || defined(LTC_ECC160)
-{ /* this curve ***MUST*** be the first from all with size 20 (backward compatibility reasons) */
- /* size/bytes */ 20,
+{
/* curve name */ "SECP160R1",
/* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF",
/* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC",
@@ -97,12 +86,11 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
/* Gx */ "4A96B5688EF573284664698968C38BB913CBFC82",
/* Gy */ "23A628553168947D59DCC912042351377AC5FB32",
/* cofactor */ 1,
- /* OID struct */ { {1,3,132,0,8}, 5 }
+ /* OID */ { 1,3,132,0,8 }, 5
},
#endif
#ifdef LTC_ECC_SECP160R2
{
- /* size/bytes */ 20,
/* curve name */ "SECP160R2",
/* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73",
/* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70",
@@ -111,12 +99,11 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
/* Gx */ "52DCB034293A117E1F4FF11B30F7199D3144CE6D",
/* Gy */ "FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E",
/* cofactor */ 1,
- /* OID struct */ { {1,3,132,0,30}, 5 }
+ /* OID */ { 1,3,132,0,30 }, 5
},
#endif
#ifdef LTC_ECC_SECP160K1
{
- /* size/bytes */ 20,
/* curve name */ "SECP160K1",
/* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73",
/* A */ "0000000000000000000000000000000000000000",
@@ -125,26 +112,11 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
/* Gx */ "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB",
/* Gy */ "938CF935318FDCED6BC28286531733C3F03C4FEE",
/* cofactor */ 1,
- /* OID struct */ { {1,3,132,0,9}, 5 }
-},
-#endif
-#ifdef LTC_ECC_BRAINPOOLP160R1
-{
- /* size/bytes */ 20,
- /* curve name */ "BRAINPOOLP160R1",
- /* prime */ "E95E4A5F737059DC60DFC7AD95B3D8139515620F",
- /* A */ "340E7BE2A280EB74E2BE61BADA745D97E8F7C300",
- /* B */ "1E589A8595423412134FAA2DBDEC95C8D8675E58",
- /* order */ "E95E4A5F737059DC60DF5991D45029409E60FC09",
- /* Gx */ "BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC3",
- /* Gy */ "1667CB477A1A8EC338F94741669C976316DA6321",
- /* cofactor */ 1,
- /* OID struct */ { {1,3,36,3,3,2,8,1,1,1}, 10 }
+ /* OID */ { 1,3,132,0,9 }, 5
},
#endif
#if defined(LTC_ECC_SECP192R1) || defined(LTC_ECC192)
-{ /* this curve ***MUST*** be the first from all with size 24 (backward compatibility reasons) */
- /* size/bytes */ 24,
+{
/* curve name */ "SECP192R1", /* same as: NISTP192 PRIME192V1, old libtomcrypt name: ECC-192 */
/* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
/* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC",
@@ -153,12 +125,11 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
/* Gx */ "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012",
/* Gy */ "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811",
/* cofactor */ 1,
- /* OID struct */ { {1,2,840,10045,3,1,1}, 7 }
+ /* OID */ { 1,2,840,10045,3,1,1 }, 7
},
#endif
#ifdef LTC_ECC_PRIME192V2
{
- /* size/bytes */ 24,
/* curve name */ "PRIME192V2",
/* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
/* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC",
@@ -167,12 +138,11 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
/* Gx */ "EEA2BAE7E1497842F2DE7769CFE9C989C072AD696F48034A",
/* Gy */ "6574D11D69B6EC7A672BB82A083DF2F2B0847DE970B2DE15",
/* cofactor */ 1,
- /* OID struct */ { {1,2,840,10045,3,1,2}, 7 }
+ /* OID */ { 1,2,840,10045,3,1,2 }, 7
},
#endif
#ifdef LTC_ECC_PRIME192V3
{
- /* size/bytes */ 24,
/* curve name */ "PRIME192V3",
/* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
/* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC",
@@ -181,12 +151,11 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
/* Gx */ "7D29778100C65A1DA1783716588DCE2B8B4AEE8E228F1896",
/* Gy */ "38A90F22637337334B49DCB66A6DC8F9978ACA7648A943B0",
/* cofactor */ 1,
- /* OID struct */ { {1,2,840,10045,3,1,3}, 7 }
+ /* OID */ { 1,2,840,10045,3,1,3 }, 7
},
#endif
#ifdef LTC_ECC_SECP192K1
{
- /* size/bytes */ 24,
/* curve name */ "SECP192K1",
/* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37",
/* A */ "000000000000000000000000000000000000000000000000",
@@ -195,26 +164,11 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
/* Gx */ "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D",
/* Gy */ "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D",
/* cofactor */ 1,
- /* OID struct */ { {1,3,132,0,31}, 5 }
-},
-#endif
-#ifdef LTC_ECC_BRAINPOOLP192R1
-{
- /* size/bytes */ 24,
- /* curve name */ "BRAINPOOLP192R1",
- /* prime */ "C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297",
- /* A */ "6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF",
- /* B */ "469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9",
- /* order */ "C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1",
- /* Gx */ "C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD6",
- /* Gy */ "14B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F",
- /* cofactor */ 1,
- /* OID struct */ { {1,3,36,3,3,2,8,1,1,3}, 10 }
+ /* OID */ { 1,3,132,0,31 }, 5
},
#endif
#if defined(LTC_ECC_SECP224R1) || defined(LTC_ECC224)
-{ /* this curve ***MUST*** be the first from all with size 28 (backward compatibility reasons) */
- /* size/bytes */ 28,
+{
/* curve name */ "SECP224R1", /* same as: NISTP224, old libtomcrypt name: ECC-224 */
/* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001",
/* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE",
@@ -223,12 +177,11 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
/* Gx */ "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21",
/* Gy */ "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34",
/* cofactor */ 1,
- /* OID struct */ { {1,3,132,0,33}, 5 }
+ /* OID */ { 1,3,132,0,33 }, 5
},
#endif
#ifdef LTC_ECC_SECP224K1
{
- /* size/bytes */ 28,
/* curve name */ "SECP224K1",
/* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D",
/* A */ "00000000000000000000000000000000000000000000000000000000",
@@ -237,26 +190,63 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
/* Gx */ "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C",
/* Gy */ "7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5",
/* cofactor */ 1,
- /* OID struct */ { {1,3,132,0,32}, 5 }
+ /* OID */ { 1,3,132,0,32 }, 5
},
#endif
-#ifdef LTC_ECC_BRAINPOOLP224R1
+#if defined(LTC_ECC_SECP256R1) || defined(LTC_ECC256)
{
- /* size/bytes */ 28,
- /* curve name */ "BRAINPOOLP224R1",
- /* prime */ "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF",
- /* A */ "68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43",
- /* B */ "2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B",
- /* order */ "D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F",
- /* Gx */ "0D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D",
- /* Gy */ "58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD",
+ /* curve name */ "SECP256R1", /* same as: NISTP256 PRIME256V1, old libtomcrypt name: ECC-256 */
+ /* prime */ "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
+ /* A */ "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC",
+ /* B */ "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B",
+ /* order */ "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
+ /* Gx */ "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296",
+ /* Gy */ "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
/* cofactor */ 1,
- /* OID struct */ { {1,3,36,3,3,2,8,1,1,5}, 10 }
+ /* OID */ { 1,2,840,10045,3,1,7 }, 7
+},
+#endif
+#ifdef LTC_ECC_SECP256K1
+{
+ /* curve name */ "SECP256K1",
+ /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F",
+ /* A */ "0000000000000000000000000000000000000000000000000000000000000000",
+ /* B */ "0000000000000000000000000000000000000000000000000000000000000007",
+ /* order */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141",
+ /* Gx */ "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798",
+ /* Gy */ "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8",
+ /* cofactor */ 1,
+ /* OID */ { 1,3,132,0,10 }, 5
+},
+#endif
+#if defined(LTC_ECC_SECP384R1) || defined(LTC_ECC384)
+{
+ /* curve name */ "SECP384R1", /* same as: NISTP384, old libtomcrypt name: ECC-384 */
+ /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF",
+ /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC",
+ /* B */ "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF",
+ /* order */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973",
+ /* Gx */ "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7",
+ /* Gy */ "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F",
+ /* cofactor */ 1,
+ /* OID */ { 1,3,132,0,34 }, 5
+},
+#endif
+#if defined(LTC_ECC_SECP521R1) || defined(LTC_ECC521)
+{
+ /* curve name */ "SECP521R1", /* same as: NISTP521, old libtomcrypt name: ECC-521 */
+ /* prime */ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
+ /* A */ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC",
+ /* B */ "0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00",
+ /* order */ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409",
+ /* Gx */ "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66",
+ /* Gy */ "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650",
+ /* cofactor */ 1,
+ /* OID */ { 1,3,132,0,35 }, 5
},
#endif
#ifdef LTC_ECC_PRIME239V1
{
- /* size/bytes */ 30,
/* curve name */ "PRIME239V1",
/* prime */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF",
/* A */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC",
@@ -265,12 +255,11 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
/* Gx */ "0FFA963CDCA8816CCC33B8642BEDF905C3D358573D3F27FBBD3B3CB9AAAF",
/* Gy */ "7DEBE8E4E90A5DAE6E4054CA530BA04654B36818CE226B39FCCB7B02F1AE",
/* cofactor */ 1,
- /* OID struct */ { {1,2,840,10045,3,1,4}, 7 }
+ /* OID */ { 1,2,840,10045,3,1,4 }, 7
},
#endif
#ifdef LTC_ECC_PRIME239V2
{
- /* size/bytes */ 30,
/* curve name */ "PRIME239V2",
/* prime */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF",
/* A */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC",
@@ -279,12 +268,11 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
/* Gx */ "38AF09D98727705120C921BB5E9E26296A3CDCF2F35757A0EAFD87B830E7",
/* Gy */ "5B0125E4DBEA0EC7206DA0FC01D9B081329FB555DE6EF460237DFF8BE4BA",
/* cofactor */ 1,
- /* OID struct */ { {1,2,840,10045,3,1,5}, 7 }
+ /* OID */ { 1,2,840,10045,3,1,5 }, 7
},
#endif
#ifdef LTC_ECC_PRIME239V3
{
- /* size/bytes */ 30,
/* curve name */ "PRIME239V3",
/* prime */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF",
/* A */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC",
@@ -293,40 +281,50 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
/* Gx */ "6768AE8E18BB92CFCF005C949AA2C6D94853D0E660BBF854B1C9505FE95A",
/* Gy */ "1607E6898F390C06BC1D552BAD226F3B6FCFE48B6E818499AF18E3ED6CF3",
/* cofactor */ 1,
- /* OID struct */ { {1,2,840,10045,3,1,6}, 7 }
+ /* OID */ { 1,2,840,10045,3,1,6 }, 7
},
#endif
-#if defined(LTC_ECC_SECP256R1) || defined(LTC_ECC256)
-{ /* this curve ***MUST*** be the first from all with size 32 (backward compatibility reasons) */
- /* size/bytes */ 32,
- /* curve name */ "SECP256R1", /* same as: NISTP256 PRIME256V1, old libtomcrypt name: ECC-256 */
- /* prime */ "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
- /* A */ "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC",
- /* B */ "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B",
- /* order */ "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
- /* Gx */ "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296",
- /* Gy */ "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
+#ifdef LTC_ECC_BRAINPOOLP160R1
+{
+ /* curve name */ "BRAINPOOLP160R1",
+ /* prime */ "E95E4A5F737059DC60DFC7AD95B3D8139515620F",
+ /* A */ "340E7BE2A280EB74E2BE61BADA745D97E8F7C300",
+ /* B */ "1E589A8595423412134FAA2DBDEC95C8D8675E58",
+ /* order */ "E95E4A5F737059DC60DF5991D45029409E60FC09",
+ /* Gx */ "BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC3",
+ /* Gy */ "1667CB477A1A8EC338F94741669C976316DA6321",
/* cofactor */ 1,
- /* OID struct */ { {1,2,840,10045,3,1,7}, 7 }
+ /* OID */ { 1,3,36,3,3,2,8,1,1,1 }, 10
},
#endif
-#ifdef LTC_ECC_SECP256K1
+#ifdef LTC_ECC_BRAINPOOLP192R1
{
- /* size/bytes */ 32,
- /* curve name */ "SECP256K1",
- /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F",
- /* A */ "0000000000000000000000000000000000000000000000000000000000000000",
- /* B */ "0000000000000000000000000000000000000000000000000000000000000007",
- /* order */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141",
- /* Gx */ "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798",
- /* Gy */ "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8",
+ /* curve name */ "BRAINPOOLP192R1",
+ /* prime */ "C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297",
+ /* A */ "6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF",
+ /* B */ "469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9",
+ /* order */ "C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1",
+ /* Gx */ "C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD6",
+ /* Gy */ "14B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F",
/* cofactor */ 1,
- /* OID struct */ { {1,3,132,0,10}, 5 }
+ /* OID */ { 1,3,36,3,3,2,8,1,1,3 }, 10
+},
+#endif
+#ifdef LTC_ECC_BRAINPOOLP224R1
+{
+ /* curve name */ "BRAINPOOLP224R1",
+ /* prime */ "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF",
+ /* A */ "68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43",
+ /* B */ "2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B",
+ /* order */ "D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F",
+ /* Gx */ "0D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D",
+ /* Gy */ "58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD",
+ /* cofactor */ 1,
+ /* OID */ { 1,3,36,3,3,2,8,1,1,5 }, 10
},
#endif
#ifdef LTC_ECC_BRAINPOOLP256R1
{
- /* size/bytes */ 32,
/* curve name */ "BRAINPOOLP256R1",
/* prime */ "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377",
/* A */ "7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9",
@@ -335,12 +333,11 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
/* Gx */ "8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262",
/* Gy */ "547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997",
/* cofactor */ 1,
- /* OID struct */ { {1,3,36,3,3,2,8,1,1,7}, 10 }
+ /* OID */ { 1,3,36,3,3,2,8,1,1,7 }, 10
},
#endif
#ifdef LTC_ECC_BRAINPOOLP320R1
{
- /* size/bytes */ 40,
/* curve name */ "BRAINPOOLP320R1",
/* prime */ "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27",
/* A */ "3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4",
@@ -349,26 +346,11 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
/* Gx */ "43BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E20611",
/* Gy */ "14FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1",
/* cofactor */ 1,
- /* OID struct */ { {1,3,36,3,3,2,8,1,1,9}, 10 }
-},
-#endif
-#if defined(LTC_ECC_SECP384R1) || defined(LTC_ECC384)
-{ /* this curve ***MUST*** be the first from all with size 48 (backward compatibility reasons) */
- /* size/bytes */ 48,
- /* curve name */ "SECP384R1", /* same as: NISTP384, old libtomcrypt name: ECC-384 */
- /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF",
- /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC",
- /* B */ "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF",
- /* order */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973",
- /* Gx */ "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7",
- /* Gy */ "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F",
- /* cofactor */ 1,
- /* OID struct */ { {1,3,132,0,34}, 5 }
+ /* OID */ { 1,3,36,3,3,2,8,1,1,9 }, 10
},
#endif
#ifdef LTC_ECC_BRAINPOOLP384R1
{
- /* size/bytes */ 48,
/* curve name */ "BRAINPOOLP384R1",
/* prime */ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53",
/* A */ "7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826",
@@ -377,12 +359,11 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
/* Gx */ "1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E",
/* Gy */ "8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315",
/* cofactor */ 1,
- /* OID struct */ { {1,3,36,3,3,2,8,1,1,11}, 10 }
+ /* OID */ { 1,3,36,3,3,2,8,1,1,11 }, 10
},
#endif
#ifdef LTC_ECC_BRAINPOOLP512R1
{
- /* size/bytes */ 64,
/* curve name */ "BRAINPOOLP512R1",
/* prime */ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3",
/* A */ "7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA",
@@ -391,28 +372,104 @@ const ltc_ecc_set_type ltc_ecc_sets[] = {
/* Gx */ "81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822",
/* Gy */ "7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892",
/* cofactor */ 1,
- /* OID struct */ { {1,3,36,3,3,2,8,1,1,13}, 10 }
+ /* OID */ { 1,3,36,3,3,2,8,1,1,13 }, 10
},
#endif
-#if defined(LTC_ECC_SECP521R1) || defined(LTC_ECC521)
-{ /* this curve ***MUST*** be the first from all with size 66 (backward compatibility reasons) */
- /* size/bytes */ 66,
- /* curve name */ "SECP521R1", /* same as: NISTP521, old libtomcrypt name: ECC-521 */
- /* prime */ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
- /* A */ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC",
- /* B */ "0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00",
- /* order */ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409",
- /* Gx */ "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66",
- /* Gy */ "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650",
+#ifdef LTC_ECC_BRAINPOOLP160T1
+{
+ /* curve name */ "BRAINPOOLP160T1",
+ /* prime */ "E95E4A5F737059DC60DFC7AD95B3D8139515620F",
+ /* A */ "E95E4A5F737059DC60DFC7AD95B3D8139515620C",
+ /* B */ "7A556B6DAE535B7B51ED2C4D7DAA7A0B5C55F380",
+ /* order */ "E95E4A5F737059DC60DF5991D45029409E60FC09",
+ /* Gx */ "B199B13B9B34EFC1397E64BAEB05ACC265FF2378",
+ /* Gy */ "ADD6718B7C7C1961F0991B842443772152C9E0AD",
/* cofactor */ 1,
- /* OID struct */ { {1,3,132,0,35}, 5 }
+ /* OID */ { 1,3,36,3,3,2,8,1,1,2 }, 10
+},
+#endif
+#ifdef LTC_ECC_BRAINPOOLP192T1
+{
+ /* curve name */ "BRAINPOOLP192T1",
+ /* prime */ "C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297",
+ /* A */ "C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86294",
+ /* B */ "13D56FFAEC78681E68F9DEB43B35BEC2FB68542E27897B79",
+ /* order */ "C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1",
+ /* Gx */ "3AE9E58C82F63C30282E1FE7BBF43FA72C446AF6F4618129",
+ /* Gy */ "097E2C5667C2223A902AB5CA449D0084B7E5B3DE7CCC01C9",
+ /* cofactor */ 1,
+ /* OID */ { 1,3,36,3,3,2,8,1,1,4 }, 10
+},
+#endif
+#ifdef LTC_ECC_BRAINPOOLP224T1
+{
+ /* curve name */ "BRAINPOOLP224T1",
+ /* prime */ "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF",
+ /* A */ "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FC",
+ /* B */ "4B337D934104CD7BEF271BF60CED1ED20DA14C08B3BB64F18A60888D",
+ /* order */ "D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F",
+ /* Gx */ "6AB1E344CE25FF3896424E7FFE14762ECB49F8928AC0C76029B4D580",
+ /* Gy */ "0374E9F5143E568CD23F3F4D7C0D4B1E41C8CC0D1C6ABD5F1A46DB4C",
+ /* cofactor */ 1,
+ /* OID */ { 1,3,36,3,3,2,8,1,1,6 }, 10
+},
+#endif
+#ifdef LTC_ECC_BRAINPOOLP256T1
+{
+ /* curve name */ "BRAINPOOLP256T1",
+ /* prime */ "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377",
+ /* A */ "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5374",
+ /* B */ "662C61C430D84EA4FE66A7733D0B76B7BF93EBC4AF2F49256AE58101FEE92B04",
+ /* order */ "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7",
+ /* Gx */ "A3E8EB3CC1CFE7B7732213B23A656149AFA142C47AAFBC2B79A191562E1305F4",
+ /* Gy */ "2D996C823439C56D7F7B22E14644417E69BCB6DE39D027001DABE8F35B25C9BE",
+ /* cofactor */ 1,
+ /* OID */ { 1,3,36,3,3,2,8,1,1,8 }, 10
+},
+#endif
+#ifdef LTC_ECC_BRAINPOOLP320T1
+{
+ /* curve name */ "BRAINPOOLP320T1",
+ /* prime */ "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27",
+ /* A */ "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E24",
+ /* B */ "A7F561E038EB1ED560B3D147DB782013064C19F27ED27C6780AAF77FB8A547CEB5B4FEF422340353",
+ /* order */ "D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311",
+ /* Gx */ "925BE9FB01AFC6FB4D3E7D4990010F813408AB106C4F09CB7EE07868CC136FFF3357F624A21BED52",
+ /* Gy */ "63BA3A7A27483EBF6671DBEF7ABB30EBEE084E58A0B077AD42A5A0989D1EE71B1B9BC0455FB0D2C3",
+ /* cofactor */ 1,
+ /* OID */ { 1,3,36,3,3,2,8,1,1,10 }, 10
+},
+#endif
+#ifdef LTC_ECC_BRAINPOOLP384T1
+{
+ /* curve name */ "BRAINPOOLP384T1",
+ /* prime */ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53",
+ /* A */ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC50",
+ /* B */ "7F519EADA7BDA81BD826DBA647910F8C4B9346ED8CCDC64E4B1ABD11756DCE1D2074AA263B88805CED70355A33B471EE",
+ /* order */ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565",
+ /* Gx */ "18DE98B02DB9A306F2AFCD7235F72A819B80AB12EBD653172476FECD462AABFFC4FF191B946A5F54D8D0AA2F418808CC",
+ /* Gy */ "25AB056962D30651A114AFD2755AD336747F93475B7A1FCA3B88F2B6A208CCFE469408584DC2B2912675BF5B9E582928",
+ /* cofactor */ 1,
+ /* OID */ { 1,3,36,3,3,2,8,1,1,12 }, 10
+},
+#endif
+#ifdef LTC_ECC_BRAINPOOLP512T1
+{
+ /* curve name */ "BRAINPOOLP512T1",
+ /* prime */ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3",
+ /* A */ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F0",
+ /* B */ "7CBBBCF9441CFAB76E1890E46884EAE321F70C0BCB4981527897504BEC3E36A62BCDFA2304976540F6450085F2DAE145C22553B465763689180EA2571867423E",
+ /* order */ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069",
+ /* Gx */ "640ECE5C12788717B9C1BA06CBC2A6FEBA85842458C56DDE9DB1758D39C0313D82BA51735CDB3EA499AA77A7D6943A64F7A3F25FE26F06B51BAA2696FA9035DA",
+ /* Gy */ "5B534BD595F5AF0FA2C892376C84ACE1BB4E3019B71634C01131159CAE03CEE9D9932184BEEF216BD71DF2DADF86A627306ECFF96DBB8BACE198B61E00F8B332",
+ /* cofactor */ 1,
+ /* OID */ { 1,3,36,3,3,2,8,1,1,14 }, 10
},
#endif
{
- 0,
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
0,
- { { 0 }, 0 }
+ { 0 }, 0
}
};
diff --git a/src/ltc/pk/ecc/ecc_ansi_x963_export.c b/src/ltc/pk/ecc/ecc_ansi_x963_export.c
index 8bb4cc5f..528dcd80 100644
--- a/src/ltc/pk/ecc/ecc_ansi_x963_export.c
+++ b/src/ltc/pk/ecc/ecc_ansi_x963_export.c
@@ -7,9 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
#include "tomcrypt.h"
/**
@@ -34,10 +31,7 @@ int ecc_ansi_x963_export(ecc_key *key, unsigned char *out, unsigned long *outlen
LTC_ARGCHK(out != NULL);
LTC_ARGCHK(outlen != NULL);
- if (ltc_ecc_is_valid_idx(key->idx) == 0) {
- return CRYPT_INVALID_ARG;
- }
- numlen = key->dp->size;
+ numlen = key->dp.size;
xlen = mp_unsigned_bin_size(key->pubkey.x);
ylen = mp_unsigned_bin_size(key->pubkey.y);
diff --git a/src/ltc/pk/ecc/ecc_ansi_x963_import.c b/src/ltc/pk/ecc/ecc_ansi_x963_import.c
index 9c5a84e5..bcc8575f 100644
--- a/src/ltc/pk/ecc/ecc_ansi_x963_import.c
+++ b/src/ltc/pk/ecc/ecc_ansi_x963_import.c
@@ -7,9 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
#include "tomcrypt.h"
/**
@@ -29,9 +26,9 @@ int ecc_ansi_x963_import(const unsigned char *in, unsigned long inlen, ecc_key *
return ecc_ansi_x963_import_ex(in, inlen, key, NULL);
}
-int ecc_ansi_x963_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, ltc_ecc_set_type *dp)
+int ecc_ansi_x963_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, const ltc_ecc_set_type *dp)
{
- int x, err;
+ int err;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(key != NULL);
@@ -41,60 +38,21 @@ int ecc_ansi_x963_import_ex(const unsigned char *in, unsigned long inlen, ecc_ke
return CRYPT_INVALID_ARG;
}
- /* init key */
- if (mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, NULL) != CRYPT_OK) {
- return CRYPT_MEM;
- }
-
- /* check for 4, 6 or 7 */
- if (in[0] != 4 && in[0] != 6 && in[0] != 7) {
- err = CRYPT_INVALID_PACKET;
- goto error;
- }
-
- /* read data */
- if ((err = mp_read_unsigned_bin(key->pubkey.x, (unsigned char *)in+1, (inlen-1)>>1)) != CRYPT_OK) {
- goto error;
+ /* initialize key->dp */
+ if (dp == NULL) {
+ /* this case works only for uncompressed public keys */
+ if ((err = ecc_set_dp_size((inlen-1)>>1, key)) != CRYPT_OK) { return err; }
}
-
- if ((err = mp_read_unsigned_bin(key->pubkey.y, (unsigned char *)in+1+((inlen-1)>>1), (inlen-1)>>1)) != CRYPT_OK) {
- goto error;
+ else {
+ /* this one works for both compressed / uncompressed pubkeys */
+ if ((err = ecc_set_dp(dp, key)) != CRYPT_OK) { return err; }
}
- if ((err = mp_set(key->pubkey.z, 1)) != CRYPT_OK) { goto error; }
- if (dp == NULL) {
- /* BEWARE: Here we are looking up the curve params by keysize (neither curve name nor curve oid),
- * which might be ambiguous (there can more than one curve for given keysize).
- * Thus the chosen curve depends on order of items in ltc_ecc_sets[] - see ecc.c file.
- */
- /* determine the idx */
- for (x = 0; ltc_ecc_sets[x].size != 0; x++) {
- if ((unsigned)ltc_ecc_sets[x].size >= ((inlen-1)>>1)) {
- break;
- }
- }
- if (ltc_ecc_sets[x].size == 0) {
- err = CRYPT_INVALID_PACKET;
- goto error;
- }
- /* set the idx */
- key->idx = x;
- key->dp = &ltc_ecc_sets[x];
- } else {
- if (((inlen-1)>>1) != (unsigned long) dp->size) {
- err = CRYPT_INVALID_PACKET;
- goto error;
- }
- key->idx = -1;
- key->dp = dp;
- }
- key->type = PK_PUBLIC;
+ /* load public key */
+ if ((err = ecc_set_key((unsigned char *)in, inlen, PK_PUBLIC, key)) != CRYPT_OK) { return err; }
/* we're done */
return CRYPT_OK;
-error:
- mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL);
- return err;
}
#endif
diff --git a/src/ltc/pk/ecc/ecc_decrypt_key.c b/src/ltc/pk/ecc/ecc_decrypt_key.c
index d86c168b..ebfa5156 100644
--- a/src/ltc/pk/ecc/ecc_decrypt_key.c
+++ b/src/ltc/pk/ecc/ecc_decrypt_key.c
@@ -7,9 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
#include "tomcrypt.h"
/**
@@ -33,7 +30,8 @@ int ecc_decrypt_key(const unsigned char *in, unsigned long inlen,
ecc_key *key)
{
unsigned char *ecc_shared, *skey, *pub_expt;
- unsigned long x, y, hashOID[32];
+ unsigned long x, y;
+ unsigned long hashOID[32] = { 0 };
int hash, err;
ecc_key pubkey;
ltc_asn1_list decode[3];
@@ -87,9 +85,8 @@ int ecc_decrypt_key(const unsigned char *in, unsigned long inlen,
}
/* import ECC key from packet */
- if ((err = ecc_import_raw(decode[1].data, decode[1].size, &pubkey, (ltc_ecc_set_type *)key->dp)) != CRYPT_OK) {
- goto LBL_ERR;
- }
+ if ((err = ecc_set_dp_copy(key, &pubkey)) != CRYPT_OK) { goto LBL_ERR; }
+ if ((err = ecc_set_key(decode[1].data, decode[1].size, PK_PUBLIC, &pubkey)) != CRYPT_OK) { goto LBL_ERR; }
/* make shared key */
x = ECC_BUF_SIZE;
diff --git a/src/ltc/pk/ecc/ecc_dp_clear.c b/src/ltc/pk/ecc/ecc_dp_clear.c
deleted file mode 100644
index 76fa375e..00000000
--- a/src/ltc/pk/ecc/ecc_dp_clear.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/* LibTomCrypt, modular cryptographic library -- Tom St Denis
- *
- * LibTomCrypt is a library that provides various cryptographic
- * algorithms in a highly modular and flexible manner.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- */
-
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
-
-#include "tomcrypt.h"
-
-#ifdef LTC_MECC
-
-int ecc_dp_clear(ltc_ecc_set_type *dp)
-{
- if (dp == NULL) return CRYPT_INVALID_ARG;
-
- if (dp->name != NULL) { XFREE(dp->name ); dp->name = NULL; }
- if (dp->prime != NULL) { XFREE(dp->prime); dp->prime = NULL; }
- if (dp->A != NULL) { XFREE(dp->A ); dp->A = NULL; }
- if (dp->B != NULL) { XFREE(dp->B ); dp->B = NULL; }
- if (dp->order != NULL) { XFREE(dp->order); dp->order = NULL; }
- if (dp->Gx != NULL) { XFREE(dp->Gx ); dp->Gx = NULL; }
- if (dp->Gy != NULL) { XFREE(dp->Gy ); dp->Gy = NULL; }
- dp->cofactor = 0;
- dp->oid.OIDlen = 0;
-
- return CRYPT_OK;
-}
-
-#endif
diff --git a/src/ltc/pk/ecc/ecc_dp_fill_from_sets.c b/src/ltc/pk/ecc/ecc_dp_fill_from_sets.c
deleted file mode 100644
index 06c66be4..00000000
--- a/src/ltc/pk/ecc/ecc_dp_fill_from_sets.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/* LibTomCrypt, modular cryptographic library -- Tom St Denis
- *
- * LibTomCrypt is a library that provides various cryptographic
- * algorithms in a highly modular and flexible manner.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- */
-
-#include "tomcrypt.h"
-
-#ifdef LTC_MECC
-
-static int hexstrcmp(const char *hexa, const char *hexb)
-{
- #define MY_TOLOWER(a) ((((a)>='A')&&((a)<='Z')) ? ((a)|0x60) : (a))
- /* ignore leading zeroes */
- while(*hexa == '0') hexa++;
- while(*hexb == '0') hexb++;
- /* compare: case insensitive, hexadecimal chars only */
- while (*hexa && *hexb) {
- if ( (*hexa < '0' || *hexa > '9') &&
- (*hexa < 'a' || *hexa > 'f') &&
- (*hexa < 'A' || *hexa > 'F') ) return 1;
- if ( (*hexb < '0' || *hexb > '9') &&
- (*hexb < 'a' || *hexb > 'f') &&
- (*hexb < 'A' || *hexb > 'F') ) return 1;
- if (MY_TOLOWER(*hexa) != MY_TOLOWER(*hexb)) return 1;
- hexa++;
- hexb++;
- }
- if (*hexa == '\0' && *hexb == '\0') return 0; /* success - match */
- return 1;
-}
-
-/* search known curve by curve parameters and fill in missing parameters into dp
- * we assume every parameter has the same case (usually uppercase) and no leading zeros
- */
-int ecc_dp_fill_from_sets(ltc_ecc_set_type *dp)
-{
- ltc_ecc_set_type params;
- int x;
-
- if (!dp) return CRYPT_INVALID_ARG;
- if (dp->oid.OIDlen > 0) return CRYPT_OK;
- if (!dp->prime || !dp->A || !dp->B || !dp->order || !dp->Gx || !dp->Gy || dp->cofactor == 0) return CRYPT_INVALID_ARG;
-
- for (x = 0; ltc_ecc_sets[x].size != 0; x++) {
- if (hexstrcmp(ltc_ecc_sets[x].prime, dp->prime) == 0 &&
- hexstrcmp(ltc_ecc_sets[x].A, dp->A) == 0 &&
- hexstrcmp(ltc_ecc_sets[x].B, dp->B) == 0 &&
- hexstrcmp(ltc_ecc_sets[x].order, dp->order) == 0 &&
- hexstrcmp(ltc_ecc_sets[x].Gx, dp->Gx) == 0 &&
- hexstrcmp(ltc_ecc_sets[x].Gy, dp->Gy) == 0 &&
- ltc_ecc_sets[x].cofactor == dp->cofactor) {
-
- params = ltc_ecc_sets[x];
-
- /* copy oid */
- dp->oid.OIDlen = params.oid.OIDlen;
- XMEMCPY(dp->oid.OID, params.oid.OID, dp->oid.OIDlen * sizeof(dp->oid.OID[0]));
-
- /* copy name */
- if (dp->name != NULL) XFREE(dp->name);
- if ((dp->name = XMALLOC(1+strlen(params.name))) == NULL) return CRYPT_MEM;
- strcpy(dp->name, params.name);
-
- return CRYPT_OK;
- }
- }
-
- return CRYPT_INVALID_ARG;
-}
-
-#endif
diff --git a/src/ltc/pk/ecc/ecc_dp_from_oid.c b/src/ltc/pk/ecc/ecc_dp_from_oid.c
deleted file mode 100644
index 5ddd1aba..00000000
--- a/src/ltc/pk/ecc/ecc_dp_from_oid.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/* LibTomCrypt, modular cryptographic library -- Tom St Denis
- *
- * LibTomCrypt is a library that provides various cryptographic
- * algorithms in a highly modular and flexible manner.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- */
-
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
-
-#include "tomcrypt.h"
-
-#ifdef LTC_MECC
-
-int ecc_dp_set_by_oid(ltc_ecc_set_type *dp, unsigned long *oid, unsigned long oidsize)
-{
- int i;
- unsigned long len;
-
- for(i=0; ltc_ecc_sets[i].size != 0; i++) {
- if ((oidsize == ltc_ecc_sets[i].oid.OIDlen) &&
- (XMEM_NEQ(oid, ltc_ecc_sets[i].oid.OID, sizeof(unsigned long) * ltc_ecc_sets[i].oid.OIDlen) == 0)) {
- break;
- }
- }
- if (ltc_ecc_sets[i].size == 0) return CRYPT_INVALID_ARG; /* not found */
-
- /* a */
- len = (unsigned long)strlen(ltc_ecc_sets[i].A);
- if ((dp->A = XMALLOC(1+len)) == NULL) goto cleanup1;
- strncpy(dp->A, ltc_ecc_sets[i].A, 1+len);
- /* b */
- len = (unsigned long)strlen(ltc_ecc_sets[i].B);
- if ((dp->B = XMALLOC(1+len)) == NULL) goto cleanup2;
- strncpy(dp->B, ltc_ecc_sets[i].B, 1+len);
- /* order */
- len = (unsigned long)strlen(ltc_ecc_sets[i].order);
- if ((dp->order = XMALLOC(1+len)) == NULL) goto cleanup3;
- strncpy(dp->order, ltc_ecc_sets[i].order, 1+len);
- /* prime */
- len = (unsigned long)strlen(ltc_ecc_sets[i].prime);
- if ((dp->prime = XMALLOC(1+len)) == NULL) goto cleanup4;
- strncpy(dp->prime, ltc_ecc_sets[i].prime, 1+len);
- /* gx */
- len = (unsigned long)strlen(ltc_ecc_sets[i].Gx);
- if ((dp->Gx = XMALLOC(1+len)) == NULL) goto cleanup5;
- strncpy(dp->Gx, ltc_ecc_sets[i].Gx, 1+len);
- /* gy */
- len = (unsigned long)strlen(ltc_ecc_sets[i].Gy);
- if ((dp->Gy = XMALLOC(1+len)) == NULL) goto cleanup6;
- strncpy(dp->Gy, ltc_ecc_sets[i].Gy, 1+len);
- /* cofactor & size */
- dp->cofactor = ltc_ecc_sets[i].cofactor;
- dp->size = ltc_ecc_sets[i].size;
- /* name */
- len = (unsigned long)strlen(ltc_ecc_sets[i].name);
- if ((dp->name = XMALLOC(1+len)) == NULL) goto cleanup7;
- strncpy(dp->name, ltc_ecc_sets[i].name, 1+len);
- /* oid */
- dp->oid.OIDlen = ltc_ecc_sets[i].oid.OIDlen;
- XMEMCPY(dp->oid.OID, ltc_ecc_sets[i].oid.OID, dp->oid.OIDlen * sizeof(dp->oid.OID[0]));
- /* done - success */
- return CRYPT_OK;
-
-cleanup7:
- XFREE(dp->Gy);
-cleanup6:
- XFREE(dp->Gx);
-cleanup5:
- XFREE(dp->prime);
-cleanup4:
- XFREE(dp->order);
-cleanup3:
- XFREE(dp->B);
-cleanup2:
- XFREE(dp->A);
-cleanup1:
- return CRYPT_MEM;
-}
-
-#endif
diff --git a/src/ltc/pk/ecc/ecc_dp_from_params.c b/src/ltc/pk/ecc/ecc_dp_from_params.c
deleted file mode 100644
index a1ddee97..00000000
--- a/src/ltc/pk/ecc/ecc_dp_from_params.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/* LibTomCrypt, modular cryptographic library -- Tom St Denis
- *
- * LibTomCrypt is a library that provides various cryptographic
- * algorithms in a highly modular and flexible manner.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- */
-
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
-
-#include "tomcrypt.h"
-
-#ifdef LTC_MECC
-
-int ecc_dp_set_bn(ltc_ecc_set_type *dp, void *a, void *b, void *prime, void *order, void *gx, void *gy, unsigned long cofactor)
-{
- unsigned char buf[ECC_BUF_SIZE];
- unsigned long len;
-
- /* a */
- mp_tohex(a, (char *)buf);
- len = (unsigned long)strlen((char *)buf);
- if ((dp->A = XMALLOC(1+len)) == NULL) goto cleanup1;
- strncpy(dp->A, (char*)buf, 1+len);
- /* b */
- mp_tohex(b, (char *)buf);
- len = (unsigned long)strlen((char *)buf);
- if ((dp->B = XMALLOC(1+len)) == NULL) goto cleanup2;
- strncpy(dp->B, (char*)buf, 1+len);
- /* order */
- mp_tohex(order, (char *)buf);
- len = (unsigned long)strlen((char *)buf);
- if ((dp->order = XMALLOC(1+len)) == NULL) goto cleanup3;
- strncpy(dp->order, (char*)buf, 1+len);
- /* prime */
- mp_tohex(prime, (char *)buf);
- len = (unsigned long)strlen((char *)buf);
- if ((dp->prime = XMALLOC(1+len)) == NULL) goto cleanup4;
- strncpy(dp->prime, (char*)buf, 1+len);
- /* gx */
- mp_tohex(gx, (char *)buf);
- len = (unsigned long)strlen((char *)buf);
- if ((dp->Gx = XMALLOC(1+len)) == NULL) goto cleanup5;
- strncpy(dp->Gx, (char*)buf, 1+len);
- /* gy */
- mp_tohex(gy, (char *)buf);
- len = (unsigned long)strlen((char *)buf);
- if ((dp->Gy = XMALLOC(1+len)) == NULL) goto cleanup6;
- strncpy(dp->Gy, (char*)buf, 1+len);
- /* cofactor & size */
- dp->cofactor = cofactor;
- dp->size = mp_unsigned_bin_size(prime);
- /* see if we can fill in the missing parameters from known curves */
- if ((ecc_dp_fill_from_sets(dp)) != CRYPT_OK) {
- /* custom name */
- if ((dp->name = XMALLOC(7)) == NULL) goto cleanup7;
- strcpy(dp->name, "custom"); /* XXX-TODO check this */
- /* no oid */
- dp->oid.OIDlen = 0;
- }
- /* done - success */
- return CRYPT_OK;
-
- /* XFREE(dp->name); **** warning: statement not reached *** */
-cleanup7:
- XFREE(dp->Gy);
-cleanup6:
- XFREE(dp->Gx);
-cleanup5:
- XFREE(dp->prime);
-cleanup4:
- XFREE(dp->order);
-cleanup3:
- XFREE(dp->B);
-cleanup2:
- XFREE(dp->A);
-cleanup1:
- return CRYPT_MEM;
-}
-
-#endif
diff --git a/src/ltc/pk/ecc/ecc_dp_init.c b/src/ltc/pk/ecc/ecc_dp_init.c
deleted file mode 100644
index 36c8f5c6..00000000
--- a/src/ltc/pk/ecc/ecc_dp_init.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/* LibTomCrypt, modular cryptographic library -- Tom St Denis
- *
- * LibTomCrypt is a library that provides various cryptographic
- * algorithms in a highly modular and flexible manner.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- */
-
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
-
-#include "tomcrypt.h"
-
-#ifdef LTC_MECC
-
-int ecc_dp_init(ltc_ecc_set_type *dp)
-{
- if (dp == NULL) return CRYPT_INVALID_ARG;
-
- dp->name = NULL;
- dp->prime = NULL;
- dp->A = NULL;
- dp->B = NULL;
- dp->order = NULL;
- dp->Gx = NULL;
- dp->Gy = NULL;
- dp->oid.OIDlen = 0;
- dp->cofactor = 0;
-
- return CRYPT_OK;
-}
-
-#endif
diff --git a/src/ltc/pk/ecc/ecc_dp_set.c b/src/ltc/pk/ecc/ecc_dp_set.c
deleted file mode 100644
index 33c72816..00000000
--- a/src/ltc/pk/ecc/ecc_dp_set.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/* LibTomCrypt, modular cryptographic library -- Tom St Denis
- *
- * LibTomCrypt is a library that provides various cryptographic
- * algorithms in a highly modular and flexible manner.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- */
-
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
-
-#include "tomcrypt.h"
-#include <errno.h>
-
-#ifdef LTC_MECC
-
-int ecc_dp_set(ltc_ecc_set_type *dp, char *ch_prime, char *ch_A, char *ch_B, char *ch_order, char *ch_Gx, char *ch_Gy, unsigned long cofactor, char *ch_name, char *oid)
-{
- unsigned long l_name, l_prime, l_A, l_B, l_order, l_Gx, l_Gy;
-
- if (!dp || !ch_prime || !ch_A || !ch_B || !ch_order || !ch_Gx || !ch_Gy || cofactor==0) return CRYPT_INVALID_ARG;
-
- l_prime = (unsigned long)strlen(ch_prime);
- l_A = (unsigned long)strlen(ch_A);
- l_B = (unsigned long)strlen(ch_B);
- l_order = (unsigned long)strlen(ch_order);
- l_Gx = (unsigned long)strlen(ch_Gx);
- l_Gy = (unsigned long)strlen(ch_Gy);
-
- dp->cofactor = cofactor;
-
- { /* calculate size */
- void *p_num;
- mp_init(&p_num);
- mp_read_radix(p_num, ch_prime, 16);
- dp->size = mp_unsigned_bin_size(p_num);
- mp_clear(p_num);
- }
-
- if (dp->name != NULL) { XFREE(dp->name ); dp->name = NULL; }
- if (dp->prime != NULL) { XFREE(dp->prime); dp->prime = NULL; }
- if (dp->A != NULL) { XFREE(dp->A ); dp->A = NULL; }
- if (dp->B != NULL) { XFREE(dp->B ); dp->B = NULL; }
- if (dp->order != NULL) { XFREE(dp->order); dp->order = NULL; }
- if (dp->Gx != NULL) { XFREE(dp->Gx ); dp->Gx = NULL; }
- if (dp->Gy != NULL) { XFREE(dp->Gy ); dp->Gy = NULL; }
-
- dp->prime = XMALLOC(1+l_prime); strncpy(dp->prime, ch_prime, 1+l_prime);
- dp->A = XMALLOC(1+l_A); strncpy(dp->A, ch_A, 1+l_A);
- dp->B = XMALLOC(1+l_B); strncpy(dp->B, ch_B, 1+l_B);
- dp->order = XMALLOC(1+l_order); strncpy(dp->order, ch_order, 1+l_order);
- dp->Gx = XMALLOC(1+l_Gx); strncpy(dp->Gx, ch_Gx, 1+l_Gx);
- dp->Gy = XMALLOC(1+l_Gy); strncpy(dp->Gy, ch_Gy, 1+l_Gy);
-
- /* optional parameters */
- if (ch_name == NULL && oid == NULL) {
- (void)ecc_dp_fill_from_sets(dp);
- }
- else {
- if (ch_name != NULL) {
- l_name = (unsigned long)strlen(ch_name);
- dp->name = XMALLOC(1+l_name);
- strncpy(dp->name, ch_name, 1+l_name);
- }
-
- if (oid != NULL) {
- char *end_ptr;
- unsigned int i = 0;
- unsigned long val;
-
- end_ptr = oid;
- while (i < sizeof(dp->oid.OID)/sizeof(dp->oid.OID[0]) && *oid != '\0') {
- errno = 0;
- val = strtoul(oid, &end_ptr, 10);
- if (errno != 0 || oid == end_ptr) break; /* parsing failed */
- if (val > 0xFFFFFFFF) break; /* x64 check */
- dp->oid.OID[i++] = val;
- oid = end_ptr;
- if (*oid != '.') break;
- oid++;
- }
- if (i == 0 || *end_ptr != '\0') return CRYPT_INVALID_ARG;
- dp->oid.OIDlen = i;
- }
- }
-
- /* in case the parameters are really custom (unlikely) */
- if (dp->name == NULL) {
- dp->name = XMALLOC(7);
- strcpy(dp->name, "custom");
- dp->oid.OIDlen = 0;
- }
-
- return CRYPT_OK;
-}
-
-#endif
diff --git a/src/ltc/pk/ecc/ecc_encrypt_key.c b/src/ltc/pk/ecc/ecc_encrypt_key.c
index 8a32190b..530eadd8 100644
--- a/src/ltc/pk/ecc/ecc_encrypt_key.c
+++ b/src/ltc/pk/ecc/ecc_encrypt_key.c
@@ -7,9 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
#include "tomcrypt.h"
/**
@@ -60,9 +57,8 @@ int ecc_encrypt_key(const unsigned char *in, unsigned long inlen,
}
/* make a random key and export the public copy */
- if ((err = ecc_make_key_ex(prng, wprng, &pubkey, key->dp)) != CRYPT_OK) {
- return err;
- }
+ if ((err = ecc_set_dp_copy(key, &pubkey)) != CRYPT_OK) { return err; }
+ if ((err = ecc_generate_key(prng, wprng, &pubkey)) != CRYPT_OK) { return err; }
pub_expt = XMALLOC(ECC_BUF_SIZE);
ecc_shared = XMALLOC(ECC_BUF_SIZE);
@@ -82,7 +78,12 @@ int ecc_encrypt_key(const unsigned char *in, unsigned long inlen,
}
pubkeysize = ECC_BUF_SIZE;
- if ((err = ecc_export_raw(pub_expt, &pubkeysize, PK_PUBLIC|PK_COMPRESSED, &pubkey)) != CRYPT_OK) {
+#ifdef USE_TFM
+ /* XXX-FIXME: TFM does not support sqrtmod_prime */
+ if ((err = ecc_get_key(pub_expt, &pubkeysize, PK_PUBLIC, &pubkey)) != CRYPT_OK) {
+#else
+ if ((err = ecc_get_key(pub_expt, &pubkeysize, PK_PUBLIC|PK_COMPRESSED, &pubkey)) != CRYPT_OK) {
+#endif
ecc_free(&pubkey);
goto LBL_ERR;
}
diff --git a/src/ltc/pk/ecc/ecc_export.c b/src/ltc/pk/ecc/ecc_export.c
index 05aacfed..a095e9a2 100644
--- a/src/ltc/pk/ecc/ecc_export.c
+++ b/src/ltc/pk/ecc/ecc_export.c
@@ -7,9 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
#include "tomcrypt.h"
/**
@@ -42,12 +39,8 @@ int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key
return CRYPT_PK_TYPE_MISMATCH;
}
- if (ltc_ecc_is_valid_idx(key->idx) == 0) {
- return CRYPT_INVALID_ARG;
- }
-
/* we store the NIST byte size */
- key_size = key->dp->size;
+ key_size = key->dp.size;
if (type == PK_PRIVATE) {
flags[0] = 1;
diff --git a/src/ltc/pk/ecc/ecc_export_full.c b/src/ltc/pk/ecc/ecc_export_openssl.c
index e7d940d5..c9181376 100644
--- a/src/ltc/pk/ecc/ecc_export_full.c
+++ b/src/ltc/pk/ecc/ecc_export_openssl.c
@@ -5,11 +5,6 @@
*
* The library is free for all purposes without any express
* guarantee it works.
- *
- */
-
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
*/
#include "tomcrypt.h"
@@ -25,7 +20,7 @@
@return CRYPT_OK if successful
*/
-int ecc_export_full(unsigned char *out, unsigned long *outlen, int type, ecc_key *key)
+int ecc_export_openssl(unsigned char *out, unsigned long *outlen, int type, ecc_key *key)
{
int err;
void *prime, *order, *a, *b, *gx, *gy;
@@ -33,24 +28,23 @@ int ecc_export_full(unsigned char *out, unsigned long *outlen, int type, ecc_key
unsigned long len_a, len_b, len_k, len_g, len_xy;
unsigned long cofactor, one = 1;
oid_st oid;
- ltc_asn1_list seq_fieldid[2], seq_curve[2], seq_ecparams[6], seq_priv[4], asn_ecparams[1];
+ ltc_asn1_list seq_fieldid[2], seq_curve[2], seq_ecparams[6], seq_priv[4], pub_xy, ecparams;
+ int flag_oid = type & PK_CURVEOID ? 1 : 0;
+ int flag_com = type & PK_COMPRESSED ? 1 : 0;
+ int flag_pri = type & PK_PRIVATE ? 1 : 0;
LTC_ARGCHK(out != NULL);
LTC_ARGCHK(outlen != NULL);
LTC_ARGCHK(key != NULL);
- if (key->type != PK_PRIVATE && type == PK_PRIVATE) return CRYPT_PK_TYPE_MISMATCH;
- if (ltc_ecc_is_valid_idx(key->idx) == 0) return CRYPT_INVALID_ARG;
- if (key->dp == NULL) return CRYPT_INVALID_ARG;
-
- if ((err = mp_init_multi(&prime, &order, &a, &b, &gx, &gy, NULL)) != CRYPT_OK) return err;
+ if (key->type != PK_PRIVATE && flag_pri) return CRYPT_PK_TYPE_MISMATCH;
- if ((err = mp_read_radix(prime, key->dp->prime, 16)) != CRYPT_OK) goto error;
- if ((err = mp_read_radix(order, key->dp->order, 16)) != CRYPT_OK) goto error;
- if ((err = mp_read_radix(b, key->dp->B, 16)) != CRYPT_OK) goto error;
- if ((err = mp_read_radix(a, key->dp->A, 16)) != CRYPT_OK) goto error;
- if ((err = mp_read_radix(gx, key->dp->Gx, 16)) != CRYPT_OK) goto error;
- if ((err = mp_read_radix(gy, key->dp->Gy, 16)) != CRYPT_OK) goto error;
+ prime = key->dp.prime;
+ order = key->dp.order;
+ b = key->dp.B;
+ a = key->dp.A;
+ gx = key->dp.base.x;
+ gy = key->dp.base.y;
/* curve param a */
len_a = mp_unsigned_bin_size(a);
@@ -64,33 +58,32 @@ int ecc_export_full(unsigned char *out, unsigned long *outlen, int type, ecc_key
if ((err = mp_to_unsigned_bin(b, bin_b)) != CRYPT_OK) goto error;
if (len_b == 0) { len_b = 1; bin_b[0] = 0; } /* XXX-TODO hack to handle case b == 0 */
- /* base point - we export uncompressed form */
+ /* base point - (un)compressed based on flag_com */
len_g = sizeof(bin_g);
- if ((err = ltc_ecc_export_point(bin_g, &len_g, gx, gy, key->dp->size, 0)) != CRYPT_OK) goto error;
+ if ((err = ltc_ecc_export_point(bin_g, &len_g, gx, gy, key->dp.size, flag_com)) != CRYPT_OK) goto error;
- /* public key */
+ /* public key - (un)compressed based on flag_com */
len_xy = sizeof(bin_xy);
- if ((err = ltc_ecc_export_point(bin_xy, &len_xy, key->pubkey.x, key->pubkey.y, key->dp->size, 0)) != CRYPT_OK) goto error;
+ if ((err = ltc_ecc_export_point(bin_xy, &len_xy, key->pubkey.x, key->pubkey.y, key->dp.size, flag_com)) != CRYPT_OK) goto error;
/* co-factor */
- cofactor = key->dp->cofactor;
+ cofactor = key->dp.cofactor;
/* we support only prime-field EC */
- if ((err = pk_get_oid(EC_PRIME_FIELD, &oid)) != CRYPT_OK) goto error;
+ if ((err = pk_get_oid(PKA_EC_PRIMEF, &oid)) != CRYPT_OK) goto error;
- if (type & PK_CURVEOID) {
+ if (flag_oid) {
/* from http://tools.ietf.org/html/rfc5912
ECParameters ::= CHOICE {
namedCurve CURVE.&id({NamedCurve}) # OBJECT
}
*/
-
- /* BEWARE: exporting PK_CURVEOID with custom OID means we're unable to read the curve again */
- if (key->dp->oid.OIDlen == 0) { err = CRYPT_INVALID_ARG; goto error; }
-
- /* ECParameters used by ECPrivateKey or SubjectPublicKeyInfo below */
- LTC_SET_ASN1(asn_ecparams, 0, LTC_ASN1_OBJECT_IDENTIFIER, key->dp->oid.OID, key->dp->oid.OIDlen);
+ if (key->dp.oidlen == 0) {
+ err = CRYPT_INVALID_ARG;
+ goto error;
+ }
+ LTC_SET_ASN1(&ecparams, 0, LTC_ASN1_OBJECT_IDENTIFIER, key->dp.oid, key->dp.oidlen);
}
else {
/* from http://tools.ietf.org/html/rfc3279
@@ -129,12 +122,10 @@ int ecc_export_full(unsigned char *out, unsigned long *outlen, int type, ecc_key
LTC_SET_ASN1(seq_ecparams, 5, LTC_ASN1_SHORT_INTEGER, &cofactor, 1UL);
/* ECParameters used by ECPrivateKey or SubjectPublicKeyInfo below */
- LTC_SET_ASN1(asn_ecparams, 0, LTC_ASN1_SEQUENCE, seq_ecparams, 6UL);
+ LTC_SET_ASN1(&ecparams, 0, LTC_ASN1_SEQUENCE, seq_ecparams, 6UL);
}
- type &= ~PK_CURVEOID;
-
- if (type == PK_PRIVATE) {
+ if (flag_pri) {
/* private key format: http://tools.ietf.org/html/rfc5915
ECPrivateKey ::= SEQUENCE { # SEQUENCE
@@ -150,12 +141,11 @@ int ecc_export_full(unsigned char *out, unsigned long *outlen, int type, ecc_key
if (len_k > sizeof(bin_k)) { err = CRYPT_BUFFER_OVERFLOW; goto error; }
if ((err = mp_to_unsigned_bin(key->k, bin_k)) != CRYPT_OK) goto error;
- LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER, &one, 1UL);
- LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING, bin_k, len_k);
- LTC_SET_ASN1(seq_priv, 2, asn_ecparams[0].type, asn_ecparams[0].data, asn_ecparams[0].size);
- LTC_SET_ASN1(seq_priv, 3, LTC_ASN1_RAW_BIT_STRING, bin_xy, 8*len_xy);
- seq_priv[2].tag = 0xA0;
- seq_priv[3].tag = 0xA1;
+ LTC_SET_ASN1(&pub_xy, 0, LTC_ASN1_RAW_BIT_STRING, bin_xy, 8*len_xy);
+ LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER, &one, 1);
+ LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING, bin_k, len_k);
+ LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 2, LTC_ASN1_CL_CONTEXT_SPECIFIC, 0, &ecparams); /* context specific 0 */
+ LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 3, LTC_ASN1_CL_CONTEXT_SPECIFIC, 1, &pub_xy); /* context specific 1 */
err = der_encode_sequence(seq_priv, 4, out, outlen);
}
@@ -170,14 +160,17 @@ int ecc_export_full(unsigned char *out, unsigned long *outlen, int type, ecc_key
subjectPublicKey BIT STRING # BIT STRING
}
*/
- err = der_encode_subject_public_key_info( out, outlen,
+ err = x509_encode_subject_public_key_info( out, outlen,
PKA_EC, bin_xy, len_xy,
- asn_ecparams[0].type, asn_ecparams[0].data, asn_ecparams[0].size );
+ ecparams.type, ecparams.data, ecparams.size );
}
error:
- mp_clear_multi(prime, order, a, b, gx, gy, NULL);
return err;
}
#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/ecc/ecc_free.c b/src/ltc/pk/ecc/ecc_free.c
index e25d7c58..c8033b3b 100644
--- a/src/ltc/pk/ecc/ecc_free.c
+++ b/src/ltc/pk/ecc/ecc_free.c
@@ -7,9 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
#include "tomcrypt.h"
/**
@@ -26,7 +23,14 @@
void ecc_free(ecc_key *key)
{
LTC_ARGCHKVD(key != NULL);
- mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL);
+ /* clean dp */
+ mp_cleanup_multi(&key->dp.prime, &key->dp.order,
+ &key->dp.A, &key->dp.B,
+ &key->dp.base.x, &key->dp.base.y, &key->dp.base.z,
+ NULL);
+
+ /* clean key */
+ mp_cleanup_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, NULL);
}
#endif
diff --git a/src/ltc/pk/ecc/ecc_export_raw.c b/src/ltc/pk/ecc/ecc_get_key.c
index ed4966dd..2b4e8574 100644
--- a/src/ltc/pk/ecc/ecc_export_raw.c
+++ b/src/ltc/pk/ecc/ecc_get_key.c
@@ -5,11 +5,6 @@
*
* The library is free for all purposes without any express
* guarantee it works.
- *
- */
-
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
*/
#include "tomcrypt.h"
@@ -24,7 +19,7 @@
Return CRYPT_OK on success
*/
-int ecc_export_raw(unsigned char *out, unsigned long *outlen, int type, ecc_key *key)
+int ecc_get_key(unsigned char *out, unsigned long *outlen, int type, ecc_key *key)
{
unsigned long size, ksize;
int err, compressed;
@@ -33,19 +28,14 @@ int ecc_export_raw(unsigned char *out, unsigned long *outlen, int type, ecc_key
LTC_ARGCHK(out != NULL);
LTC_ARGCHK(outlen != NULL);
- if (ltc_ecc_is_valid_idx(key->idx) == 0) {
- return CRYPT_INVALID_ARG;
- }
- size = key->dp->size;
-
- compressed = type & PK_COMPRESSED;
+ size = key->dp.size;
+ compressed = type & PK_COMPRESSED ? 1 : 0;
type &= ~PK_COMPRESSED;
- if (type == PK_PUBLIC && compressed) {
- if ((err = ltc_ecc_export_point(out, outlen, key->pubkey.x, key->pubkey.y, size, 1)) != CRYPT_OK) return err;
- }
- else if (type == PK_PUBLIC) {
- if ((err = ltc_ecc_export_point(out, outlen, key->pubkey.x, key->pubkey.y, size, 0)) != CRYPT_OK) return err;
+ if (type == PK_PUBLIC) {
+ if ((err = ltc_ecc_export_point(out, outlen, key->pubkey.x, key->pubkey.y, size, compressed)) != CRYPT_OK) {
+ return err;
+ }
}
else if (type == PK_PRIVATE) {
if (key->type != PK_PRIVATE) return CRYPT_PK_TYPE_MISMATCH;
@@ -64,3 +54,7 @@ int ecc_export_raw(unsigned char *out, unsigned long *outlen, int type, ecc_key
}
#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/ecc/ecc_get_set.c b/src/ltc/pk/ecc/ecc_get_set.c
new file mode 100644
index 00000000..f00cf45f
--- /dev/null
+++ b/src/ltc/pk/ecc/ecc_get_set.c
@@ -0,0 +1,40 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+
+#include "tomcrypt.h"
+
+#ifdef LTC_MECC
+
+int ecc_get_set_by_name(const char* name, const ltc_ecc_set_type** dp)
+{
+ int i;
+
+ LTC_ARGCHK(dp != NULL);
+ LTC_ARGCHK(name != NULL);
+
+ *dp = NULL;
+
+ for (i = 0; ltc_ecc_sets[i].name != NULL; i++) {
+ if (XSTRCMP(ltc_ecc_sets[i].name, name) == 0) break;
+ }
+
+ if (ltc_ecc_sets[i].name == NULL) {
+ /* not found */
+ return CRYPT_INVALID_ARG;
+ }
+
+ *dp = &ltc_ecc_sets[i];
+ return CRYPT_OK;
+}
+
+#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/ecc/ecc_get_size.c b/src/ltc/pk/ecc/ecc_get_size.c
index f77ab8b3..8d1c9362 100644
--- a/src/ltc/pk/ecc/ecc_get_size.c
+++ b/src/ltc/pk/ecc/ecc_get_size.c
@@ -7,9 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
#include "tomcrypt.h"
/**
@@ -26,11 +23,10 @@
*/
int ecc_get_size(ecc_key *key)
{
- LTC_ARGCHK(key != NULL);
- if (ltc_ecc_is_valid_idx(key->idx))
- return key->dp->size;
- else
- return INT_MAX; /* large value known to cause it to fail when passed to ecc_make_key() */
+ if (key == NULL) {
+ return INT_MAX;
+ }
+ return key->dp.size;
}
#endif
diff --git a/src/ltc/pk/ecc/ecc_import.c b/src/ltc/pk/ecc/ecc_import.c
index 38465b12..3a1dcc57 100644
--- a/src/ltc/pk/ecc/ecc_import.c
+++ b/src/ltc/pk/ecc/ecc_import.c
@@ -7,9 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
#include "tomcrypt.h"
/**
@@ -49,18 +46,20 @@ int ecc_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, co
LTC_ARGCHK(key != NULL);
LTC_ARGCHK(ltc_mp.name != NULL);
- /* init key */
- if (mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, NULL) != CRYPT_OK) {
- return CRYPT_MEM;
- }
-
/* find out what type of key it is */
- err = der_decode_sequence_multi(in, inlen, LTC_ASN1_BIT_STRING, 1UL, flags,
- LTC_ASN1_EOL, 0UL, NULL);
+ err = der_decode_sequence_multi(in, inlen, LTC_ASN1_BIT_STRING, 1UL, flags,
+ LTC_ASN1_SHORT_INTEGER, 1UL, &key_size,
+ LTC_ASN1_EOL, 0UL, NULL);
if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) {
- goto done;
+ return err;
}
+ /* allocate & initialize the key */
+ if (dp == NULL) {
+ if ((err = ecc_set_dp_size(key_size, key)) != CRYPT_OK) { goto done; }
+ } else {
+ if ((err = ecc_set_dp(dp, key)) != CRYPT_OK) { goto done; }
+ }
if (flags[0] == 1) {
/* private key */
@@ -91,30 +90,17 @@ int ecc_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, co
goto done;
}
- if (dp == NULL) {
- /* find the idx */
- for (key->idx = 0; ltc_ecc_sets[key->idx].size && (unsigned long)ltc_ecc_sets[key->idx].size != key_size; ++key->idx);
- if (ltc_ecc_sets[key->idx].size == 0) {
- err = CRYPT_INVALID_PACKET;
- goto done;
- }
- key->dp = &ltc_ecc_sets[key->idx];
- } else {
- key->idx = -1;
- key->dp = dp;
- }
/* set z */
if ((err = mp_set(key->pubkey.z, 1)) != CRYPT_OK) { goto done; }
- /* is it a point on the curve? */
- if ((err = ltc_ecc_is_point(key->dp, key->pubkey.x, key->pubkey.y)) != CRYPT_OK) {
- goto done;
- }
+ /* point on the curve + other checks */
+ if ((err = ltc_ecc_verify_key(key)) != CRYPT_OK) { goto done; }
/* we're good */
return CRYPT_OK;
+
done:
- mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL);
+ ecc_free(key);
return err;
}
#endif
diff --git a/src/ltc/pk/ecc/ecc_import_full.c b/src/ltc/pk/ecc/ecc_import_full.c
deleted file mode 100644
index 0e5093d4..00000000
--- a/src/ltc/pk/ecc/ecc_import_full.c
+++ /dev/null
@@ -1,152 +0,0 @@
-/* LibTomCrypt, modular cryptographic library -- Tom St Denis
- *
- * LibTomCrypt is a library that provides various cryptographic
- * algorithms in a highly modular and flexible manner.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- */
-
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
-
-#include "tomcrypt.h"
-
-#ifdef LTC_MECC
-
-int ecc_import_full(const unsigned char *in, unsigned long inlen, ecc_key *key, ltc_ecc_set_type *dp)
-{
- void *prime, *order, *a, *b, *gx, *gy;
- ltc_asn1_list seq_fieldid[2], seq_curve[3], seq_ecparams[6], seq_priv[4];
- unsigned char bin_a[ECC_MAXSIZE], bin_b[ECC_MAXSIZE], bin_k[ECC_MAXSIZE], bin_g[2*ECC_MAXSIZE+1], bin_xy[2*ECC_MAXSIZE+2], bin_seed[128];
- unsigned long len_a, len_b, len_k, len_g, len_xy, len_oid;
- unsigned long cofactor = 0, ecver = 0, pkver = 0, tmpoid[16], curveoid[16];
- int err;
-
- if ((err = mp_init_multi(&prime, &order, &a, &b, &gx, &gy, NULL)) != CRYPT_OK) return err;
-
- /* ### 1. try to load public key - no curve parameters just curve OID */
-
- len_xy = sizeof(bin_xy);
- err = der_decode_subject_public_key_info_ex(in, inlen, PKA_EC, bin_xy, &len_xy, LTC_ASN1_OBJECT_IDENTIFIER, curveoid, 16UL, &len_oid);
- if (err == CRYPT_OK) {
- /* load curve parameters for given curve OID */
- if ((err = ecc_dp_set_by_oid(dp, curveoid, len_oid)) != CRYPT_OK) { goto error; }
- /* load public key */
- if ((err = ecc_import_raw(bin_xy, len_xy, key, dp)) != CRYPT_OK) { goto error; }
- goto success;
- }
-
- /* ### 2. try to load public key - curve parameters included */
-
- /* ECParameters SEQUENCE */
- LTC_SET_ASN1(seq_ecparams, 0, LTC_ASN1_SHORT_INTEGER, &ecver, 1UL);
- LTC_SET_ASN1(seq_ecparams, 1, LTC_ASN1_SEQUENCE, seq_fieldid, 2UL);
- LTC_SET_ASN1(seq_ecparams, 2, LTC_ASN1_SEQUENCE, seq_curve, 3UL);
- LTC_SET_ASN1(seq_ecparams, 3, LTC_ASN1_OCTET_STRING, bin_g, (unsigned long)2*ECC_MAXSIZE+1);
- LTC_SET_ASN1(seq_ecparams, 4, LTC_ASN1_INTEGER, order, 1UL);
- LTC_SET_ASN1(seq_ecparams, 5, LTC_ASN1_SHORT_INTEGER, &cofactor, 1UL);
- seq_ecparams[5].optional = 1;
- /* FieldID SEQUENCE */
- LTC_SET_ASN1(seq_fieldid, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, 16UL);
- LTC_SET_ASN1(seq_fieldid, 1, LTC_ASN1_INTEGER, prime, 1UL);
- /* Curve SEQUENCE */
- LTC_SET_ASN1(seq_curve, 0, LTC_ASN1_OCTET_STRING, bin_a, (unsigned long)ECC_MAXSIZE);
- LTC_SET_ASN1(seq_curve, 1, LTC_ASN1_OCTET_STRING, bin_b, (unsigned long)ECC_MAXSIZE);
- LTC_SET_ASN1(seq_curve, 2, LTC_ASN1_RAW_BIT_STRING, bin_seed, (unsigned long)8*128);
- seq_curve[2].optional = 1;
- /* try to load public key */
- len_xy = sizeof(bin_xy);
- err = der_decode_subject_public_key_info(in, inlen, PKA_EC, bin_xy, &len_xy, LTC_ASN1_SEQUENCE, seq_ecparams, 6);
-
- if (err == CRYPT_OK) {
- len_a = seq_curve[0].size;
- len_b = seq_curve[1].size;
- len_g = seq_ecparams[3].size;
- /* create bignums */
- if ((err = mp_read_unsigned_bin(a, bin_a, len_a)) != CRYPT_OK) { goto error; }
- if ((err = mp_read_unsigned_bin(b, bin_b, len_b)) != CRYPT_OK) { goto error; }
- if ((err = ltc_ecc_import_point(bin_g, len_g, prime, a, b, gx, gy)) != CRYPT_OK) { goto error; }
- /* load curve parameters */
- if ((err = ecc_dp_set_bn(dp, a, b, prime, order, gx, gy, cofactor)) != CRYPT_OK) { goto error; }
- /* load public key */
- if ((err = ecc_import_raw(bin_xy, len_xy, key, dp)) != CRYPT_OK) { goto error; }
- goto success;
- }
-
- /* ### 3. try to load private key - no curve parameters just curve OID */
-
- /* ECPrivateKey SEQUENCE */
- LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER, &pkver, 1UL);
- LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING, bin_k, (unsigned long)ECC_MAXSIZE);
- LTC_SET_ASN1(seq_priv, 2, LTC_ASN1_OBJECT_IDENTIFIER, curveoid, 16UL);
- LTC_SET_ASN1(seq_priv, 3, LTC_ASN1_RAW_BIT_STRING, bin_xy, (unsigned long)8*(2*ECC_MAXSIZE+2));
- seq_priv[2].tag = 0xA0; /* context specific 0 */
- seq_priv[3].tag = 0xA1; /* context specific 1 */
- /* try to load private key */
- err = der_decode_sequence(in, inlen, seq_priv, 4);
-
- if (err == CRYPT_OK) {
- /* load curve parameters for given curve OID */
- if ((err = ecc_dp_set_by_oid(dp, curveoid, seq_priv[2].size)) != CRYPT_OK) { goto error; }
- /* load private+public key */
- if ((err = ecc_import_raw(bin_k, seq_priv[1].size, key, dp)) != CRYPT_OK) { goto error; }
- goto success;
- }
-
- /* ### 4. try to load private key - curve parameters included */
-
- /* ECPrivateKey SEQUENCE */
- LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER, &pkver, 1UL);
- LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING, bin_k, (unsigned long)ECC_MAXSIZE);
- LTC_SET_ASN1(seq_priv, 2, LTC_ASN1_SEQUENCE, seq_ecparams, 6UL);
- LTC_SET_ASN1(seq_priv, 3, LTC_ASN1_RAW_BIT_STRING, bin_xy, (unsigned long)8*(2*ECC_MAXSIZE+2));
- seq_priv[2].tag = 0xA0; /* context specific 0 */
- seq_priv[3].tag = 0xA1; /* context specific 1 */
- /* ECParameters SEQUENCE */
- LTC_SET_ASN1(seq_ecparams, 0, LTC_ASN1_SHORT_INTEGER, &ecver, 1UL);
- LTC_SET_ASN1(seq_ecparams, 1, LTC_ASN1_SEQUENCE, seq_fieldid, 2UL);
- LTC_SET_ASN1(seq_ecparams, 2, LTC_ASN1_SEQUENCE, seq_curve, 3UL);
- LTC_SET_ASN1(seq_ecparams, 3, LTC_ASN1_OCTET_STRING, bin_g, (unsigned long)2*ECC_MAXSIZE+1);
- LTC_SET_ASN1(seq_ecparams, 4, LTC_ASN1_INTEGER, order, 1UL);
- LTC_SET_ASN1(seq_ecparams, 5, LTC_ASN1_SHORT_INTEGER, &cofactor, 1UL);
- seq_ecparams[5].optional = 1;
- /* FieldID SEQUENCE */
- LTC_SET_ASN1(seq_fieldid, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, 16UL);
- LTC_SET_ASN1(seq_fieldid, 1, LTC_ASN1_INTEGER, prime, 1UL);
- /* Curve SEQUENCE */
- LTC_SET_ASN1(seq_curve, 0, LTC_ASN1_OCTET_STRING, bin_a, (unsigned long)ECC_MAXSIZE);
- LTC_SET_ASN1(seq_curve, 1, LTC_ASN1_OCTET_STRING, bin_b, (unsigned long)ECC_MAXSIZE);
- LTC_SET_ASN1(seq_curve, 2, LTC_ASN1_RAW_BIT_STRING, bin_seed, (unsigned long)8*128);
- seq_curve[2].optional = 1;
- /* try to load private key */
- err = der_decode_sequence(in, inlen, seq_priv, 4);
- if (err == CRYPT_OK) {
- len_k = seq_priv[1].size;
- len_xy = seq_priv[3].size;
- len_a = seq_curve[0].size;
- len_b = seq_curve[1].size;
- len_g = seq_ecparams[3].size;
- /* create bignums */
- if ((err = mp_read_unsigned_bin(a, bin_a, len_a)) != CRYPT_OK) { goto error; }
- if ((err = mp_read_unsigned_bin(b, bin_b, len_b)) != CRYPT_OK) { goto error; }
- if ((err = ltc_ecc_import_point(bin_g, len_g, prime, a, b, gx, gy)) != CRYPT_OK) { goto error; }
- /* load curve parameters */
- if ((err = ecc_dp_set_bn(dp, a, b, prime, order, gx, gy, cofactor)) != CRYPT_OK) { goto error; }
- /* load private+public key */
- if ((err = ecc_import_raw(bin_k, len_k, key, dp)) != CRYPT_OK) { goto error; }
- goto success;
- }
-
- /* ### 5. backward compatibility - try to load old-DER format */
- if ((err = ecc_import(in, inlen, key)) != CRYPT_OK) { goto error; }
-
-success:
- err = CRYPT_OK;
-error:
- mp_clear_multi(prime, order, a, b, gx, gy, NULL);
- return err;
-}
-
-#endif
diff --git a/src/ltc/pk/ecc/ecc_import_openssl.c b/src/ltc/pk/ecc/ecc_import_openssl.c
new file mode 100644
index 00000000..abbf5052
--- /dev/null
+++ b/src/ltc/pk/ecc/ecc_import_openssl.c
@@ -0,0 +1,157 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+
+#include "tomcrypt.h"
+
+#ifdef LTC_MECC
+
+int ecc_import_openssl(const unsigned char *in, unsigned long inlen, ecc_key *key)
+{
+ void *prime, *order, *a, *b, *gx, *gy;
+ ltc_asn1_list seq_fieldid[2], seq_curve[3], seq_ecparams[6], seq_priv[4], custom[2];
+ unsigned char bin_a[ECC_MAXSIZE], bin_b[ECC_MAXSIZE], bin_k[ECC_MAXSIZE], bin_g[2*ECC_MAXSIZE+1], bin_xy[2*ECC_MAXSIZE+2], bin_seed[128];
+ unsigned long len_a, len_b, len_k, len_g, len_xy, len_oid, len;
+ unsigned long cofactor = 0, ecver = 0, pkver = 0, tmpoid[16], curveoid[16];
+ int err;
+
+ if ((err = mp_init_multi(&prime, &order, &a, &b, &gx, &gy, NULL)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* ### 1. try to load public key - no curve parameters just curve OID */
+
+ len_xy = sizeof(bin_xy);
+ len_oid = 16;
+ err = x509_decode_subject_public_key_info(in, inlen, PKA_EC, bin_xy, &len_xy, LTC_ASN1_OBJECT_IDENTIFIER, curveoid, &len_oid);
+ if (err == CRYPT_OK) {
+ /* load curve parameters for given curve OID */
+ if ((err = ecc_set_dp_oid(curveoid, len_oid, key)) != CRYPT_OK) { goto error; }
+ /* load public key */
+ if ((err = ecc_set_key(bin_xy, len_xy, PK_PUBLIC, key)) != CRYPT_OK) { goto error; }
+ goto success;
+ }
+
+ /* ### 2. try to load public key - curve parameters included */
+
+ /* ECParameters SEQUENCE */
+ LTC_SET_ASN1(seq_ecparams, 0, LTC_ASN1_SHORT_INTEGER, &ecver, 1UL);
+ LTC_SET_ASN1(seq_ecparams, 1, LTC_ASN1_SEQUENCE, seq_fieldid, 2UL);
+ LTC_SET_ASN1(seq_ecparams, 2, LTC_ASN1_SEQUENCE, seq_curve, 3UL);
+ LTC_SET_ASN1(seq_ecparams, 3, LTC_ASN1_OCTET_STRING, bin_g, (unsigned long)2*ECC_MAXSIZE+1);
+ LTC_SET_ASN1(seq_ecparams, 4, LTC_ASN1_INTEGER, order, 1UL);
+ LTC_SET_ASN1(seq_ecparams, 5, LTC_ASN1_SHORT_INTEGER, &cofactor, 1UL);
+ seq_ecparams[5].optional = 1;
+ /* FieldID SEQUENCE */
+ LTC_SET_ASN1(seq_fieldid, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, 16UL);
+ LTC_SET_ASN1(seq_fieldid, 1, LTC_ASN1_INTEGER, prime, 1UL);
+ /* Curve SEQUENCE */
+ LTC_SET_ASN1(seq_curve, 0, LTC_ASN1_OCTET_STRING, bin_a, (unsigned long)ECC_MAXSIZE);
+ LTC_SET_ASN1(seq_curve, 1, LTC_ASN1_OCTET_STRING, bin_b, (unsigned long)ECC_MAXSIZE);
+ LTC_SET_ASN1(seq_curve, 2, LTC_ASN1_RAW_BIT_STRING, bin_seed, (unsigned long)8*128);
+ seq_curve[2].optional = 1;
+ /* try to load public key */
+ len_xy = sizeof(bin_xy);
+ len = 6;
+ err = x509_decode_subject_public_key_info(in, inlen, PKA_EC, bin_xy, &len_xy, LTC_ASN1_SEQUENCE, seq_ecparams, &len);
+
+ if (err == CRYPT_OK) {
+ len_a = seq_curve[0].size;
+ len_b = seq_curve[1].size;
+ len_g = seq_ecparams[3].size;
+ /* create bignums */
+ if ((err = mp_read_unsigned_bin(a, bin_a, len_a)) != CRYPT_OK) { goto error; }
+ if ((err = mp_read_unsigned_bin(b, bin_b, len_b)) != CRYPT_OK) { goto error; }
+ if ((err = ltc_ecc_import_point(bin_g, len_g, prime, a, b, gx, gy)) != CRYPT_OK) { goto error; }
+ /* load curve parameters */
+ if ((err = ecc_set_dp_bn(a, b, prime, order, gx, gy, cofactor, key)) != CRYPT_OK) { goto error; }
+ /* load public key */
+ if ((err = ecc_set_key(bin_xy, len_xy, PK_PUBLIC, key)) != CRYPT_OK) { goto error; }
+ goto success;
+ }
+
+ /* ### 3. try to load private key - no curve parameters just curve OID */
+
+ /* ECPrivateKey SEQUENCE */
+ LTC_SET_ASN1(custom, 0, LTC_ASN1_OBJECT_IDENTIFIER, curveoid, 16UL);
+ LTC_SET_ASN1(custom, 1, LTC_ASN1_RAW_BIT_STRING, bin_xy, (unsigned long)8*(2*ECC_MAXSIZE+2));
+ LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER, &pkver, 1UL);
+ LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING, bin_k, (unsigned long)ECC_MAXSIZE);
+ LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 2, LTC_ASN1_CL_CONTEXT_SPECIFIC, 0, custom); /* context specific 0 */
+ LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 3, LTC_ASN1_CL_CONTEXT_SPECIFIC, 1, custom + 1); /* context specific 1 */
+
+ /* try to load private key */
+ err = der_decode_sequence(in, inlen, seq_priv, 4);
+ if (err == CRYPT_OK) {
+ /* load curve parameters for given curve OID */
+ if ((err = ecc_set_dp_oid(curveoid, custom[0].size, key)) != CRYPT_OK) { goto error; }
+ /* load private+public key */
+ if ((err = ecc_set_key(bin_k, seq_priv[1].size, PK_PRIVATE, key)) != CRYPT_OK) { goto error; }
+ goto success;
+ }
+
+ /* ### 4. try to load private key - curve parameters included */
+
+ /* ECPrivateKey SEQUENCE */
+ LTC_SET_ASN1(custom, 0, LTC_ASN1_SEQUENCE, seq_ecparams, 6UL);
+ LTC_SET_ASN1(custom, 1, LTC_ASN1_RAW_BIT_STRING, bin_xy, (unsigned long)8*(2*ECC_MAXSIZE+2));
+ LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER, &pkver, 1UL);
+ LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING, bin_k, (unsigned long)ECC_MAXSIZE);
+ LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 2, LTC_ASN1_CL_CONTEXT_SPECIFIC, 0, custom); /* context specific 0 */
+ LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 3, LTC_ASN1_CL_CONTEXT_SPECIFIC, 1, custom + 1); /* context specific 1 */
+ /* ECParameters SEQUENCE */
+ LTC_SET_ASN1(seq_ecparams, 0, LTC_ASN1_SHORT_INTEGER, &ecver, 1UL);
+ LTC_SET_ASN1(seq_ecparams, 1, LTC_ASN1_SEQUENCE, seq_fieldid, 2UL);
+ LTC_SET_ASN1(seq_ecparams, 2, LTC_ASN1_SEQUENCE, seq_curve, 3UL);
+ LTC_SET_ASN1(seq_ecparams, 3, LTC_ASN1_OCTET_STRING, bin_g, (unsigned long)2*ECC_MAXSIZE+1);
+ LTC_SET_ASN1(seq_ecparams, 4, LTC_ASN1_INTEGER, order, 1UL);
+ LTC_SET_ASN1(seq_ecparams, 5, LTC_ASN1_SHORT_INTEGER, &cofactor, 1UL);
+ seq_ecparams[5].optional = 1;
+ /* FieldID SEQUENCE */
+ LTC_SET_ASN1(seq_fieldid, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, 16UL);
+ LTC_SET_ASN1(seq_fieldid, 1, LTC_ASN1_INTEGER, prime, 1UL);
+ /* Curve SEQUENCE */
+ LTC_SET_ASN1(seq_curve, 0, LTC_ASN1_OCTET_STRING, bin_a, (unsigned long)ECC_MAXSIZE);
+ LTC_SET_ASN1(seq_curve, 1, LTC_ASN1_OCTET_STRING, bin_b, (unsigned long)ECC_MAXSIZE);
+ LTC_SET_ASN1(seq_curve, 2, LTC_ASN1_RAW_BIT_STRING, bin_seed, (unsigned long)8*128);
+ seq_curve[2].optional = 1;
+ /* try to load private key */
+ err = der_decode_sequence(in, inlen, seq_priv, 4);
+ if (err == CRYPT_OK) {
+ len_xy = custom[1].size;
+ len_k = seq_priv[1].size;
+ len_a = seq_curve[0].size;
+ len_b = seq_curve[1].size;
+ len_g = seq_ecparams[3].size;
+ /* create bignums */
+ if ((err = mp_read_unsigned_bin(a, bin_a, len_a)) != CRYPT_OK) { goto error; }
+ if ((err = mp_read_unsigned_bin(b, bin_b, len_b)) != CRYPT_OK) { goto error; }
+ if ((err = ltc_ecc_import_point(bin_g, len_g, prime, a, b, gx, gy)) != CRYPT_OK) { goto error; }
+ /* load curve parameters */
+ if ((err = ecc_set_dp_bn(a, b, prime, order, gx, gy, cofactor, key)) != CRYPT_OK) { goto error; }
+ /* load private+public key */
+ if ((err = ecc_set_key(bin_k, len_k, PK_PRIVATE, key)) != CRYPT_OK) { goto error; }
+ goto success;
+ }
+
+ /* ### 5. backward compatibility - try to load old-DER format */
+
+ if ((err = ecc_import(in, inlen, key)) != CRYPT_OK) { goto error; }
+
+success:
+ err = CRYPT_OK;
+error:
+ mp_clear_multi(prime, order, a, b, gx, gy, NULL);
+ return err;
+}
+
+#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/ecc/ecc_import_pkcs8.c b/src/ltc/pk/ecc/ecc_import_pkcs8.c
index 85f8d218..6b5b0c71 100644
--- a/src/ltc/pk/ecc/ecc_import_pkcs8.c
+++ b/src/ltc/pk/ecc/ecc_import_pkcs8.c
@@ -7,153 +7,597 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
-
#include "tomcrypt.h"
#ifdef LTC_MECC
-int ecc_import_pkcs8(const unsigned char *in, unsigned long inlen,
- const void *pwd, unsigned long pwdlen,
- ecc_key *key, ltc_ecc_set_type *dp)
+enum algorithm_oid {
+ PBE_MD2_DES, /* 0 */
+ PBE_MD2_RC2,
+ PBE_MD5_DES,
+ PBE_MD5_RC2,
+ PBE_SHA1_DES,
+ PBE_SHA1_RC2, /* 5 */
+ PBES2,
+ PBKDF2,
+ DES_CBC,
+ RC2_CBC,
+ DES_EDE3_CBC, /* 10 */
+ HMAC_WITH_SHA1,
+ HMAC_WITH_SHA224,
+ HMAC_WITH_SHA256,
+ HMAC_WITH_SHA384,
+ HMAC_WITH_SHA512, /* 15 */
+ PBE_SHA1_3DES
+};
+
+static const oid_st oid_list[] = {
+ { { 1,2,840,113549,1,5,1 }, 7 }, /* [0] http://www.oid-info.com/get/1.2.840.113549.1.5.1 pbeWithMD2AndDES-CBC */
+ { { 1,2,840,113549,1,5,4 }, 7 }, /* [1] http://www.oid-info.com/get/1.2.840.113549.1.5.4 pbeWithMD2AndRC2-CBC */
+ { { 1,2,840,113549,1,5,3 }, 7 }, /* [2] http://www.oid-info.com/get/1.2.840.113549.1.5.3 pbeWithMD5AndDES-CBC */
+ { { 1,2,840,113549,1,5,6 }, 7 }, /* [3] http://www.oid-info.com/get/1.2.840.113549.1.5.6 pbeWithMD5AndRC2-CBC */
+ { { 1,2,840,113549,1,5,10 }, 7 }, /* [4] http://www.oid-info.com/get/1.2.840.113549.1.5.10 pbeWithSHA1AndDES-CBC */
+ { { 1,2,840,113549,1,5,11 }, 7 }, /* [5] http://www.oid-info.com/get/1.2.840.113549.1.5.11 pbeWithSHA1AndRC2-CBC */
+ { { 1,2,840,113549,1,5,13 }, 7 }, /* [6] http://www.oid-info.com/get/1.2.840.113549.1.5.13 pbes2 */
+ { { 1,2,840,113549,1,5,12 }, 7 }, /* [7] http://www.oid-info.com/get/1.2.840.113549.1.5.12 pBKDF2 */
+ { { 1,3,14,3,2,7 }, 6 }, /* [8] http://www.oid-info.com/get/1.3.14.3.2.7 desCBC */
+ { { 1,2,840,113549,3,2 }, 6 }, /* [9] http://www.oid-info.com/get/1.2.840.113549.3.2 rc2CBC */
+ { { 1,2,840,113549,3,7 }, 6 }, /* [10] http://www.oid-info.com/get/1.2.840.113549.3.7 des-EDE3-CBC */
+ { { 1,2,840,113549,2,7 }, 6 }, /* [11] http://www.oid-info.com/get/1.2.840.113549.2.7 hmacWithSHA1 */
+ { { 1,2,840,113549,2,8 }, 6 }, /* [12] http://www.oid-info.com/get/1.2.840.113549.2.8 hmacWithSHA224 */
+ { { 1,2,840,113549,2,9 }, 6 }, /* [13] http://www.oid-info.com/get/1.2.840.113549.2.9 hmacWithSHA256 */
+ { { 1,2,840,113549,2,10 }, 6 }, /* [14] http://www.oid-info.com/get/1.2.840.113549.2.10 hmacWithSHA384 */
+ { { 1,2,840,113549,2,11 }, 6 }, /* [15] http://www.oid-info.com/get/1.2.840.113549.2.11 hmacWithSHA512 */
+ { { 1,2,840,113549,1,12,1,3 }, 8 }, /* [16] http://www.oid-info.com/get/1.2.840.113549.1.12.1.3 pbeWithSHAAnd3-KeyTripleDES-CBC */
+ { { 0 }, 0 },
+};
+
+static int _simple_utf8_to_utf16(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen) {
+ unsigned long len = 0;
+ const unsigned char* in_end = in + inlen;
+ const ulong32 offset[6] = {
+ 0x00000000UL, 0x00003080UL, 0x000E2080UL,
+ 0x03C82080UL, 0xFA082080UL, 0x82082080UL
+ };
+ int err = CRYPT_ERROR;
+
+ while (in < in_end) {
+ ulong32 ch = 0;
+ unsigned short extra = 0; /* 0 */
+ if (*in >= 192) extra++; /* 1 */
+ if (*in >= 224) extra++; /* 2 */
+ if (*in >= 240) extra++; /* 3 */
+ if (*in >= 248) extra++; /* 4 */
+ if (*in >= 252) extra++; /* 5 */
+ if (in + extra >= in_end) goto ERROR;
+ switch (extra) {
+ case 5: ch += *in++; ch <<= 6;
+ case 4: ch += *in++; ch <<= 6;
+ case 3: ch += *in++; ch <<= 6;
+ case 2: ch += *in++; ch <<= 6;
+ case 1: ch += *in++; ch <<= 6;
+ case 0: ch += *in++;
+ }
+ ch -= offset[extra];
+ if (ch > 0xFFFF) goto ERROR;
+ if (*outlen >= len + 2) {
+ out[len] = (unsigned short)((ch >> 8) & 0xFF);
+ out[len + 1] = (unsigned char)(ch & 0xFF);
+ }
+ len += 2;
+ }
+
+ err = len > *outlen ? CRYPT_BUFFER_OVERFLOW : CRYPT_OK;
+ *outlen = len;
+ERROR:
+ return err;
+}
+
+static int _kdf_pkcs12(int hash_id, const unsigned char *pw, unsigned long pwlen,
+ const unsigned char *salt, unsigned long saltlen,
+ unsigned int iterations, unsigned char purpose,
+ unsigned char *out, unsigned long outlen)
{
- int err;
- void *zero, *one, *iter;
- unsigned char *buf1=NULL, *buf2=NULL;
- unsigned long buf1len, buf2len;
- unsigned long oid[16];
- oid_st ecoid;
- ltc_asn1_list alg_seq[2], top_seq[3];
- ltc_asn1_list alg_seq_e[2], key_seq_e[2], top_seq_e[2];
- unsigned char *decrypted=NULL;
- unsigned long decryptedlen;
- void *prime, *order, *a, *b, *gx, *gy;
- ltc_asn1_list seq_fieldid[2], seq_curve[3], seq_ecparams[6], seq_priv[4];
- unsigned char bin_a[ECC_MAXSIZE], bin_b[ECC_MAXSIZE], bin_k[ECC_MAXSIZE], bin_g[2*ECC_MAXSIZE+1], bin_xy[2*ECC_MAXSIZE+2], bin_seed[128];
- unsigned long len_a, len_b, len_g;
- unsigned long cofactor = 0, ecver = 0, tmpoid[16], curveoid[16];
+ unsigned long u = hash_descriptor[hash_id].hashsize;
+ unsigned long v = hash_descriptor[hash_id].blocksize;
+ unsigned long c = (outlen + u - 1) / u;
+ unsigned long Slen = ((saltlen + v - 1) / v) * v;
+ unsigned long Plen = ((pwlen + v - 1) / v) * v;
+ unsigned long k = (Plen + Slen) / v;
+ unsigned long Alen, keylen = 0;
+ unsigned int tmp, i, j, n;
+ unsigned char ch;
+ unsigned char D[MAXBLOCKSIZE], A[MAXBLOCKSIZE], B[MAXBLOCKSIZE];
+ unsigned char *I = NULL, *key = NULL;
+ int err = CRYPT_ERROR;
- LTC_ARGCHK(in != NULL);
- LTC_ARGCHK(key != NULL);
- LTC_ARGCHK(ltc_mp.name != NULL);
+ key = XMALLOC(u * c);
+ I = XMALLOC(Plen + Slen);
+ if (key == NULL || I == NULL) goto DONE;
- /* get EC alg oid */
- err = pk_get_oid(PKA_EC, &ecoid);
- if (err != CRYPT_OK) { goto LBL_NOFREE; }
+ for (i = 0; i < v; i++) D[i] = purpose; /* D - diversifier */
+ for (i = 0; i < Slen; i++) I[i] = salt[i % saltlen];
+ for (i = 0; i < Plen; i++) I[Slen + i] = pw[i % pwlen]; /* I = Salt || Pass */
+
+ for (i = 0; i < c; i++) {
+ Alen = u; /* hash size */
+ err = hash_memory_multi(hash_id, A, &Alen, D, v, I, Slen + Plen, NULL); /* A = HASH(D || I) */
+ if (err != CRYPT_OK) goto DONE;
+ for (j = 1; j < iterations; j++) {
+ err = hash_memory(hash_id, A, Alen, A, &Alen); /* A = HASH(A) */
+ if (err != CRYPT_OK) goto DONE;
+ }
+ /* fill buffer B with A */
+ for (j = 0; j < v; j++) B[j] = A[j % Alen];
+ /* B += 1 */
+ for (j = v; j > 0; j--) {
+ if (++B[j - 1] != 0) break;
+ }
+ /* I_n += B */
+ for (n = 0; n < k; n++) {
+ ch = 0;
+ for (j = v; j > 0; j--) {
+ tmp = I[n * v + j - 1] + B[j - 1] + ch;
+ ch = (unsigned char)((tmp >> 8) & 0xFF);
+ I[n * v + j - 1] = (unsigned char)(tmp & 0xFF);
+ }
+ }
+ /* store derived key block */
+ for (j = 0; j < Alen; j++) key[keylen++] = A[j];
+ }
- /* alloc buffers */
- buf1len = inlen; /* approx. guess */
- buf1 = XMALLOC(buf1len);
- if (buf1 == NULL) { err = CRYPT_MEM; goto LBL_NOFREE; }
- buf2len = inlen; /* approx. guess */
- buf2 = XMALLOC(buf2len);
- if (buf2 == NULL) { err = CRYPT_MEM; goto LBL_FREE; }
+ for (i = 0; i < outlen; i++) out[i] = key[i];
+ err = CRYPT_OK;
+DONE:
+ if (I) XFREE(I);
+ if (key) XFREE(key);
+ return err;
+}
- /* init key */
- err = mp_init_multi(&prime, &order, &a, &b, &gx, &gy, &zero, &one, &iter, NULL);
- if (err != CRYPT_OK) { goto LBL_NOCLEAR; }
-
- /* try to decode encrypted priv key */
- LTC_SET_ASN1(key_seq_e, 0, LTC_ASN1_OCTET_STRING, buf1, buf1len);
- LTC_SET_ASN1(key_seq_e, 1, LTC_ASN1_INTEGER, iter, 1UL);
- LTC_SET_ASN1(alg_seq_e, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, 16UL);
- LTC_SET_ASN1(alg_seq_e, 1, LTC_ASN1_SEQUENCE, key_seq_e, 2UL);
- LTC_SET_ASN1(top_seq_e, 0, LTC_ASN1_SEQUENCE, alg_seq_e, 2UL);
- LTC_SET_ASN1(top_seq_e, 1, LTC_ASN1_OCTET_STRING, buf2, buf2len);
- err=der_decode_sequence(in, inlen, top_seq_e, 2UL);
- if (err == CRYPT_OK) {
- LTC_UNUSED_PARAM(pwd);
- LTC_UNUSED_PARAM(pwdlen);
- /* unsigned long icount = mp_get_int(iter); */
- /* XXX: TODO decrypt buf1 with a key derived form password + salt + iter */
- /* fprintf(stderr, "XXX-DEBUG: gonna decrypt: iter=%ld salt.len=%ld encdata.len=%ld\n", icount, key_seq_e[0].size, top_seq_e[1].size); */
- err = CRYPT_PK_INVALID_TYPE;
- goto LBL_ERR;
+static int _oid_to_id(const unsigned long *oid, unsigned long oid_size)
+{
+ int i, j;
+ for (j = 0; oid_list[j].OIDlen > 0; j++) {
+ int match = 1;
+ if (oid_list[j].OIDlen != oid_size) continue;
+ for (i = 0; i < (int)oid_size && match; i++) if (oid_list[j].OID[i] != oid[i]) match = 0;
+ if (match) return j;
}
- else {
- decrypted = (unsigned char*)in;
- decryptedlen = inlen;
+ return -1;
+}
+
+static int _pbes1_decrypt(const unsigned char *enc_data, unsigned long enc_size,
+ const unsigned char *pass, unsigned long pass_size,
+ const unsigned char *salt, unsigned long salt_size,
+ unsigned long iterations,
+ const unsigned long *oid, unsigned long oid_size,
+ unsigned char *dec_data, unsigned long *dec_size)
+{
+ int id = _oid_to_id(oid, oid_size);
+ int err, hid = -1, cid = -1;
+ unsigned int keylen, blklen;
+ unsigned char key_iv[32] = { 0 }, pad;
+ unsigned long len = sizeof(key_iv), pwlen = pass_size;
+ symmetric_CBC cbc;
+ unsigned char *pw = NULL;
+
+ /* https://tools.ietf.org/html/rfc8018#section-6.1.2 */
+ if (id == PBE_MD2_DES || id == PBE_MD2_RC2) hid = find_hash("md2");
+ if (id == PBE_MD5_DES || id == PBE_MD5_RC2) hid = find_hash("md5");
+ if (id == PBE_SHA1_DES || id == PBE_SHA1_RC2 || id == PBE_SHA1_3DES) hid = find_hash("sha1");
+
+ if (id == PBE_MD2_RC2 || id == PBE_MD5_RC2 || id == PBE_SHA1_RC2) {
+ cid = find_cipher("rc2");
+ keylen = 8;
+ blklen = 8;
+ }
+ if (id == PBE_MD2_DES || id == PBE_MD5_DES || id == PBE_SHA1_DES) {
+ cid = find_cipher("des");
+ keylen = 8;
+ blklen = 8;
+ }
+ if (id == PBE_SHA1_3DES) {
+ cid = find_cipher("3des");
+ keylen = 24;
+ blklen = 8;
}
- /* try to decode unencrypted priv key - curve defined by OID */
- LTC_SET_ASN1(alg_seq, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, 16UL);
- LTC_SET_ASN1(alg_seq, 1, LTC_ASN1_OBJECT_IDENTIFIER, curveoid, 16UL);
- LTC_SET_ASN1(top_seq, 0, LTC_ASN1_INTEGER, zero, 1UL);
- LTC_SET_ASN1(top_seq, 1, LTC_ASN1_SEQUENCE, alg_seq, 2UL);
- LTC_SET_ASN1(top_seq, 2, LTC_ASN1_OCTET_STRING, buf1, buf1len);
- err=der_decode_sequence(decrypted, decryptedlen, top_seq, 3UL);
- if (err == CRYPT_OK) {
- /* load curve parameters for given curve OID */
- err = ecc_dp_set_by_oid(dp, curveoid, alg_seq[1].size);
- if (err != CRYPT_OK) { goto LBL_ERR; }
+ if (id == PBE_SHA1_3DES) {
+ /* convert password to unicode/utf16-be */
+ pwlen = pass_size * 2;
+ pw = XMALLOC(pwlen + 2);
+ if (pw == NULL) goto LBL_ERROR;
+ if ((err = _simple_utf8_to_utf16(pass, pass_size, pw, &pwlen) != CRYPT_OK)) goto LBL_ERROR;
+ pw[pwlen++] = 0;
+ pw[pwlen++] = 0;
+ /* derive KEY */
+ if ((err = _kdf_pkcs12(hid, pw, pwlen, salt, salt_size, iterations, 1, key_iv, keylen)) != CRYPT_OK) goto LBL_ERROR;
+ /* derive IV */
+ if ((err = _kdf_pkcs12(hid, pw, pwlen, salt, salt_size, iterations, 2, key_iv+24, blklen)) != CRYPT_OK) goto LBL_ERROR;
}
else {
- /* try to decode unencrypted priv key - curve defined by params */
- /* ECParameters SEQUENCE */
- LTC_SET_ASN1(seq_ecparams, 0, LTC_ASN1_SHORT_INTEGER, &ecver, 1UL);
- LTC_SET_ASN1(seq_ecparams, 1, LTC_ASN1_SEQUENCE, seq_fieldid, 2UL);
- LTC_SET_ASN1(seq_ecparams, 2, LTC_ASN1_SEQUENCE, seq_curve, 3UL);
- LTC_SET_ASN1(seq_ecparams, 3, LTC_ASN1_OCTET_STRING, bin_g, (unsigned long)2*ECC_MAXSIZE+1);
- LTC_SET_ASN1(seq_ecparams, 4, LTC_ASN1_INTEGER, order, 1UL);
- LTC_SET_ASN1(seq_ecparams, 5, LTC_ASN1_SHORT_INTEGER, &cofactor, 1UL);
- seq_ecparams[5].optional = 1;
- /* FieldID SEQUENCE */
- LTC_SET_ASN1(seq_fieldid, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, 16UL);
- LTC_SET_ASN1(seq_fieldid, 1, LTC_ASN1_INTEGER, prime, 1UL);
- /* Curve SEQUENCE */
- LTC_SET_ASN1(seq_curve, 0, LTC_ASN1_OCTET_STRING, bin_a, (unsigned long)ECC_MAXSIZE);
- LTC_SET_ASN1(seq_curve, 1, LTC_ASN1_OCTET_STRING, bin_b, (unsigned long)ECC_MAXSIZE);
- LTC_SET_ASN1(seq_curve, 2, LTC_ASN1_RAW_BIT_STRING, bin_seed, (unsigned long)8*128);
- /* */
- LTC_SET_ASN1(alg_seq, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, 16UL);
- LTC_SET_ASN1(alg_seq, 1, LTC_ASN1_SEQUENCE, seq_ecparams, 6UL);
- LTC_SET_ASN1(top_seq, 0, LTC_ASN1_INTEGER, zero, 1UL);
- LTC_SET_ASN1(top_seq, 1, LTC_ASN1_SEQUENCE, alg_seq, 2UL);
- LTC_SET_ASN1(top_seq, 2, LTC_ASN1_OCTET_STRING, buf1, buf1len);
- seq_curve[2].optional = 1;
- err=der_decode_sequence(decrypted, decryptedlen, top_seq, 3UL);
- if (err != CRYPT_OK) { goto LBL_ERR; }
- len_a = seq_curve[0].size;
- len_b = seq_curve[1].size;
- len_g = seq_ecparams[3].size;
- /* create bignums */
- if ((err = mp_read_unsigned_bin(a, bin_a, len_a)) != CRYPT_OK) { goto LBL_ERR; }
- if ((err = mp_read_unsigned_bin(b, bin_b, len_b)) != CRYPT_OK) { goto LBL_ERR; }
- if ((err = ltc_ecc_import_point(bin_g, len_g, prime, a, b, gx, gy)) != CRYPT_OK) { goto LBL_ERR; }
- /* load curve parameters */
- if ((err = ecc_dp_set_bn(dp, a, b, prime, order, gx, gy, cofactor)) != CRYPT_OK) { goto LBL_ERR; }
+ if ((err = pkcs_5_alg1(pass, pass_size, salt, iterations, hid, key_iv, &len)) != CRYPT_OK) goto LBL_ERROR;
+ /* the output has 16 bytes: [KEY-8-bytes][IV-8-bytes] */
}
- /* check alg oid */
- if ((alg_seq[0].size != ecoid.OIDlen) ||
- XMEMCMP(ecoid.OID, alg_seq[0].data, ecoid.OIDlen * sizeof(ecoid.OID[0]))) {
- err = CRYPT_PK_INVALID_TYPE;
- goto LBL_ERR;
+ if (hid != -1 && cid != -1) {
+ if (salt_size != 8 || enc_size < blklen) goto LBL_ERROR;
+ if ((err = cbc_start(cid, key_iv + keylen, key_iv, keylen, 0, &cbc)) != CRYPT_OK) goto LBL_ERROR;
+ if ((err = cbc_decrypt(enc_data, dec_data, enc_size, &cbc)) != CRYPT_OK) goto LBL_ERROR;
+ if ((err = cbc_done(&cbc)) != CRYPT_OK) goto LBL_ERROR;
+ pad = dec_data[enc_size-1];
+ if (pad < 1 || pad > blklen) goto LBL_ERROR;
+ *dec_size = enc_size - pad;
+ return CRYPT_OK;
}
- /* ECPrivateKey SEQUENCE */
- LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER, &one, 1UL);
- LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING, bin_k, (unsigned long)ECC_MAXSIZE);
- LTC_SET_ASN1(seq_priv, 2, LTC_ASN1_RAW_BIT_STRING, bin_xy, (unsigned long)8*(2*ECC_MAXSIZE+2));
- seq_priv[2].tag = 0xA1; /* context specific 1 */
- /* try to load private key */
- err = der_decode_sequence(buf1, top_seq[2].size, seq_priv, 3);
- if (err != CRYPT_OK) { goto LBL_ERR; }
- /* load private+public key */
- if ((err = ecc_import_raw(bin_k, seq_priv[1].size, key, dp)) != CRYPT_OK) { goto LBL_ERR; }
- /* success */
+LBL_ERROR:
+ zeromem(key_iv, sizeof(key_iv));
+ if (pw) { zeromem(pw, pwlen); XFREE(pw); }
+ return CRYPT_INVALID_ARG;
+}
+
+static int _pbes2_pbkdf2_decrypt(const unsigned char *enc_data, unsigned long enc_size,
+ const unsigned char *pass, unsigned long pass_size,
+ const unsigned char *salt, unsigned long salt_size,
+ const unsigned char *iv, unsigned long iv_size,
+ unsigned long iterations,
+ int hmacid,
+ int encid,
+ int extra_arg,
+ unsigned char *dec_data, unsigned long *dec_size)
+{
+ int err, hid = -1, cid = -1;
+ unsigned char k[32], pad;
+ unsigned long klen = sizeof(k);
+ symmetric_CBC cbc;
+
+ /* https://tools.ietf.org/html/rfc8018#section-6.2.2 */
+
+ if (hmacid == HMAC_WITH_SHA1) hid = find_hash("sha1");
+ if (hmacid == HMAC_WITH_SHA224) hid = find_hash("sha224");
+ if (hmacid == HMAC_WITH_SHA256) hid = find_hash("sha256");
+ if (hmacid == HMAC_WITH_SHA384) hid = find_hash("sha384");
+ if (hmacid == HMAC_WITH_SHA512) hid = find_hash("sha512");
+ if (hid == -1) return CRYPT_INVALID_ARG;
+
+ if (encid == DES_EDE3_CBC) {
+ /* https://tools.ietf.org/html/rfc8018#appendix-B.2.2 */
+ cid = find_cipher("3des");
+ klen = 24;
+ if (klen > sizeof(k) || iv_size != 8 || iv == NULL || cid == -1) goto LBL_ERROR;
+ if ((err = pkcs_5_alg2(pass, pass_size, salt, salt_size, iterations, hid, k, &klen)) != CRYPT_OK) goto LBL_ERROR;
+ if ((err = cbc_start(cid, iv, k, klen, 0, &cbc)) != CRYPT_OK) goto LBL_ERROR;
+ if ((err = cbc_decrypt(enc_data, dec_data, enc_size, &cbc)) != CRYPT_OK) goto LBL_ERROR;
+ if ((err = cbc_done(&cbc)) != CRYPT_OK) goto LBL_ERROR;
+ pad = dec_data[enc_size-1];
+ if (pad < 1 || pad > 8) goto LBL_ERROR;
+ *dec_size = enc_size - pad;
+ return CRYPT_OK;
+ }
+
+ if (encid == DES_CBC) {
+ /* https://tools.ietf.org/html/rfc8018#appendix-B.2.1 */
+ cid = find_cipher("des");
+ klen = 8; /* 64 bits */
+ if (klen > sizeof(k) || iv_size != 8 || iv == NULL || cid == -1) goto LBL_ERROR;
+ if ((err = pkcs_5_alg2(pass, pass_size, salt, salt_size, iterations, hid, k, &klen)) != CRYPT_OK) goto LBL_ERROR;
+ if ((err = cbc_start(cid, iv, k, klen, 0, &cbc)) != CRYPT_OK) goto LBL_ERROR;
+ if ((err = cbc_decrypt(enc_data, dec_data, enc_size, &cbc)) != CRYPT_OK) goto LBL_ERROR;
+ if ((err = cbc_done(&cbc)) != CRYPT_OK) goto LBL_ERROR;
+ pad = dec_data[enc_size-1];
+ if (pad < 1 || pad > 8) goto LBL_ERROR;
+ *dec_size = enc_size - pad;
+ return CRYPT_OK;
+ }
+
+ if (encid == RC2_CBC) {
+ /* https://tools.ietf.org/html/rfc8018#appendix-B.2.3 */
+ cid = find_cipher("rc2");
+ klen = 4; /* default: 32 bits */
+ if (extra_arg == 160) klen = 5;
+ if (extra_arg == 120) klen = 8;
+ if (extra_arg == 58) klen = 16;
+ if (extra_arg >= 256) klen = extra_arg / 8;
+ if (klen > sizeof(k) || iv_size != 8 || iv == NULL || cid == -1) goto LBL_ERROR;
+ if ((err = pkcs_5_alg2(pass, pass_size, salt, salt_size, iterations, hid, k, &klen)) != CRYPT_OK) goto LBL_ERROR;
+ if ((err = cbc_start(cid, iv, k, klen, 0, &cbc)) != CRYPT_OK) goto LBL_ERROR;
+ if ((err = cbc_decrypt(enc_data, dec_data, enc_size, &cbc)) != CRYPT_OK) goto LBL_ERROR;
+ if ((err = cbc_done(&cbc)) != CRYPT_OK) goto LBL_ERROR;
+ pad = dec_data[enc_size-1];
+ if (pad < 1 || pad > 8) goto LBL_ERROR;
+ *dec_size = enc_size - pad;
+ return CRYPT_OK;
+ }
+
+LBL_ERROR:
+ zeromem(k, sizeof(k));
+ return CRYPT_INVALID_ARG;
+}
+
+static int _der_decode_pkcs8_flexi(const unsigned char *in, unsigned long inlen,
+ const void *pwd, unsigned long pwdlen,
+ ltc_asn1_list **decoded_list)
+{
+ unsigned long len = inlen;
+ unsigned long dec_size;
+ unsigned char *dec_data = NULL;
+ ltc_asn1_list *l = NULL;
+ int err;
+
+ *decoded_list = NULL;
+ if ((err = der_decode_sequence_flexi(in, &len, &l)) == CRYPT_OK) {
+ /* the following "if" detects whether it is encrypted or not */
+ if (l->type == LTC_ASN1_SEQUENCE &&
+ l->child && l->child->type == LTC_ASN1_SEQUENCE &&
+ l->child->child && l->child->child->type == LTC_ASN1_OBJECT_IDENTIFIER &&
+ l->child->child->next && l->child->child->next->type == LTC_ASN1_SEQUENCE &&
+ l->child->next && l->child->next->type == LTC_ASN1_OCTET_STRING) {
+ ltc_asn1_list *lalgoid = l->child->child;
+ ltc_asn1_list *lalgparam = l->child->child->next;
+ unsigned char *enc_data = l->child->next->data;
+ unsigned long enc_size = l->child->next->size;
+ dec_size = enc_size;
+ if ((dec_data = XMALLOC(dec_size)) == NULL) {
+ err = CRYPT_MEM;
+ goto LBL_DONE;
+ }
+ if (lalgparam->child && lalgparam->child->type == LTC_ASN1_OCTET_STRING &&
+ lalgparam->child->next && lalgparam->child->next->type == LTC_ASN1_INTEGER) {
+ /* PBES1: encrypted pkcs8 - pbeWithMD5AndDES-CBC:
+ * 0:d=0 hl=4 l= 329 cons: SEQUENCE
+ * 4:d=1 hl=2 l= 27 cons: SEQUENCE (== *lalg)
+ * 6:d=2 hl=2 l= 9 prim: OBJECT :pbeWithMD5AndDES-CBC (== 1.2.840.113549.1.5.3)
+ * 17:d=2 hl=2 l= 14 cons: SEQUENCE (== *lalgparam)
+ * 19:d=3 hl=2 l= 8 prim: OCTET STRING [HEX DUMP]:8EDF749A06CCDE51 (== salt)
+ * 29:d=3 hl=2 l= 2 prim: INTEGER :0800 (== iterations)
+ * 33:d=1 hl=4 l= 296 prim: OCTET STRING :bytes (== encrypted data)
+ */
+ unsigned long iter = mp_get_int(lalgparam->child->next->data);
+ unsigned long salt_size = lalgparam->child->size;
+ unsigned char *salt = lalgparam->child->data;
+ err = _pbes1_decrypt(enc_data, enc_size, pwd, pwdlen, salt, salt_size, iter, lalgoid->data, lalgoid->size, dec_data, &dec_size);
+ if (err != CRYPT_OK) goto LBL_DONE;
+ }
+ else if (PBES2 == _oid_to_id(lalgoid->data, lalgoid->size) &&
+ lalgparam->child && lalgparam->child->type == LTC_ASN1_SEQUENCE &&
+ lalgparam->child->child && lalgparam->child->child->type == LTC_ASN1_OBJECT_IDENTIFIER &&
+ lalgparam->child->child->next && lalgparam->child->child->next->type == LTC_ASN1_SEQUENCE &&
+ lalgparam->child->next && lalgparam->child->next->type == LTC_ASN1_SEQUENCE &&
+ lalgparam->child->next->child && lalgparam->child->next->child->type == LTC_ASN1_OBJECT_IDENTIFIER) {
+ /* PBES2: encrypted pkcs8 - PBES2+PBKDF2+des-ede3-cbc:
+ * 0:d=0 hl=4 l= 380 cons: SEQUENCE
+ * 4:d=1 hl=2 l= 78 cons: SEQUENCE (== *lalg)
+ * 6:d=2 hl=2 l= 9 prim: OBJECT :PBES2 (== 1.2.840.113549.1.5.13)
+ * 17:d=2 hl=2 l= 65 cons: SEQUENCE (== *lalgparam)
+ * 19:d=3 hl=2 l= 41 cons: SEQUENCE
+ * 21:d=4 hl=2 l= 9 prim: OBJECT :PBKDF2
+ * 32:d=4 hl=2 l= 28 cons: SEQUENCE
+ * 34:d=5 hl=2 l= 8 prim: OCTET STRING [HEX DUMP]:28BA4ABF6AA76A3D (== salt)
+ * 44:d=5 hl=2 l= 2 prim: INTEGER :0800 (== iterations)
+ * 48:d=5 hl=2 l= 12 cons: SEQUENCE (this sequence is optional, may be missing)
+ * 50:d=6 hl=2 l= 8 prim: OBJECT :hmacWithSHA256
+ * 60:d=6 hl=2 l= 0 prim: NULL
+ * 62:d=3 hl=2 l= 20 cons: SEQUENCE
+ * 64:d=4 hl=2 l= 8 prim: OBJECT :des-ede3-cbc
+ * 74:d=4 hl=2 l= 8 prim: OCTET STRING [HEX DUMP]:B1404C4688DC9A5A
+ * 84:d=1 hl=4 l= 296 prim: OCTET STRING :bytes (== encrypted data)
+ */
+ ltc_asn1_list *lkdf = lalgparam->child->child;
+ ltc_asn1_list *lenc = lalgparam->child->next->child;
+ int kdfid = _oid_to_id(lkdf->data, lkdf->size);
+ int encid = _oid_to_id(lenc->data, lenc->size);
+ if (PBKDF2 == kdfid &&
+ lkdf->next && lkdf->next->type == LTC_ASN1_SEQUENCE &&
+ lkdf->next->child && lkdf->next->child->type == LTC_ASN1_OCTET_STRING &&
+ lkdf->next->child->next && lkdf->next->child->next->type == LTC_ASN1_INTEGER) {
+ unsigned long iter = mp_get_int(lkdf->next->child->next->data);
+ unsigned long salt_size = lkdf->next->child->size;
+ unsigned char *salt = lkdf->next->child->data;
+ unsigned char *iv = NULL;
+ unsigned long iv_size = 0;
+ unsigned long arg = 0;
+ ltc_asn1_list *loptseq = lkdf->next->child->next->next;
+ int hmacid = HMAC_WITH_SHA1; /* this is default */
+ if (loptseq && loptseq->type == LTC_ASN1_SEQUENCE &&
+ loptseq->child && loptseq->child->type == LTC_ASN1_OBJECT_IDENTIFIER) {
+ /* this sequence is optional */
+ hmacid = _oid_to_id(loptseq->child->data, loptseq->child->size);
+ }
+ if (lenc->next && lenc->next->type == LTC_ASN1_OCTET_STRING) {
+ /* DES-CBC + DES_EDE3_CBC */
+ iv = lenc->next->data;
+ iv_size = lenc->next->size;
+ }
+ else if (lenc->next && lenc->next->type == LTC_ASN1_SEQUENCE &&
+ lenc->next->child && lenc->next->child->type == LTC_ASN1_INTEGER &&
+ lenc->next->child->next && lenc->next->child->next->type == LTC_ASN1_OCTET_STRING) {
+ /* RC2-CBC is a bit special */
+ iv = lenc->next->child->next->data;
+ iv_size = lenc->next->child->next->size;
+ arg = mp_get_int(lenc->next->child->data);
+ }
+ err = _pbes2_pbkdf2_decrypt(enc_data, enc_size, pwd, pwdlen, salt, salt_size, iv, iv_size, iter, hmacid, encid, arg, dec_data, &dec_size);
+ if (err != CRYPT_OK) goto LBL_DONE;
+ }
+ else {
+ /* non-PBKDF2 algorithms are not supported */
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_DONE;
+ }
+ }
+ else {
+ /* unsupported encryption */
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_DONE;
+ }
+ der_free_sequence_flexi(l);
+ l = NULL;
+ err = der_decode_sequence_flexi(dec_data, &dec_size, &l);
+ if (err != CRYPT_OK) goto LBL_DONE;
+ *decoded_list = l;
+ }
+ else {
+ /* not encrypted */
+ err = CRYPT_OK;
+ *decoded_list = l;
+ }
+ }
+
+LBL_DONE:
+ if (dec_data) XFREE(dec_data);
return err;
+}
+
+/* NOTE: _der_decode_pkcs8_flexi & related stuff can be shared with rsa_import_pkcs8() */
-LBL_ERR:
- mp_clear_multi(prime, order, a, b, gx, gy, NULL);
-LBL_NOCLEAR:
- XFREE(buf2);
-LBL_FREE:
- XFREE(buf1);
-LBL_NOFREE:
+int ecc_import_pkcs8(const unsigned char *in, unsigned long inlen,
+ const void *pwd, unsigned long pwdlen,
+ ecc_key *key)
+{
+ void *a, *b, *gx, *gy;
+ unsigned long len, cofactor;
+ oid_st ecoid;
+ int err;
+ ltc_asn1_list *p = NULL, *l = NULL;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(ltc_mp.name != NULL);
+
+ /* get EC alg oid */
+ err = pk_get_oid(PKA_EC, &ecoid);
+ if (err != CRYPT_OK) return err;
+
+ /* init key */
+ err = mp_init_multi(&a, &b, &gx, &gy, NULL);
+ if (err != CRYPT_OK) return err;
+
+ if ((err = _der_decode_pkcs8_flexi(in, inlen, pwd, pwdlen, &l)) == CRYPT_OK) {
+ if (l->type == LTC_ASN1_SEQUENCE &&
+ l->child && l->child->type == LTC_ASN1_INTEGER &&
+ l->child->next && l->child->next->type == LTC_ASN1_SEQUENCE &&
+ l->child->next->child && l->child->next->child->type == LTC_ASN1_OBJECT_IDENTIFIER &&
+ l->child->next->next && l->child->next->next->type == LTC_ASN1_OCTET_STRING) {
+ ltc_asn1_list *lseq = l->child->next;
+ ltc_asn1_list *lpri = l->child->next->next;
+ ltc_asn1_list *lecoid = l->child->next->child;
+
+ if ((lecoid->size != ecoid.OIDlen) ||
+ XMEMCMP(ecoid.OID, lecoid->data, ecoid.OIDlen * sizeof(ecoid.OID[0]))) {
+ err = CRYPT_PK_INVALID_TYPE;
+ goto LBL_DONE;
+ }
+
+ if (lseq->child->next && lseq->child->next->type == LTC_ASN1_OBJECT_IDENTIFIER) {
+ /* CASE 1: curve by OID (AKA short variant):
+ * 0:d=0 hl=2 l= 100 cons: SEQUENCE
+ * 2:d=1 hl=2 l= 1 prim: INTEGER :00
+ * 5:d=1 hl=2 l= 16 cons: SEQUENCE (== *lseq)
+ * 7:d=2 hl=2 l= 7 prim: OBJECT :id-ecPublicKey
+ * 16:d=2 hl=2 l= 5 prim: OBJECT :secp256k1 (== 1.3.132.0.10)
+ * 23:d=1 hl=2 l= 77 prim: OCTET STRING :bytes (== privatekey)
+ */
+ ltc_asn1_list *loid = lseq->child->next;
+ if ((err = ecc_set_dp_oid(loid->data, loid->size, key)) != CRYPT_OK) {
+ goto LBL_DONE;
+ }
+ }
+ else if (lseq->child->next && lseq->child->next->type == LTC_ASN1_SEQUENCE) {
+ /* CASE 2: explicit curve parameters (AKA long variant):
+ * 0:d=0 hl=3 l= 227 cons: SEQUENCE
+ * 3:d=1 hl=2 l= 1 prim: INTEGER :00
+ * 6:d=1 hl=3 l= 142 cons: SEQUENCE (== *lseq)
+ * 9:d=2 hl=2 l= 7 prim: OBJECT :id-ecPublicKey
+ * 18:d=2 hl=3 l= 130 cons: SEQUENCE (== *lcurve)
+ * 21:d=3 hl=2 l= 1 prim: INTEGER :01
+ * 24:d=3 hl=2 l= 44 cons: SEQUENCE (== *lfield)
+ * 26:d=4 hl=2 l= 7 prim: OBJECT :prime-field
+ * 35:d=4 hl=2 l= 33 prim: INTEGER :(== curve.prime)
+ * 70:d=3 hl=2 l= 6 cons: SEQUENCE (== *lpoint)
+ * 72:d=4 hl=2 l= 1 prim: OCTET STRING :bytes (== curve.A)
+ * 75:d=4 hl=2 l= 1 prim: OCTET STRING :bytes (== curve.B)
+ * 78:d=3 hl=2 l= 33 prim: OCTET STRING :bytes (== curve.G-point)
+ * 113:d=3 hl=2 l= 33 prim: INTEGER :(== curve.order)
+ * 148:d=3 hl=2 l= 1 prim: INTEGER :(== curve.cofactor)
+ * 151:d=1 hl=2 l= 77 prim: OCTET STRING :bytes (== privatekey)
+ */
+ ltc_asn1_list *lcurve = lseq->child->next;
+
+ if (lcurve->child && lcurve->child->type == LTC_ASN1_INTEGER &&
+ lcurve->child->next && lcurve->child->next->type == LTC_ASN1_SEQUENCE &&
+ lcurve->child->next->next && lcurve->child->next->next->type == LTC_ASN1_SEQUENCE &&
+ lcurve->child->next->next->next && lcurve->child->next->next->next->type == LTC_ASN1_OCTET_STRING &&
+ lcurve->child->next->next->next->next && lcurve->child->next->next->next->next->type == LTC_ASN1_INTEGER &&
+ lcurve->child->next->next->next->next->next && lcurve->child->next->next->next->next->next->type == LTC_ASN1_INTEGER) {
+
+ ltc_asn1_list *lfield = lcurve->child->next;
+ ltc_asn1_list *lpoint = lcurve->child->next->next;
+ ltc_asn1_list *lg = lcurve->child->next->next->next;
+ ltc_asn1_list *lorder = lcurve->child->next->next->next->next;
+ cofactor = mp_get_int(lcurve->child->next->next->next->next->next->data);
+
+ if (lfield->child && lfield->child->type == LTC_ASN1_OBJECT_IDENTIFIER &&
+ lfield->child->next && lfield->child->next->type == LTC_ASN1_INTEGER &&
+ lpoint->child && lpoint->child->type == LTC_ASN1_OCTET_STRING &&
+ lpoint->child->next && lpoint->child->next->type == LTC_ASN1_OCTET_STRING) {
+
+ ltc_asn1_list *lprime = lfield->child->next;
+ if ((err = mp_read_unsigned_bin(a, lpoint->child->data, lpoint->child->size)) != CRYPT_OK) {
+ goto LBL_DONE;
+ }
+ if ((err = mp_read_unsigned_bin(b, lpoint->child->next->data, lpoint->child->next->size)) != CRYPT_OK) {
+ goto LBL_DONE;
+ }
+ if ((err = ltc_ecc_import_point(lg->data, lg->size, lprime->data, a, b, gx, gy)) != CRYPT_OK) {
+ goto LBL_DONE;
+ }
+ if ((err = ecc_set_dp_bn(a, b, lprime->data, lorder->data, gx, gy, cofactor, key)) != CRYPT_OK) {
+ goto LBL_DONE;
+ }
+ }
+ }
+ }
+ else {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_DONE;
+ }
+
+ /* load private key value 'k' */
+ len = lpri->size;
+ if ((err = der_decode_sequence_flexi(lpri->data, &len, &p)) == CRYPT_OK) {
+ err = CRYPT_INVALID_PACKET;
+ if (p->type == LTC_ASN1_SEQUENCE &&
+ p->child && p->child->type == LTC_ASN1_INTEGER &&
+ p->child->next && p->child->next->type == LTC_ASN1_OCTET_STRING) {
+ ltc_asn1_list *lk = p->child->next;
+ if (mp_cmp_d(p->child->data, 1) != LTC_MP_EQ) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ECCFREE;
+ }
+ if ((err = ecc_set_key(lk->data, lk->size, PK_PRIVATE, key)) != CRYPT_OK) {
+ goto LBL_ECCFREE;
+ }
+ goto LBL_DONE; /* success */
+ }
+ }
+ }
+ }
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_DONE;
+
+LBL_ECCFREE:
+ ecc_free(key);
+LBL_DONE:
+ mp_clear_multi(a, b, gx, gy, NULL);
+ if (l) der_free_sequence_flexi(l);
+ if (p) der_free_sequence_flexi(p);
return err;
}
#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/ecc/ecc_import_raw.c b/src/ltc/pk/ecc/ecc_import_raw.c
deleted file mode 100644
index 1ea4bb1e..00000000
--- a/src/ltc/pk/ecc/ecc_import_raw.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/* LibTomCrypt, modular cryptographic library -- Tom St Denis
- *
- * LibTomCrypt is a library that provides various cryptographic
- * algorithms in a highly modular and flexible manner.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- */
-
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
-
-#include "tomcrypt.h"
-
-#ifdef LTC_MECC
-
-/** Import raw public or private key (public keys = ANSI X9.63 compressed or uncompressed; private keys = raw bytes)
- @param in The input data to read
- @param inlen The length of the input data
- @param key [out] destination to store imported key
- @param dp Curve parameters
- Return CRYPT_OK on success
-*/
-
-int ecc_import_raw(const unsigned char *in, unsigned long inlen, ecc_key *key, ltc_ecc_set_type *dp)
-{
- int err, type = -1;
- unsigned long size = 0;
- void *prime, *a, *b;
- ecc_point *base;
-
- LTC_ARGCHK(in != NULL);
- LTC_ARGCHK(key != NULL);
- LTC_ARGCHK(dp != NULL);
-
- /* init key + temporary numbers */
- if (mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, &prime, &a, &b, NULL) != CRYPT_OK) {
- return CRYPT_MEM;
- }
-
- if (inlen <= (unsigned long)dp->size) {
- /* read PRIVATE key */
- type = PK_PRIVATE;
- size = inlen;
- /* load private k */
- if ((err = mp_read_unsigned_bin(key->k, (unsigned char *)in, size)) != CRYPT_OK) {
- goto cleanup;
- }
- if (mp_iszero(key->k)) {
- err = CRYPT_INVALID_PACKET;
- goto cleanup;
- }
- /* init base point */
- if ((base = ltc_ecc_new_point()) == NULL) {
- err = CRYPT_MEM;
- goto cleanup;
- }
- /* load prime + base point */
- if ((err = mp_read_radix(prime, dp->prime, 16)) != CRYPT_OK) { goto cleanup; }
- if ((err = mp_read_radix(base->x, dp->Gx, 16)) != CRYPT_OK) { goto cleanup; }
- if ((err = mp_read_radix(base->y, dp->Gy, 16)) != CRYPT_OK) { goto cleanup; }
- if ((err = mp_set(base->z, 1)) != CRYPT_OK) { goto cleanup; }
- /* make the public key */
- if ((err = mp_read_radix(a, dp->A, 16)) != CRYPT_OK) { goto cleanup; }
- if ((err = ltc_mp.ecc_ptmul(key->k, base, &key->pubkey, a, prime, 1)) != CRYPT_OK) { goto cleanup; }
- /* cleanup */
- ltc_ecc_del_point(base);
- }
- else {
- /* read PUBLIC key */
- type = PK_PUBLIC;
- /* load prime + A + B */
- if ((err = mp_read_radix(prime, dp->prime, 16)) != CRYPT_OK) { goto cleanup; }
- if ((err = mp_read_radix(b, dp->B, 16)) != CRYPT_OK) { goto cleanup; }
- if ((err = mp_read_radix(a, dp->A, 16)) != CRYPT_OK) { goto cleanup; }
- err = ltc_ecc_import_point(in, inlen, prime, a, b, key->pubkey.x, key->pubkey.y);
- if (err != CRYPT_OK) { goto cleanup; }
- if ((err = mp_set(key->pubkey.z, 1)) != CRYPT_OK) { goto cleanup; }
- }
-
- if ((err = ltc_ecc_is_point(dp, key->pubkey.x, key->pubkey.y)) != CRYPT_OK) {
- err = CRYPT_INVALID_PACKET;
- goto cleanup;
- }
-
- key->type = type;
- key->idx = -1;
- key->dp = dp;
-
- /* we're done */
- mp_clear_multi(prime, a, b, NULL);
- return CRYPT_OK;
-cleanup:
- mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, prime, a, b, NULL);
- return err;
-}
-
-#endif
diff --git a/src/ltc/pk/ecc/ecc_import_x509.c b/src/ltc/pk/ecc/ecc_import_x509.c
new file mode 100644
index 00000000..e57b156f
--- /dev/null
+++ b/src/ltc/pk/ecc/ecc_import_x509.c
@@ -0,0 +1,59 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+#include "tomcrypt.h"
+
+#ifdef LTC_MECC
+
+/**
+ Import an ECC key from a X.509 certificate
+ @param in The packet to import from
+ @param inlen It's length (octets)
+ @param key [out] Destination for newly imported key
+ @return CRYPT_OK if successful, upon error allocated memory is freed
+*/
+int ecc_import_x509(const unsigned char *in, unsigned long inlen, ecc_key *key)
+{
+ int err;
+ unsigned long len;
+ ltc_asn1_list *decoded_list = NULL, *l;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ len = inlen;
+ if ((err = der_decode_sequence_flexi(in, &len, &decoded_list)) == CRYPT_OK) {
+ l = decoded_list;
+ if (l->type == LTC_ASN1_SEQUENCE &&
+ l->child && l->child->type == LTC_ASN1_SEQUENCE) {
+ err = CRYPT_ERROR;
+ l = l->child->child;
+ while (l) {
+ if (l->type == LTC_ASN1_SEQUENCE && l->data &&
+ l->child && l->child->type == LTC_ASN1_SEQUENCE &&
+ l->child->child && l->child->child->type == LTC_ASN1_OBJECT_IDENTIFIER &&
+ l->child->next && l->child->next->type == LTC_ASN1_BIT_STRING) {
+ err = ecc_import_openssl(l->data, l->size, key);
+ goto LBL_DONE;
+ }
+ l = l->next;
+ }
+ }
+ }
+
+LBL_DONE:
+ if (decoded_list) der_free_sequence_flexi(decoded_list);
+ return err;
+}
+
+#endif /* LTC_MECC */
+
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/ecc/ecc_make_key.c b/src/ltc/pk/ecc/ecc_make_key.c
index 0d89552e..4617befb 100644
--- a/src/ltc/pk/ecc/ecc_make_key.c
+++ b/src/ltc/pk/ecc/ecc_make_key.c
@@ -7,9 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
#include "tomcrypt.h"
/**
@@ -29,76 +26,34 @@
*/
int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key)
{
- /* BEWARE: Here we are looking up the curve params by keysize (neither curve name nor curve oid),
- * which might be ambiguous (there can more than one curve for given keysize).
- * Thus the chosen curve depends on order of items in ltc_ecc_sets[] - see ecc.c file.
- */
- int x, err;
+ int err;
- /* find key size */
- for (x = 0; (keysize > ltc_ecc_sets[x].size) && (ltc_ecc_sets[x].size != 0); x++);
- keysize = ltc_ecc_sets[x].size;
-
- if (keysize > ECC_MAXSIZE || ltc_ecc_sets[x].size == 0) {
- return CRYPT_INVALID_KEYSIZE;
- }
- err = ecc_make_key_ex(prng, wprng, key, &ltc_ecc_sets[x]);
- key->idx = x;
- return err;
+ if ((err = ecc_set_dp_size(keysize, key)) != CRYPT_OK) { return err; }
+ if ((err = ecc_generate_key(prng, wprng, key)) != CRYPT_OK) { return err; }
+ return CRYPT_OK;
}
int ecc_make_key_ex(prng_state *prng, int wprng, ecc_key *key, const ltc_ecc_set_type *dp)
{
+ int err;
+ if ((err = ecc_set_dp(dp, key)) != CRYPT_OK) { return err; }
+ if ((err = ecc_generate_key(prng, wprng, key)) != CRYPT_OK) { return err; }
+ return CRYPT_OK;
+}
+
+int ecc_generate_key(prng_state *prng, int wprng, ecc_key *key)
+{
int err;
- ecc_point *base;
- void *prime, *order, *a;
- unsigned char *buf;
- int keysize, orderbits;
- LTC_ARGCHK(key != NULL);
LTC_ARGCHK(ltc_mp.name != NULL);
- LTC_ARGCHK(dp != NULL);
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(key->dp.size > 0);
/* good prng? */
if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
return err;
}
- key->idx = -1;
- key->dp = dp;
- keysize = dp->size;
-
- /* allocate ram */
- base = NULL;
- buf = XMALLOC(ECC_MAXSIZE);
- if (buf == NULL) {
- return CRYPT_MEM;
- }
-
- /* make up random string */
- if (prng_descriptor[wprng].read(buf, (unsigned long)keysize, prng) != (unsigned long)keysize) {
- err = CRYPT_ERROR_READPRNG;
- goto ERR_BUF;
- }
-
- /* setup the key variables */
- if ((err = mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, &prime, &order, &a, NULL)) != CRYPT_OK) {
- goto ERR_BUF;
- }
- base = ltc_ecc_new_point();
- if (base == NULL) {
- err = CRYPT_MEM;
- goto errkey;
- }
-
- /* read in the specs for this key */
- if ((err = mp_read_radix(prime, (char *)key->dp->prime, 16)) != CRYPT_OK) { goto errkey; }
- if ((err = mp_read_radix(order, (char *)key->dp->order, 16)) != CRYPT_OK) { goto errkey; }
- if ((err = mp_read_radix(base->x, (char *)key->dp->Gx, 16)) != CRYPT_OK) { goto errkey; }
- if ((err = mp_read_radix(base->y, (char *)key->dp->Gy, 16)) != CRYPT_OK) { goto errkey; }
- if ((err = mp_set(base->z, 1)) != CRYPT_OK) { goto errkey; }
- if ((err = mp_read_unsigned_bin(key->k, (unsigned char *)buf, keysize)) != CRYPT_OK) { goto errkey; }
-
/* ECC key pair generation according to FIPS-186-4 (B.4.2 Key Pair Generation by Testing Candidates):
* the generated private key k should be the range [1, order-1]
* a/ N = bitlen(order)
@@ -106,29 +61,23 @@ int ecc_make_key_ex(prng_state *prng, int wprng, ecc_key *key, const ltc_ecc_set
* c/ if k not in [1, order-1] go to b/
* e/ Q = k*G
*/
- orderbits = mp_count_bits(order);
- do {
- if ((err = rand_bn_bits(key->k, orderbits, prng, wprng)) != CRYPT_OK) { goto errkey; }
- } while (mp_iszero(key->k) || mp_cmp(key->k, order) != LTC_MP_LT);
+ if ((err = rand_bn_upto(key->k, key->dp.order, prng, wprng)) != CRYPT_OK) {
+ goto error;
+ }
/* make the public key */
- if ((err = mp_read_radix(a, (char *)key->dp->A, 16)) != CRYPT_OK) { goto errkey; }
- if ((err = ltc_mp.ecc_ptmul(key->k, base, &key->pubkey, a, prime, 1)) != CRYPT_OK) { goto errkey; }
+ if ((err = ltc_mp.ecc_ptmul(key->k, &key->dp.base, &key->pubkey, key->dp.A, key->dp.prime, 1)) != CRYPT_OK) {
+ goto error;
+ }
key->type = PK_PRIVATE;
- /* free up ram */
+ /* success */
err = CRYPT_OK;
goto cleanup;
-errkey:
- mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL);
+
+error:
+ ecc_free(key);
cleanup:
- ltc_ecc_del_point(base);
- mp_clear_multi(prime, order, a, NULL);
-ERR_BUF:
-#ifdef LTC_CLEAN_STACK
- zeromem(buf, ECC_MAXSIZE);
-#endif
- XFREE(buf);
return err;
}
diff --git a/src/ltc/pk/ecc/ecc_set_dp.c b/src/ltc/pk/ecc/ecc_set_dp.c
new file mode 100644
index 00000000..17a0d2aa
--- /dev/null
+++ b/src/ltc/pk/ecc/ecc_set_dp.c
@@ -0,0 +1,97 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+
+#include "tomcrypt.h"
+
+#ifdef LTC_MECC
+
+int ecc_set_dp(const ltc_ecc_set_type *set, ecc_key *key)
+{
+ unsigned long i;
+ int err;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(set != NULL);
+
+ if ((err = mp_init_multi(&key->dp.prime, &key->dp.order, &key->dp.A, &key->dp.B,
+ &key->dp.base.x, &key->dp.base.y, &key->dp.base.z,
+ &key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k,
+ NULL)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* A, B, order, prime, Gx, Gy */
+ if ((err = mp_read_radix(key->dp.prime, set->prime, 16)) != CRYPT_OK) { goto error; }
+ if ((err = mp_read_radix(key->dp.order, set->order, 16)) != CRYPT_OK) { goto error; }
+ if ((err = mp_read_radix(key->dp.A, set->A, 16)) != CRYPT_OK) { goto error; }
+ if ((err = mp_read_radix(key->dp.B, set->B, 16)) != CRYPT_OK) { goto error; }
+ if ((err = mp_read_radix(key->dp.base.x, set->Gx, 16)) != CRYPT_OK) { goto error; }
+ if ((err = mp_read_radix(key->dp.base.y, set->Gy, 16)) != CRYPT_OK) { goto error; }
+ if ((err = mp_set(key->dp.base.z, 1)) != CRYPT_OK) { goto error; }
+ /* cofactor & size */
+ key->dp.cofactor = set->cofactor;
+ key->dp.size = mp_unsigned_bin_size(key->dp.prime);
+ /* OID */
+ key->dp.oidlen = set->oidlen;
+ for (i = 0; i < key->dp.oidlen; i++) key->dp.oid[i] = set->oid[i];
+ /* success */
+ return CRYPT_OK;
+
+error:
+ ecc_free(key);
+ return err;
+}
+
+int ecc_set_dp_size(int size, ecc_key *key)
+{
+ const ltc_ecc_set_type *dp = NULL;
+ int err;
+
+ /* for compatibility with libtomcrypt-1.17 the sizes below must match the specific curves */
+ if (size <= 14) {
+ if ((err = ecc_get_set_by_name("SECP112R1", &dp)) != CRYPT_OK) return err;
+ return ecc_set_dp(dp, key);
+ }
+ else if (size <= 16) {
+ if ((err = ecc_get_set_by_name("SECP128R1", &dp)) != CRYPT_OK) return err;
+ return ecc_set_dp(dp, key);
+ }
+ else if (size <= 20) {
+ if ((err = ecc_get_set_by_name("SECP160R1", &dp)) != CRYPT_OK) return err;
+ return ecc_set_dp(dp, key);
+ }
+ else if (size <= 24) {
+ if ((err = ecc_get_set_by_name("SECP192R1", &dp)) != CRYPT_OK) return err;
+ return ecc_set_dp(dp, key);
+ }
+ else if (size <= 28) {
+ if ((err = ecc_get_set_by_name("SECP224R1", &dp)) != CRYPT_OK) return err;
+ return ecc_set_dp(dp, key);
+ }
+ else if (size <= 32) {
+ if ((err = ecc_get_set_by_name("SECP256R1", &dp)) != CRYPT_OK) return err;
+ return ecc_set_dp(dp, key);
+ }
+ else if (size <= 48) {
+ if ((err = ecc_get_set_by_name("SECP384R1", &dp)) != CRYPT_OK) return err;
+ return ecc_set_dp(dp, key);
+ }
+ else if (size <= 66) {
+ if ((err = ecc_get_set_by_name("SECP521R1", &dp)) != CRYPT_OK) return err;
+ return ecc_set_dp(dp, key);
+ }
+
+ return CRYPT_INVALID_ARG;
+}
+
+#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/ecc/ecc_set_dp_internal.c b/src/ltc/pk/ecc/ecc_set_dp_internal.c
new file mode 100644
index 00000000..bd7c0403
--- /dev/null
+++ b/src/ltc/pk/ecc/ecc_set_dp_internal.c
@@ -0,0 +1,150 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+
+#include "tomcrypt.h"
+
+#ifdef LTC_MECC
+
+static void _ecc_oid_lookup(ecc_key *key)
+{
+ int err;
+ unsigned i;
+ void *tmp;
+ const ltc_ecc_set_type *set;
+
+ key->dp.oidlen = 0;
+ if ((err = mp_init(&tmp)) != CRYPT_OK) return;
+ for (set = ltc_ecc_sets; set->name != NULL; set++) {
+ if ((err = mp_read_radix(tmp, set->prime, 16)) != CRYPT_OK) continue;
+ if ((mp_cmp(tmp, key->dp.prime) != LTC_MP_EQ)) continue;
+ if ((err = mp_read_radix(tmp, set->order, 16)) != CRYPT_OK) continue;
+ if ((mp_cmp(tmp, key->dp.order) != LTC_MP_EQ)) continue;
+ if ((err = mp_read_radix(tmp, set->A, 16)) != CRYPT_OK) continue;
+ if ((mp_cmp(tmp, key->dp.A) != LTC_MP_EQ)) continue;
+ if ((err = mp_read_radix(tmp, set->B, 16)) != CRYPT_OK) continue;
+ if ((mp_cmp(tmp, key->dp.B) != LTC_MP_EQ)) continue;
+ if ((err = mp_read_radix(tmp, set->Gx, 16)) != CRYPT_OK) continue;
+ if ((mp_cmp(tmp, key->dp.base.x) != LTC_MP_EQ)) continue;
+ if ((err = mp_read_radix(tmp, set->Gy, 16)) != CRYPT_OK) continue;
+ if ((mp_cmp(tmp, key->dp.base.y) != LTC_MP_EQ)) continue;
+ if (key->dp.cofactor != set->cofactor) continue;
+ break; /* found */
+ }
+ mp_clear(tmp);
+ if (set->name != NULL) {
+ /* OID found */
+ key->dp.oidlen = set->oidlen;
+ for(i = 0; i < set->oidlen; i++) key->dp.oid[i] = set->oid[i];
+ }
+}
+
+int ecc_set_dp_oid(unsigned long *oid, unsigned long oidsize, ecc_key *key)
+{
+ int i;
+
+ LTC_ARGCHK(oid != NULL);
+ LTC_ARGCHK(oidsize > 0);
+
+ for(i = 0; ltc_ecc_sets[i].name != NULL; i++) {
+ if ((oidsize == ltc_ecc_sets[i].oidlen) &&
+ (XMEM_NEQ(oid, ltc_ecc_sets[i].oid, sizeof(unsigned long) * ltc_ecc_sets[i].oidlen) == 0)) {
+ break;
+ }
+ }
+ if (ltc_ecc_sets[i].name == NULL) return CRYPT_ERROR; /* not found */
+ return ecc_set_dp(&ltc_ecc_sets[i], key);
+}
+
+int ecc_set_dp_copy(ecc_key *srckey, ecc_key *key)
+{
+ unsigned long i;
+ int err;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(srckey != NULL);
+
+ if ((err = mp_init_multi(&key->dp.prime, &key->dp.order, &key->dp.A, &key->dp.B,
+ &key->dp.base.x, &key->dp.base.y, &key->dp.base.z,
+ &key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k,
+ NULL)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* A, B, order, prime, Gx, Gy */
+ if ((err = mp_copy(srckey->dp.prime, key->dp.prime )) != CRYPT_OK) { goto error; }
+ if ((err = mp_copy(srckey->dp.order, key->dp.order )) != CRYPT_OK) { goto error; }
+ if ((err = mp_copy(srckey->dp.A, key->dp.A )) != CRYPT_OK) { goto error; }
+ if ((err = mp_copy(srckey->dp.B, key->dp.B )) != CRYPT_OK) { goto error; }
+ if ((err = mp_copy(srckey->dp.base.x, key->dp.base.x)) != CRYPT_OK) { goto error; }
+ if ((err = mp_copy(srckey->dp.base.y, key->dp.base.y)) != CRYPT_OK) { goto error; }
+ if ((err = mp_copy(srckey->dp.base.z, key->dp.base.z)) != CRYPT_OK) { goto error; }
+ /* cofactor & size */
+ key->dp.cofactor = srckey->dp.cofactor;
+ key->dp.size = srckey->dp.size;
+ /* OID */
+ if (srckey->dp.oidlen > 0) {
+ key->dp.oidlen = srckey->dp.oidlen;
+ for (i = 0; i < key->dp.oidlen; i++) key->dp.oid[i] = srckey->dp.oid[i];
+ }
+ else {
+ _ecc_oid_lookup(key); /* try to find OID in ltc_ecc_sets */
+ }
+ /* success */
+ return CRYPT_OK;
+
+error:
+ ecc_free(key);
+ return err;
+}
+
+int ecc_set_dp_bn(void *a, void *b, void *prime, void *order, void *gx, void *gy, unsigned long cofactor, ecc_key *key)
+{
+ int err;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(a != NULL);
+ LTC_ARGCHK(b != NULL);
+ LTC_ARGCHK(prime != NULL);
+ LTC_ARGCHK(order != NULL);
+ LTC_ARGCHK(gx != NULL);
+ LTC_ARGCHK(gy != NULL);
+
+ if ((err = mp_init_multi(&key->dp.prime, &key->dp.order, &key->dp.A, &key->dp.B,
+ &key->dp.base.x, &key->dp.base.y, &key->dp.base.z,
+ &key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k,
+ NULL)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* A, B, order, prime, Gx, Gy */
+ if ((err = mp_copy(prime, key->dp.prime )) != CRYPT_OK) { goto error; }
+ if ((err = mp_copy(order, key->dp.order )) != CRYPT_OK) { goto error; }
+ if ((err = mp_copy(a, key->dp.A )) != CRYPT_OK) { goto error; }
+ if ((err = mp_copy(b, key->dp.B )) != CRYPT_OK) { goto error; }
+ if ((err = mp_copy(gx, key->dp.base.x)) != CRYPT_OK) { goto error; }
+ if ((err = mp_copy(gy, key->dp.base.y)) != CRYPT_OK) { goto error; }
+ if ((err = mp_set(key->dp.base.z, 1)) != CRYPT_OK) { goto error; }
+ /* cofactor & size */
+ key->dp.cofactor = cofactor;
+ key->dp.size = mp_unsigned_bin_size(prime);
+ /* try to find OID in ltc_ecc_sets */
+ _ecc_oid_lookup(key);
+ /* success */
+ return CRYPT_OK;
+
+error:
+ ecc_free(key);
+ return err;
+}
+
+#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/ecc/ecc_set_key.c b/src/ltc/pk/ecc/ecc_set_key.c
new file mode 100644
index 00000000..9fabcf2e
--- /dev/null
+++ b/src/ltc/pk/ecc/ecc_set_key.c
@@ -0,0 +1,67 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+
+#include "tomcrypt.h"
+
+#ifdef LTC_MECC
+
+int ecc_set_key(const unsigned char *in, unsigned long inlen, int type, ecc_key *key)
+{
+ int err;
+ void *prime, *a, *b;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(inlen > 0);
+
+ prime = key->dp.prime;
+ a = key->dp.A;
+ b = key->dp.B;
+
+ if (type == PK_PRIVATE && inlen <= (unsigned long)key->dp.size) {
+ /* load private key */
+ if ((err = mp_read_unsigned_bin(key->k, (unsigned char *)in, inlen)) != CRYPT_OK) {
+ goto error;
+ }
+ if (mp_iszero(key->k)) {
+ err = CRYPT_INVALID_PACKET;
+ goto error;
+ }
+ /* compute public key */
+ if ((err = ltc_mp.ecc_ptmul(key->k, &key->dp.base, &key->pubkey, a, prime, 1)) != CRYPT_OK) { goto error; }
+ key->type = type;
+ }
+ else if (type == PK_PUBLIC) {
+ /* load public key */
+ if ((err = ltc_ecc_import_point(in, inlen, prime, a, b, key->pubkey.x, key->pubkey.y)) != CRYPT_OK) { goto error; }
+ if ((err = mp_set(key->pubkey.z, 1)) != CRYPT_OK) { goto error; }
+ key->type = type;
+ }
+ else {
+ err = CRYPT_INVALID_PACKET;
+ goto error;
+ }
+
+ /* point on the curve + other checks */
+ if ((err = ltc_ecc_verify_key(key)) != CRYPT_OK) {
+ goto error;
+ }
+
+ return CRYPT_OK;
+
+error:
+ ecc_free(key);
+ return err;
+}
+
+#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/ecc/ecc_shared_secret.c b/src/ltc/pk/ecc/ecc_shared_secret.c
index d21d45cf..92917cc1 100644
--- a/src/ltc/pk/ecc/ecc_shared_secret.c
+++ b/src/ltc/pk/ecc/ecc_shared_secret.c
@@ -7,9 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
#include "tomcrypt.h"
/**
@@ -45,29 +42,16 @@ int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key,
return CRYPT_PK_NOT_PRIVATE;
}
- if (ltc_ecc_is_valid_idx(private_key->idx) == 0 || ltc_ecc_is_valid_idx(public_key->idx) == 0) {
- return CRYPT_INVALID_ARG;
- }
-
-/* XXX FIXME names can be different in some situations
- if (XSTRCMP(private_key->dp->name, public_key->dp->name) != 0) {
- return CRYPT_PK_TYPE_MISMATCH;
- }
-*/
/* make new point */
result = ltc_ecc_new_point();
if (result == NULL) {
return CRYPT_MEM;
}
- if ((err = mp_init_multi(&prime, &a, NULL)) != CRYPT_OK) {
- ltc_ecc_del_point(result);
- return err;
- }
+ prime = private_key->dp.prime;
+ a = private_key->dp.A;
- if ((err = mp_read_radix(prime, (char *)private_key->dp->prime, 16)) != CRYPT_OK) { goto done; }
- if ((err = mp_read_radix(a, (char *)private_key->dp->A, 16)) != CRYPT_OK) { goto done; }
- if ((err = ltc_mp.ecc_ptmul(private_key->k, &public_key->pubkey, result, a, prime, 1)) != CRYPT_OK) { goto done; }
+ if ((err = ltc_mp.ecc_ptmul(private_key->k, &public_key->pubkey, result, a, prime, 1)) != CRYPT_OK) { goto done; }
x = (unsigned long)mp_unsigned_bin_size(prime);
if (*outlen < x) {
@@ -76,12 +60,11 @@ int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key,
goto done;
}
zeromem(out, x);
- if ((err = mp_to_unsigned_bin(result->x, out + (x - mp_unsigned_bin_size(result->x)))) != CRYPT_OK) { goto done; }
+ if ((err = mp_to_unsigned_bin(result->x, out + (x - mp_unsigned_bin_size(result->x)))) != CRYPT_OK) { goto done; }
err = CRYPT_OK;
*outlen = x;
done:
- mp_clear_multi(prime, a, NULL);
ltc_ecc_del_point(result);
return err;
}
diff --git a/src/ltc/pk/ecc/ecc_sign_hash.c b/src/ltc/pk/ecc/ecc_sign_hash.c
index 7f0a4e47..87e95060 100644
--- a/src/ltc/pk/ecc/ecc_sign_hash.c
+++ b/src/ltc/pk/ecc/ecc_sign_hash.c
@@ -7,10 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
-
#include "tomcrypt.h"
#ifdef LTC_MECC
@@ -20,13 +16,13 @@
ECC Crypto, Tom St Denis
*/
-static int ecc_sign_hash_ex(const unsigned char *in, unsigned long inlen,
- unsigned char *out, unsigned long *outlen,
- prng_state *prng, int wprng, ecc_key *key, int sigformat)
+static int _ecc_sign_hash(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ prng_state *prng, int wprng, ecc_key *key, int sigformat)
{
ecc_key pubkey;
void *r, *s, *e, *p;
- int err;
+ int err, max_iterations = LTC_PK_MAX_RETRIES;
unsigned long pbits, pbytes, i, shift_right;
unsigned char ch, buf[MAXBLOCKSIZE];
@@ -40,22 +36,17 @@ static int ecc_sign_hash_ex(const unsigned char *in, unsigned long inlen,
return CRYPT_PK_NOT_PRIVATE;
}
- /* is the IDX valid ? */
- if (ltc_ecc_is_valid_idx(key->idx) != 1) {
- return CRYPT_PK_INVALID_TYPE;
- }
-
if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
return err;
}
/* init the bignums */
- if ((err = mp_init_multi(&r, &s, &p, &e, NULL)) != CRYPT_OK) {
+ if ((err = mp_init_multi(&r, &s, &e, NULL)) != CRYPT_OK) {
return err;
}
- if ((err = mp_read_radix(p, (char *)key->dp->order, 16)) != CRYPT_OK) { goto errnokey; }
/* get the hash and load it as a bignum into 'e' */
+ p = key->dp.order;
pbits = mp_count_bits(p);
pbytes = (pbits+7) >> 3;
if (pbits > inlen*8) {
@@ -75,16 +66,16 @@ static int ecc_sign_hash_ex(const unsigned char *in, unsigned long inlen,
}
/* make up a key and export the public copy */
- for (;;) {
- if ((err = ecc_make_key_ex(prng, wprng, &pubkey, key->dp)) != CRYPT_OK) { goto errnokey; }
+ do {
+ if ((err = ecc_set_dp_copy(key, &pubkey)) != CRYPT_OK) { goto errnokey; }
+ if ((err = ecc_generate_key(prng, wprng, &pubkey)) != CRYPT_OK) { goto errnokey; }
/* find r = x1 mod n */
- if ((err = mp_mod(pubkey.pubkey.x, p, r)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mod(pubkey.pubkey.x, p, r)) != CRYPT_OK) { goto error; }
if (mp_iszero(r) == LTC_MP_YES) {
ecc_free(&pubkey);
- }
- else {
+ } else {
/* find s = (e + xr)/k */
if ((err = mp_invmod(pubkey.k, p, pubkey.k)) != CRYPT_OK) { goto error; } /* k = 1/k */
if ((err = mp_mulmod(key->k, r, p, s)) != CRYPT_OK) { goto error; } /* s = xr */
@@ -96,6 +87,10 @@ static int ecc_sign_hash_ex(const unsigned char *in, unsigned long inlen,
break;
}
}
+ } while (--max_iterations > 0);
+
+ if (max_iterations == 0) {
+ goto errnokey;
}
if (sigformat == 1) {
@@ -120,7 +115,7 @@ static int ecc_sign_hash_ex(const unsigned char *in, unsigned long inlen,
error:
ecc_free(&pubkey);
errnokey:
- mp_clear_multi(r, s, p, e, NULL);
+ mp_clear_multi(r, s, e, NULL);
return err;
}
@@ -139,7 +134,7 @@ int ecc_sign_hash(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen,
prng_state *prng, int wprng, ecc_key *key)
{
- return ecc_sign_hash_ex(in, inlen, out, outlen, prng, wprng, key, 0);
+ return _ecc_sign_hash(in, inlen, out, outlen, prng, wprng, key, 0);
}
/**
@@ -157,7 +152,11 @@ int ecc_sign_hash_rfc7518(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen,
prng_state *prng, int wprng, ecc_key *key)
{
- return ecc_sign_hash_ex(in, inlen, out, outlen, prng, wprng, key, 1);
+ return _ecc_sign_hash(in, inlen, out, outlen, prng, wprng, key, 1);
}
#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/ecc/ecc_sizes.c b/src/ltc/pk/ecc/ecc_sizes.c
index 8f61d5fd..dcd310c8 100644
--- a/src/ltc/pk/ecc/ecc_sizes.c
+++ b/src/ltc/pk/ecc/ecc_sizes.c
@@ -7,9 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
#include "tomcrypt.h"
/**
@@ -21,20 +18,25 @@
void ecc_sizes(int *low, int *high)
{
- int i;
- LTC_ARGCHKVD(low != NULL);
- LTC_ARGCHKVD(high != NULL);
-
- *low = INT_MAX;
- *high = 0;
- for (i = 0; ltc_ecc_sets[i].size != 0; i++) {
- if (ltc_ecc_sets[i].size < *low) {
- *low = ltc_ecc_sets[i].size;
- }
- if (ltc_ecc_sets[i].size > *high) {
- *high = ltc_ecc_sets[i].size;
- }
- }
+ int i, size;
+ void *prime;
+
+ LTC_ARGCHKVD(low != NULL);
+ LTC_ARGCHKVD(high != NULL);
+
+ *low = INT_MAX;
+ *high = 0;
+
+ if (mp_init(&prime) == CRYPT_OK) {
+ for (i = 0; ltc_ecc_sets[i].name != NULL; i++) {
+ if (mp_read_radix(prime, ltc_ecc_sets[i].prime, 16) == CRYPT_OK) {
+ size = mp_unsigned_bin_size(prime);
+ if (size < *low) *low = size;
+ if (size > *high) *high = size;
+ }
+ }
+ mp_clear(prime);
+ }
}
#endif
diff --git a/src/ltc/pk/ecc/ecc_verify_hash.c b/src/ltc/pk/ecc/ecc_verify_hash.c
index f9165603..34a49041 100644
--- a/src/ltc/pk/ecc/ecc_verify_hash.c
+++ b/src/ltc/pk/ecc/ecc_verify_hash.c
@@ -7,10 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
-
#include "tomcrypt.h"
#ifdef LTC_MECC
@@ -20,13 +16,13 @@
ECC Crypto, Tom St Denis
*/
-static int ecc_verify_hash_ex(const unsigned char *sig, unsigned long siglen,
- const unsigned char *hash, unsigned long hashlen,
- int *stat, ecc_key *key, int sigformat)
+static int _ecc_verify_hash(const unsigned char *sig, unsigned long siglen,
+ const unsigned char *hash, unsigned long hashlen,
+ int *stat, ecc_key *key, int sigformat)
{
- ecc_point *mG, *mQ;
- void *r, *s, *v, *w, *u1, *u2, *e, *p, *m, *a, *mu, *ma;
- void *mp;
+ ecc_point *mG = NULL, *mQ = NULL;
+ void *r, *s, *v, *w, *u1, *u2, *e, *p, *m, *a, *a_plus3 = NULL, *mu = NULL, *ma = NULL;
+ void *mp = NULL;
int err;
unsigned long pbits, pbytes, i, shift_right;
unsigned char ch, buf[MAXBLOCKSIZE];
@@ -38,18 +34,19 @@ static int ecc_verify_hash_ex(const unsigned char *sig, unsigned long siglen,
/* default to invalid signature */
*stat = 0;
- mp = NULL;
-
- /* is the IDX valid ? */
- if (ltc_ecc_is_valid_idx(key->idx) != 1) {
- return CRYPT_PK_INVALID_TYPE;
- }
/* allocate ints */
- if ((err = mp_init_multi(&r, &s, &v, &w, &u1, &u2, &p, &e, &m, &a, &mu, &ma, NULL)) != CRYPT_OK) {
+ if ((err = mp_init_multi(&r, &s, &v, &w, &u1, &u2, &e, &a_plus3, NULL)) != CRYPT_OK) {
return CRYPT_MEM;
}
+ p = key->dp.order;
+ m = key->dp.prime;
+ a = key->dp.A;
+ if ((err = mp_add_d(a, 3, a_plus3)) != CRYPT_OK) {
+ goto error;
+ }
+
/* allocate points */
mG = ltc_ecc_new_point();
mQ = ltc_ecc_new_point();
@@ -70,23 +67,15 @@ static int ecc_verify_hash_ex(const unsigned char *sig, unsigned long siglen,
}
else {
/* ASN.1 format */
- if ((err = der_decode_sequence_multi(sig, siglen,
+ if ((err = der_decode_sequence_multi_ex(sig, siglen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_STRICT,
LTC_ASN1_INTEGER, 1UL, r,
LTC_ASN1_INTEGER, 1UL, s,
LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { goto error; }
}
- /* get the order */
- if ((err = mp_read_radix(p, (char *)key->dp->order, 16)) != CRYPT_OK) { goto error; }
-
- /* get the modulus */
- if ((err = mp_read_radix(m, (char *)key->dp->prime, 16)) != CRYPT_OK) { goto error; }
-
- /* get the a */
- if ((err = mp_read_radix(a, (char *)key->dp->A, 16)) != CRYPT_OK) { goto error; }
-
/* check for zero */
- if (mp_iszero(r) || mp_iszero(s) || mp_cmp(r, p) != LTC_MP_LT || mp_cmp(s, p) != LTC_MP_LT) {
+ if (mp_cmp_d(r, 0) != LTC_MP_GT || mp_cmp_d(s, 0) != LTC_MP_GT ||
+ mp_cmp(r, p) != LTC_MP_LT || mp_cmp(s, p) != LTC_MP_LT) {
err = CRYPT_INVALID_PACKET;
goto error;
}
@@ -120,24 +109,28 @@ static int ecc_verify_hash_ex(const unsigned char *sig, unsigned long siglen,
if ((err = mp_mulmod(r, w, p, u2)) != CRYPT_OK) { goto error; }
/* find mG and mQ */
- if ((err = mp_read_radix(mG->x, (char *)key->dp->Gx, 16)) != CRYPT_OK) { goto error; }
- if ((err = mp_read_radix(mG->y, (char *)key->dp->Gy, 16)) != CRYPT_OK) { goto error; }
- if ((err = mp_set(mG->z, 1)) != CRYPT_OK) { goto error; }
-
+ if ((err = mp_copy(key->dp.base.x, mG->x)) != CRYPT_OK) { goto error; }
+ if ((err = mp_copy(key->dp.base.y, mG->y)) != CRYPT_OK) { goto error; }
+ if ((err = mp_copy(key->dp.base.z, mG->z)) != CRYPT_OK) { goto error; }
if ((err = mp_copy(key->pubkey.x, mQ->x)) != CRYPT_OK) { goto error; }
if ((err = mp_copy(key->pubkey.y, mQ->y)) != CRYPT_OK) { goto error; }
if ((err = mp_copy(key->pubkey.z, mQ->z)) != CRYPT_OK) { goto error; }
+ /* find the montgomery mp */
+ if ((err = mp_montgomery_setup(m, &mp)) != CRYPT_OK) { goto error; }
+
+ /* for curves with a == -3 keep ma == NULL */
+ if (mp_cmp(a_plus3, m) != LTC_MP_EQ) {
+ if ((err = mp_init_multi(&mu, &ma, NULL)) != CRYPT_OK) { goto error; }
+ if ((err = mp_montgomery_normalization(mu, m)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mulmod(a, mu, m, ma)) != CRYPT_OK) { goto error; }
+ }
+
/* compute u1*mG + u2*mQ = mG */
if (ltc_mp.ecc_mul2add == NULL) {
if ((err = ltc_mp.ecc_ptmul(u1, mG, mG, a, m, 0)) != CRYPT_OK) { goto error; }
if ((err = ltc_mp.ecc_ptmul(u2, mQ, mQ, a, m, 0)) != CRYPT_OK) { goto error; }
- /* find the montgomery mp */
- if ((err = mp_montgomery_setup(m, &mp)) != CRYPT_OK) { goto error; }
- if ((err = mp_montgomery_normalization(mu, m)) != CRYPT_OK) { goto error; }
- if ((err = mp_mulmod(a, mu, m, ma)) != CRYPT_OK) { goto error; }
-
/* add them */
if ((err = ltc_mp.ecc_ptadd(mQ, mG, mG, ma, m, mp)) != CRYPT_OK) { goto error; }
@@ -145,7 +138,7 @@ static int ecc_verify_hash_ex(const unsigned char *sig, unsigned long siglen,
if ((err = ltc_mp.ecc_map(mG, m, mp)) != CRYPT_OK) { goto error; }
} else {
/* use Shamir's trick to compute u1*mG + u2*mQ using half of the doubles */
- if ((err = ltc_mp.ecc_mul2add(mG, u1, mQ, u2, mG, a, m)) != CRYPT_OK) { goto error; }
+ if ((err = ltc_mp.ecc_mul2add(mG, u1, mQ, u2, mG, ma, m)) != CRYPT_OK) { goto error; }
}
/* v = X_x1 mod n */
@@ -159,9 +152,11 @@ static int ecc_verify_hash_ex(const unsigned char *sig, unsigned long siglen,
/* clear up and return */
err = CRYPT_OK;
error:
- ltc_ecc_del_point(mG);
- ltc_ecc_del_point(mQ);
- mp_clear_multi(r, s, v, w, u1, u2, p, e, m, a, mu, ma, NULL);
+ if (mG != NULL) ltc_ecc_del_point(mG);
+ if (mQ != NULL) ltc_ecc_del_point(mQ);
+ if (mu != NULL) mp_clear(mu);
+ if (ma != NULL) mp_clear(ma);
+ mp_clear_multi(r, s, v, w, u1, u2, e, a_plus3, NULL);
if (mp != NULL) {
mp_montgomery_free(mp);
}
@@ -182,7 +177,7 @@ int ecc_verify_hash(const unsigned char *sig, unsigned long siglen,
const unsigned char *hash, unsigned long hashlen,
int *stat, ecc_key *key)
{
- return ecc_verify_hash_ex(sig, siglen, hash, hashlen, stat, key, 0);
+ return _ecc_verify_hash(sig, siglen, hash, hashlen, stat, key, 0);
}
/**
@@ -199,7 +194,11 @@ int ecc_verify_hash_rfc7518(const unsigned char *sig, unsigned long siglen,
const unsigned char *hash, unsigned long hashlen,
int *stat, ecc_key *key)
{
- return ecc_verify_hash_ex(sig, siglen, hash, hashlen, stat, key, 1);
+ return _ecc_verify_hash(sig, siglen, hash, hashlen, stat, key, 1);
}
#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/ecc/ltc_ecc_export_point.c b/src/ltc/pk/ecc/ltc_ecc_export_point.c
index 086e4c2e..84750c80 100644
--- a/src/ltc/pk/ecc/ltc_ecc_export_point.c
+++ b/src/ltc/pk/ecc/ltc_ecc_export_point.c
@@ -5,11 +5,6 @@
*
* The library is free for all purposes without any express
* guarantee it works.
- *
- */
-
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
*/
#include "tomcrypt.h"
@@ -62,3 +57,7 @@ int ltc_ecc_export_point(unsigned char *out, unsigned long *outlen, void *x, voi
}
#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/ecc/ltc_ecc_import_point.c b/src/ltc/pk/ecc/ltc_ecc_import_point.c
index d4d028d5..6c8107c8 100644
--- a/src/ltc/pk/ecc/ltc_ecc_import_point.c
+++ b/src/ltc/pk/ecc/ltc_ecc_import_point.c
@@ -5,11 +5,6 @@
*
* The library is free for all purposes without any express
* guarantee it works.
- *
- */
-
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
*/
#include "tomcrypt.h"
@@ -70,3 +65,7 @@ cleanup:
}
#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/ecc/ltc_ecc_is_point.c b/src/ltc/pk/ecc/ltc_ecc_is_point.c
index 9ea963c5..46e1a6d4 100644
--- a/src/ltc/pk/ecc/ltc_ecc_is_point.c
+++ b/src/ltc/pk/ecc/ltc_ecc_is_point.c
@@ -5,10 +5,6 @@
*
* The library is free for all purposes without any express
* guarantee it works.
- *
- */
-
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
*/
#include "tomcrypt.h"
@@ -22,42 +18,39 @@
@return CRYPT_OK if valid
*/
-int ltc_ecc_is_point(const ltc_ecc_set_type *dp, void *x, void *y)
+int ltc_ecc_is_point(const ltc_ecc_dp *dp, void *x, void *y)
{
void *prime, *a, *b, *t1, *t2;
int err;
- if ((err = mp_init_multi(&prime, &a, &b, &t1, &t2, NULL)) != CRYPT_OK) {
- return err;
- }
+ prime = dp->prime;
+ b = dp->B;
+ a = dp->A;
- /* load prime, a and b */
- if ((err = mp_read_radix(prime, dp->prime, 16)) != CRYPT_OK) goto cleanup;
- if ((err = mp_read_radix(b, dp->B, 16)) != CRYPT_OK) goto cleanup;
- if ((err = mp_read_radix(a, dp->A, 16)) != CRYPT_OK) goto cleanup;
+ if ((err = mp_init_multi(&t1, &t2, NULL)) != CRYPT_OK) return err;
/* compute y^2 */
- if ((err = mp_sqr(y, t1)) != CRYPT_OK) goto cleanup;
+ if ((err = mp_sqr(y, t1)) != CRYPT_OK) goto cleanup;
/* compute x^3 */
- if ((err = mp_sqr(x, t2)) != CRYPT_OK) goto cleanup;
- if ((err = mp_mod(t2, prime, t2)) != CRYPT_OK) goto cleanup;
- if ((err = mp_mul(x, t2, t2)) != CRYPT_OK) goto cleanup;
+ if ((err = mp_sqr(x, t2)) != CRYPT_OK) goto cleanup;
+ if ((err = mp_mod(t2, prime, t2)) != CRYPT_OK) goto cleanup;
+ if ((err = mp_mul(x, t2, t2)) != CRYPT_OK) goto cleanup;
/* compute y^2 - x^3 */
- if ((err = mp_sub(t1, t2, t1)) != CRYPT_OK) goto cleanup;
+ if ((err = mp_sub(t1, t2, t1)) != CRYPT_OK) goto cleanup;
/* compute y^2 - x^3 - a*x */
- if ((err = mp_submod(prime, a, prime, t2)) != CRYPT_OK) goto cleanup;
- if ((err = mp_mulmod(t2, x, prime, t2)) != CRYPT_OK) goto cleanup;
- if ((err = mp_addmod(t1, t2, prime, t1)) != CRYPT_OK) goto cleanup;
+ if ((err = mp_submod(prime, a, prime, t2)) != CRYPT_OK) goto cleanup;
+ if ((err = mp_mulmod(t2, x, prime, t2)) != CRYPT_OK) goto cleanup;
+ if ((err = mp_addmod(t1, t2, prime, t1)) != CRYPT_OK) goto cleanup;
/* adjust range (0, prime) */
while (mp_cmp_d(t1, 0) == LTC_MP_LT) {
- if ((err = mp_add(t1, prime, t1)) != CRYPT_OK) goto cleanup;
+ if ((err = mp_add(t1, prime, t1)) != CRYPT_OK) goto cleanup;
}
while (mp_cmp(t1, prime) != LTC_MP_LT) {
- if ((err = mp_sub(t1, prime, t1)) != CRYPT_OK) goto cleanup;
+ if ((err = mp_sub(t1, prime, t1)) != CRYPT_OK) goto cleanup;
}
/* compare to b */
@@ -68,8 +61,12 @@ int ltc_ecc_is_point(const ltc_ecc_set_type *dp, void *x, void *y)
}
cleanup:
- mp_clear_multi(prime, a, b, t1, t2, NULL);
+ mp_clear_multi(t1, t2, NULL);
return err;
}
#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/ecc/ltc_ecc_is_point_at_infinity.c b/src/ltc/pk/ecc/ltc_ecc_is_point_at_infinity.c
index d5f0f0b2..87f3b0c3 100644
--- a/src/ltc/pk/ecc/ltc_ecc_is_point_at_infinity.c
+++ b/src/ltc/pk/ecc/ltc_ecc_is_point_at_infinity.c
@@ -15,7 +15,7 @@
* a point at infinity is any point (x,y,0) such that y^2 == x^3, except (0,0,0)
*/
-int ltc_ecc_is_point_at_infinity(ecc_point *P, void *modulus)
+int ltc_ecc_is_point_at_infinity(const ecc_point *P, void *modulus)
{
int err, retval = 0;
void *x3, *y2;
@@ -46,3 +46,7 @@ done:
}
#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/ecc/ltc_ecc_is_valid_idx.c b/src/ltc/pk/ecc/ltc_ecc_is_valid_idx.c
deleted file mode 100644
index d14ab330..00000000
--- a/src/ltc/pk/ecc/ltc_ecc_is_valid_idx.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/* LibTomCrypt, modular cryptographic library -- Tom St Denis
- *
- * LibTomCrypt is a library that provides various cryptographic
- * algorithms in a highly modular and flexible manner.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- */
-
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
-#include "tomcrypt.h"
-
-/**
- @file ltc_ecc_is_valid_idx.c
- ECC Crypto, Tom St Denis
-*/
-
-#ifdef LTC_MECC
-
-/** Returns whether an ECC idx is valid or not
- @param n The idx number to check
- @return 1 if valid, 0 if not
-*/
-int ltc_ecc_is_valid_idx(int n)
-{
- int x;
-
- for (x = 0; ltc_ecc_sets[x].size != 0; x++);
- /* -1 is a valid index --- indicating that the domain params were supplied by the user */
- if ((n >= -1) && (n < x)) {
- return 1;
- }
- return 0;
-}
-
-#endif
-/* ref: $Format:%D$ */
-/* git commit: $Format:%H$ */
-/* commit time: $Format:%ai$ */
-
diff --git a/src/ltc/pk/ecc/ltc_ecc_map.c b/src/ltc/pk/ecc/ltc_ecc_map.c
index 9dd202f9..92d059d1 100644
--- a/src/ltc/pk/ecc/ltc_ecc_map.c
+++ b/src/ltc/pk/ecc/ltc_ecc_map.c
@@ -7,9 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
#include "tomcrypt.h"
/**
@@ -43,7 +40,7 @@ int ltc_ecc_map(ecc_point *P, void *modulus, void *mp)
}
if ((err = mp_init_multi(&t1, &t2, NULL)) != CRYPT_OK) {
- return CRYPT_MEM;
+ return err;
}
/* first map z back to normal */
diff --git a/src/ltc/pk/ecc/ltc_ecc_mul2add.c b/src/ltc/pk/ecc/ltc_ecc_mul2add.c
index a9b780df..80ceb863 100644
--- a/src/ltc/pk/ecc/ltc_ecc_mul2add.c
+++ b/src/ltc/pk/ecc/ltc_ecc_mul2add.c
@@ -7,9 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
#include "tomcrypt.h"
/**
@@ -26,22 +23,23 @@
@param kA What to multiple A by
@param B Second point to multiply
@param kB What to multiple B by
- @param C [out] Destination point (can overlap with A or B
+ @param C [out] Destination point (can overlap with A or B)
+ @param ma ECC curve parameter a in montgomery form
@param modulus Modulus for curve
@return CRYPT_OK on success
*/
-int ltc_ecc_mul2add(ecc_point *A, void *kA,
- ecc_point *B, void *kB,
- ecc_point *C,
- void *a,
- void *modulus)
+int ltc_ecc_mul2add(const ecc_point *A, void *kA,
+ const ecc_point *B, void *kB,
+ ecc_point *C,
+ void *ma,
+ void *modulus)
{
ecc_point *precomp[16];
unsigned bitbufA, bitbufB, lenA, lenB, len, nA, nB, nibble;
unsigned x, y;
unsigned char *tA, *tB;
int err, first;
- void *mp, *mu, *ma;
+ void *mp, *mu;
/* argchks */
LTC_ARGCHK(A != NULL);
@@ -95,15 +93,12 @@ int ltc_ecc_mul2add(ecc_point *A, void *kA,
if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) {
goto ERR_P;
}
- if ((err = mp_init_multi(&mu, &ma, NULL)) != CRYPT_OK) {
+ if ((err = mp_init(&mu)) != CRYPT_OK) {
goto ERR_MP;
}
if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) {
goto ERR_MU;
}
- if ((err = mp_mulmod(a, mu, modulus, ma)) != CRYPT_OK) {
- goto ERR_MU;
- }
/* copy ones ... */
if ((err = mp_mulmod(A->x, mu, modulus, precomp[1]->x)) != CRYPT_OK) { goto ERR_MU; }
@@ -183,7 +178,7 @@ int ltc_ecc_mul2add(ecc_point *A, void *kA,
/* clean up */
ERR_MU:
- mp_clear_multi(mu, ma, NULL);
+ mp_clear(mu);
ERR_MP:
mp_montgomery_free(mp);
ERR_P:
diff --git a/src/ltc/pk/ecc/ltc_ecc_mulmod.c b/src/ltc/pk/ecc/ltc_ecc_mulmod.c
index 8b65ebf6..50dedc16 100644
--- a/src/ltc/pk/ecc/ltc_ecc_mulmod.c
+++ b/src/ltc/pk/ecc/ltc_ecc_mulmod.c
@@ -7,9 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
#include "tomcrypt.h"
/**
@@ -32,11 +29,11 @@
@param map Boolean whether to map back to affine or not (1==map, 0 == leave in projective)
@return CRYPT_OK on success
*/
-int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *a, void *modulus, int map)
+int ltc_ecc_mulmod(void *k, const ecc_point *G, ecc_point *R, void *a, void *modulus, int map)
{
ecc_point *tG, *M[8];
int i, j, err;
- void *mu, *mp, *ma;
+ void *mp = NULL, *mu = NULL, *ma = NULL, *a_plus3 = NULL;
ltc_mp_digit buf;
int first, bitbuf, bitcpy, bitcnt, mode, digidx;
@@ -54,22 +51,16 @@ int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *a, void *modulus,
}
/* init montgomery reduction */
- if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) {
- return err;
- }
- if ((err = mp_init_multi(&mu, &ma, NULL)) != CRYPT_OK) {
- mp_montgomery_free(mp);
- return err;
- }
- if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) {
- mp_montgomery_free(mp);
- mp_clear_multi(mu, ma, NULL);
- return err;
- }
- if ((err = mp_mulmod(a, mu, modulus, ma)) != CRYPT_OK) {
- mp_montgomery_free(mp);
- mp_clear_multi(mu, ma, NULL);
- return err;
+ if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto error; }
+ if ((err = mp_init(&mu)) != CRYPT_OK) { goto error; }
+ if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { goto error; }
+
+ /* for curves with a == -3 keep ma == NULL */
+ if ((err = mp_init(&a_plus3)) != CRYPT_OK) { goto error; }
+ if ((err = mp_add_d(a, 3, a_plus3)) != CRYPT_OK) { goto error; }
+ if (mp_cmp(a_plus3, modulus) != LTC_MP_EQ) {
+ if ((err = mp_init(&ma)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mulmod(a, mu, modulus, ma)) != CRYPT_OK) { goto error; }
}
/* alloc ram for window temps */
@@ -79,9 +70,8 @@ int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *a, void *modulus,
for (j = 0; j < i; j++) {
ltc_ecc_del_point(M[j]);
}
- mp_montgomery_free(mp);
- mp_clear_multi(mu, ma, NULL);
- return CRYPT_MEM;
+ err = CRYPT_MEM;
+ goto error;
}
}
@@ -209,15 +199,15 @@ int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *a, void *modulus,
err = CRYPT_OK;
}
done:
- if (mu != NULL) {
- mp_clear(mu);
- }
- mp_clear(ma);
- mp_montgomery_free(mp);
ltc_ecc_del_point(tG);
for (i = 0; i < 8; i++) {
ltc_ecc_del_point(M[i]);
}
+error:
+ if (ma != NULL) mp_clear(ma);
+ if (a_plus3 != NULL) mp_clear(a_plus3);
+ if (mu != NULL) mp_clear(mu);
+ if (mp != NULL) mp_montgomery_free(mp);
return err;
}
diff --git a/src/ltc/pk/ecc/ltc_ecc_mulmod_timing.c b/src/ltc/pk/ecc/ltc_ecc_mulmod_timing.c
index d6f7f1df..068240ae 100644
--- a/src/ltc/pk/ecc/ltc_ecc_mulmod_timing.c
+++ b/src/ltc/pk/ecc/ltc_ecc_mulmod_timing.c
@@ -7,9 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
#include "tomcrypt.h"
/**
@@ -31,11 +28,11 @@
@param map Boolean whether to map back to affine or not (1==map, 0 == leave in projective)
@return CRYPT_OK on success
*/
-int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *a, void *modulus, int map)
+int ltc_ecc_mulmod(void *k, const ecc_point *G, ecc_point *R, void *a, void *modulus, int map)
{
ecc_point *tG, *M[3];
int i, j, err;
- void *mu, *mp, *ma;
+ void *mp = NULL, *mu = NULL, *ma = NULL, *a_plus3 = NULL;
ltc_mp_digit buf;
int bitcnt, mode, digidx;
@@ -53,22 +50,16 @@ int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *a, void *modulus,
}
/* init montgomery reduction */
- if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) {
- return err;
- }
- if ((err = mp_init_multi(&mu, &ma, NULL)) != CRYPT_OK) {
- mp_montgomery_free(mp);
- return err;
- }
- if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) {
- mp_clear(mu);
- mp_montgomery_free(mp);
- return err;
- }
- if ((err = mp_mulmod(a, mu, modulus, ma)) != CRYPT_OK) {
- mp_montgomery_free(mp);
- mp_clear_multi(mu, ma, NULL);
- return err;
+ if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto error; }
+ if ((err = mp_init(&mu)) != CRYPT_OK) { goto error; }
+ if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { goto error; }
+
+ /* for curves with a == -3 keep ma == NULL */
+ if ((err = mp_init(&a_plus3)) != CRYPT_OK) { goto error; }
+ if ((err = mp_add_d(a, 3, a_plus3)) != CRYPT_OK) { goto error; }
+ if (mp_cmp(a_plus3, modulus) != LTC_MP_EQ) {
+ if ((err = mp_init(&ma)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mulmod(a, mu, modulus, ma)) != CRYPT_OK) { goto error; }
}
/* alloc ram for window temps */
@@ -156,15 +147,15 @@ int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *a, void *modulus,
err = CRYPT_OK;
}
done:
- if (mu != NULL) {
- mp_clear(mu);
- }
- mp_clear(ma);
- mp_montgomery_free(mp);
ltc_ecc_del_point(tG);
for (i = 0; i < 3; i++) {
ltc_ecc_del_point(M[i]);
}
+error:
+ if (ma != NULL) mp_clear(ma);
+ if (a_plus3 != NULL) mp_clear(a_plus3);
+ if (mu != NULL) mp_clear(mu);
+ if (mp != NULL) mp_montgomery_free(mp);
return err;
}
diff --git a/src/ltc/pk/ecc/ltc_ecc_points.c b/src/ltc/pk/ecc/ltc_ecc_points.c
index 416fc909..772e8efd 100644
--- a/src/ltc/pk/ecc/ltc_ecc_points.c
+++ b/src/ltc/pk/ecc/ltc_ecc_points.c
@@ -7,9 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
#include "tomcrypt.h"
/**
diff --git a/src/ltc/pk/ecc/ltc_ecc_projective_add_point.c b/src/ltc/pk/ecc/ltc_ecc_projective_add_point.c
index 3434902a..0182d0a8 100644
--- a/src/ltc/pk/ecc/ltc_ecc_projective_add_point.c
+++ b/src/ltc/pk/ecc/ltc_ecc_projective_add_point.c
@@ -7,9 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
#include "tomcrypt.h"
/**
@@ -24,12 +21,12 @@
@param P The point to add
@param Q The point to add
@param R [out] The destination of the double
- @param ma ECC curve parameter a in montgomery form (if NULL we assume a == -3)
+ @param ma ECC curve parameter a in montgomery form
@param modulus The modulus of the field the ECC curve is in
@param mp The "b" value from montgomery_setup()
@return CRYPT_OK on success
*/
-int ltc_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, void *ma, void *modulus, void *mp)
+int ltc_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q, ecc_point *R, void *ma, void *modulus, void *mp)
{
void *t1, *t2, *x, *y, *z;
int err;
diff --git a/src/ltc/pk/ecc/ltc_ecc_projective_dbl_point.c b/src/ltc/pk/ecc/ltc_ecc_projective_dbl_point.c
index cc01b233..57cfd6fd 100644
--- a/src/ltc/pk/ecc/ltc_ecc_projective_dbl_point.c
+++ b/src/ltc/pk/ecc/ltc_ecc_projective_dbl_point.c
@@ -7,9 +7,6 @@
* guarantee it works.
*/
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
- */
#include "tomcrypt.h"
/* ### Point doubling in Jacobian coordinate system ###
@@ -41,12 +38,12 @@
Double an ECC point
@param P The point to double
@param R [out] The destination of the double
- @param ma ECC curve parameter a in montgomery form (if NULL we assume a == -3)
+ @param ma ECC curve parameter a in montgomery form
@param modulus The modulus of the field the ECC curve is in
@param mp The "b" value from montgomery_setup()
@return CRYPT_OK on success
*/
-int ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *ma, void *modulus, void *mp)
+int ltc_ecc_projective_dbl_point(const ecc_point *P, ecc_point *R, void *ma, void *modulus, void *mp)
{
void *t1, *t2;
int err;
@@ -86,7 +83,7 @@ int ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *ma, void *mod
if ((err = mp_sub(R->z, modulus, R->z)) != CRYPT_OK) { goto done; }
}
- if (ma == NULL) { /* special case for ma == -3 (slightly faster than general case) */
+ if (ma == NULL) { /* special case for curves with a == -3 (10% faster than general case) */
/* T2 = X - T1 */
if ((err = mp_sub(R->x, t1, t2)) != CRYPT_OK) { goto done; }
if (mp_cmp_d(t2, 0) == LTC_MP_LT) {
@@ -188,7 +185,7 @@ int ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *ma, void *mod
err = CRYPT_OK;
done:
- mp_clear_multi(t1, t2, NULL);
+ mp_clear_multi(t2, t1, NULL);
return err;
}
#endif
diff --git a/src/ltc/pk/ecc/ecc_verify_key.c b/src/ltc/pk/ecc/ltc_ecc_verify_key.c
index 0ca1914f..b417465b 100644
--- a/src/ltc/pk/ecc/ecc_verify_key.c
+++ b/src/ltc/pk/ecc/ltc_ecc_verify_key.c
@@ -5,11 +5,6 @@
*
* The library is free for all purposes without any express
* guarantee it works.
- *
- */
-
-/* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b
- *
*/
#include "tomcrypt.h"
@@ -24,7 +19,7 @@
@return CRYPT_OK if successful
*/
-int ecc_verify_key(ecc_key *key)
+int ltc_ecc_verify_key(ecc_key *key)
{
int err;
void *prime = NULL;
@@ -32,18 +27,17 @@ int ecc_verify_key(ecc_key *key)
void *a = NULL;
ecc_point *point;
- if (mp_init_multi(&order, &prime, NULL) != CRYPT_OK) {
- return CRYPT_MEM;
- }
-
- /* Test 1: Are the x amd y points of the public key in the field? */
- if ((err = ltc_mp.read_radix(prime, key->dp->prime, 16)) != CRYPT_OK) { goto done2; }
+ prime = key->dp.prime;
+ order = key->dp.order;
+ a = key->dp.A;
+ /* Test 1: Are the x and y points of the public key in the field? */
if (ltc_mp.compare_d(key->pubkey.z, 1) == LTC_MP_EQ) {
if ((ltc_mp.compare(key->pubkey.x, prime) != LTC_MP_LT) ||
(ltc_mp.compare(key->pubkey.y, prime) != LTC_MP_LT) ||
- (ltc_mp.compare_d(key->pubkey.x, 0) != LTC_MP_GT) ||
- (ltc_mp.compare_d(key->pubkey.y, 0) != LTC_MP_GT)
+ (ltc_mp.compare_d(key->pubkey.x, 0) == LTC_MP_LT) ||
+ (ltc_mp.compare_d(key->pubkey.y, 0) == LTC_MP_LT) ||
+ (mp_iszero(key->pubkey.x) && mp_iszero(key->pubkey.y))
)
{
err = CRYPT_INVALID_PACKET;
@@ -52,12 +46,10 @@ int ecc_verify_key(ecc_key *key)
}
/* Test 2: is the public key on the curve? */
- if ((err = ltc_ecc_is_point(key->dp, key->pubkey.x, key->pubkey.y)) != CRYPT_OK) { goto done2; }
+ if ((err = ltc_ecc_is_point(&key->dp, key->pubkey.x, key->pubkey.y)) != CRYPT_OK) { goto done2; }
/* Test 3: does nG = O? (n = order, O = point at infinity, G = public key) */
point = ltc_ecc_new_point();
- if ((err = ltc_mp.read_radix(order, key->dp->order, 16)) != CRYPT_OK) { goto done1; }
- if ((err = ltc_mp.read_radix(a, key->dp->A, 16)) != CRYPT_OK) { goto done1; }
if ((err = ltc_ecc_mulmod(order, &(key->pubkey), point, a, prime, 1)) != CRYPT_OK) { goto done1; }
if (ltc_ecc_is_point_at_infinity(point, prime)) {
@@ -70,8 +62,11 @@ int ecc_verify_key(ecc_key *key)
done1:
ltc_ecc_del_point(point);
done2:
- mp_clear_multi(prime, order, NULL);
return err;
}
#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/ltc/pk/rsa/rsa_export.c b/src/ltc/pk/rsa/rsa_export.c
index a9885de8..b156a83f 100644
--- a/src/ltc/pk/rsa/rsa_export.c
+++ b/src/ltc/pk/rsa/rsa_export.c
@@ -79,7 +79,7 @@ int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key
goto finish;
}
- err = der_encode_subject_public_key_info(out, outlen,
+ err = x509_encode_subject_public_key_info(out, outlen,
PKA_RSA, tmp, tmplen, LTC_ASN1_NULL, NULL, 0);
finish:
diff --git a/src/ltc/pk/rsa/rsa_import.c b/src/ltc/pk/rsa/rsa_import.c
index 84cd6f65..85771783 100644
--- a/src/ltc/pk/rsa/rsa_import.c
+++ b/src/ltc/pk/rsa/rsa_import.c
@@ -27,7 +27,7 @@ int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key)
int err;
void *zero;
unsigned char *tmpbuf=NULL;
- unsigned long tmpbuf_len;
+ unsigned long tmpbuf_len, len;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(key != NULL);
@@ -47,9 +47,10 @@ int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key)
goto LBL_ERR;
}
- err = der_decode_subject_public_key_info(in, inlen,
+ len = 0;
+ err = x509_decode_subject_public_key_info(in, inlen,
PKA_RSA, tmpbuf, &tmpbuf_len,
- LTC_ASN1_NULL, NULL, 0);
+ LTC_ASN1_NULL, NULL, &len);
if (err == CRYPT_OK) { /* SubjectPublicKeyInfo format */
diff --git a/src/ltc/pk/rsa/rsa_import_x509.c b/src/ltc/pk/rsa/rsa_import_x509.c
index 0f2d5f1c..aa35e644 100644
--- a/src/ltc/pk/rsa/rsa_import_x509.c
+++ b/src/ltc/pk/rsa/rsa_import_x509.c
@@ -26,7 +26,7 @@ int rsa_import_x509(const unsigned char *in, unsigned long inlen, rsa_key *key)
{
int err;
unsigned char *tmpbuf;
- unsigned long tmpbuf_len, tmp_inlen;
+ unsigned long tmpbuf_len, tmp_inlen, len;
ltc_asn1_list *decoded_list = NULL, *l;
LTC_ARGCHK(in != NULL);
@@ -77,9 +77,10 @@ int rsa_import_x509(const unsigned char *in, unsigned long inlen, rsa_key *key)
l->child->type == LTC_ASN1_SEQUENCE && l->child->child &&
l->child->child->type == LTC_ASN1_OBJECT_IDENTIFIER && l->child->next &&
l->child->next->type == LTC_ASN1_BIT_STRING) {
- err = der_decode_subject_public_key_info(l->data, l->size,
+ len = 0;
+ err = x509_decode_subject_public_key_info(l->data, l->size,
PKA_RSA, tmpbuf, &tmpbuf_len,
- LTC_ASN1_NULL, NULL, 0);
+ LTC_ASN1_NULL, NULL, &len);
if (err == CRYPT_OK) {
/* now it should be SEQUENCE { INTEGER, INTEGER } */
if ((err = der_decode_sequence_multi(tmpbuf, tmpbuf_len,
diff --git a/src/ltc/pk/rsa/rsa_verify_hash.c b/src/ltc/pk/rsa/rsa_verify_hash.c
index b5846965..361f2378 100644
--- a/src/ltc/pk/rsa/rsa_verify_hash.c
+++ b/src/ltc/pk/rsa/rsa_verify_hash.c
@@ -142,10 +142,10 @@ int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen,
LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 2);
LTC_SET_ASN1(siginfo, 1, LTC_ASN1_OCTET_STRING, tmpbuf, siglen);
- if ((err = der_decode_sequence(out, outlen, siginfo, 2)) != CRYPT_OK) {
+ if ((err = der_decode_sequence_strict(out, outlen, siginfo, 2)) != CRYPT_OK) {
/* fallback to Legacy:missing NULL */
LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 1);
- if ((err = der_decode_sequence(out, outlen, siginfo, 2)) != CRYPT_OK) {
+ if ((err = der_decode_sequence_strict(out, outlen, siginfo, 2)) != CRYPT_OK) {
XFREE(out);
goto bail_2;
}
diff --git a/t/001_compile.t b/t/001_compile.t
index e0e0c789..1abc45f6 100644
--- a/t/001_compile.t
+++ b/t/001_compile.t
@@ -68,6 +68,10 @@ use Crypt::Digest::SHA3_224;
use Crypt::Digest::SHA3_256;
use Crypt::Digest::SHA3_384;
use Crypt::Digest::SHA3_512;
+use Crypt::Digest::Keccak224;
+use Crypt::Digest::Keccak256;
+use Crypt::Digest::Keccak384;
+use Crypt::Digest::Keccak512;
use Crypt::Digest::SHA512;
use Crypt::Digest::SHA512_224;
use Crypt::Digest::SHA512_256;
diff --git a/t/002_all_pm.t b/t/002_all_pm.t
index 0d7e12b5..3daceed3 100644
--- a/t/002_all_pm.t
+++ b/t/002_all_pm.t
@@ -31,7 +31,7 @@ for my $m (sort @files) {
$m =~ s|[\\/]|::|g;
$m =~ s|^lib::||;
$m =~ s|\.pm$||;
- push @err, "ERROR: '$m' is missing in CryptX.pm" unless $cryptx =~ /L<$m>/s || $m =~ /^(CryptX|Math::BigInt::LTM|Crypt::(PK|Mode|Mac|AuthEnc))$/;
+ push @err, "ERROR: '$m' is missing in CryptX.pm" unless $cryptx =~ /L<$m>/s || $m =~ /^(CryptX|Math::BigInt::LTM|Crypt::(PK|Mode|Mac|AuthEnc|Checksum))$/;
push @err, "ERROR: '$m' is missing in 001_compile.t" unless $compile_t =~ /\nuse $m;/s;
eval "use $m; 1;" or push @err, "ERROR: 'use $m' failed";
}
diff --git a/t/003_all_pm_pod.t b/t/003_all_pm_pod.t
index 5bc59af3..47c3ccce 100644
--- a/t/003_all_pm_pod.t
+++ b/t/003_all_pm_pod.t
@@ -6,7 +6,7 @@ use Test::More;
plan skip_all => "set TEST_POD to enable this test (developer only!)" unless $ENV{TEST_POD};
plan skip_all => "File::Find not installed" unless eval { require File::Find };
plan skip_all => "Test::Pod not installed" unless eval { require Test::Pod };
-plan tests => 103;
+plan tests => 107;
my @files;
File::Find::find({ wanted=>sub { push @files, $_ if /\.pm$/ }, no_chdir=>1 }, 'lib');
diff --git a/t/004_all_pm_pod_spelling.t b/t/004_all_pm_pod_spelling.t
index 0cb3ed6f..5e6de670 100644
--- a/t/004_all_pm_pod_spelling.t
+++ b/t/004_all_pm_pod_spelling.t
@@ -17,11 +17,12 @@ Test::Pod::Spelling->import(
params paramshash irand perl endian zbase bumac bmac budigest bdigest md de
blakes_ blakeb_
XOR'ing XOR'ed
+ keccak
)]
},
);
-plan tests => 103;
+plan tests => 107;
my @files;
File::Find::find({ wanted=>sub { push @files, $_ if /\.pm$/ }, no_chdir=>1 }, 'lib');
diff --git a/t/005_all_pm_pod_coverage.t b/t/005_all_pm_pod_coverage.t
index 4065c23d..ce06bc4b 100644
--- a/t/005_all_pm_pod_coverage.t
+++ b/t/005_all_pm_pod_coverage.t
@@ -6,7 +6,7 @@ use Test::More;
plan skip_all => "set TEST_POD to enable this test (developer only!)" unless $ENV{TEST_POD};
plan skip_all => "Pod::Coverage not installed" unless eval { require Pod::Coverage };
plan skip_all => "File::Find not installed" unless eval { require File::Find };
-plan tests => 103;
+plan tests => 107;
my @files;
File::Find::find({ wanted=>sub { push @files, $_ if /\.pm$/ }, no_chdir=>1 }, 'lib');
@@ -28,9 +28,15 @@ for my $m (sort @files) {
elsif ($m eq 'Crypt::Mode') {
$pc = Pod::Coverage->new(package => $m, pod_from => $f, trustme => [qr/^(add|decrypt|encrypt|finish|new|start_decrypt|start_encrypt)$/] );
}
+ elsif ($m eq 'Crypt::Checksum') {
+ $pc = Pod::Coverage->new(package => $m, pod_from => $f, trustme => [qr/^(addfile|(adler32_|crc32_)(file_hex|file_int|file|data_hex|data_int|data))$/] );
+ }
elsif ($m eq 'Crypt::Mac') {
$pc = Pod::Coverage->new(package => $m, pod_from => $f, trustme => [qr/^(add|addfile)$/] );
}
+ elsif ($m =~ /^Crypt::Mode::(CTR|CFB|OFB)$/) {
+ $pc = Pod::Coverage->new(package => $m, pod_from => $f, trustme => [qr/^(finish)$/] );
+ }
elsif ($m eq 'Crypt::AuthEnc::OCB') {
$pc = Pod::Coverage->new(package => $m, pod_from => $f, trustme => [qr/^(blocksize|aad_add)$/] );
}
diff --git a/t/auth_enc_ccm.t b/t/auth_enc_ccm.t
index fc8a7276..1f32583e 100644
--- a/t/auth_enc_ccm.t
+++ b/t/auth_enc_ccm.t
@@ -1,7 +1,7 @@
use strict;
use warnings;
-use Test::More tests => 12;
+use Test::More tests => 13;
use Crypt::AuthEnc::CCM qw( ccm_encrypt_authenticate ccm_decrypt_verify );
@@ -45,7 +45,9 @@ my $key = "12345678901234561234567890123456";
}
{
- my ($ct, $tag) = ccm_encrypt_authenticate('AES', $key, $nonce, "", 16, "plain_halfplain_half");
+ my ($ct, $tag) = ccm_encrypt_authenticate('AES', $key, $nonce, "", 16, "plain_halfplain_half");
+ my ($ct2, $tag2) = ccm_encrypt_authenticate('AES', $key, $nonce, undef, 16, "plain_halfplain_half");
+ ok($ct eq $ct2 && $tag eq $tag2, "header '' vs. undef");
is(unpack('H*', $ct), "96b0114ff47da72e92631aadce84f203a8168b20", "ccm_encrypt_authenticate: ciphertext (no header)");
is(unpack('H*', $tag), "9e9cba5dd4939d0d8e2687c85c5d3b89", "ccm_encrypt_authenticate: tag (no header)");
my $pt = ccm_decrypt_verify('AES', $key, $nonce, "", $ct, $tag);
diff --git a/t/checksum.t b/t/checksum.t
index b61a4b1b..53488da0 100644
--- a/t/checksum.t
+++ b/t/checksum.t
@@ -1,47 +1,103 @@
use strict;
use warnings;
-use Test::More tests => 24;
-
-use Crypt::Checksum ':all';
-use Crypt::Checksum::Adler32;
-use Crypt::Checksum::CRC32;
-
-my $a32 = Crypt::Checksum::Adler32->new;
-is($a32->hexdigest, "00000001");
-is($a32->hexdigest, "00000001");
-$a32->add("a");
-is($a32->hexdigest, "00620062");
-$a32->reset;
-is($a32->hexdigest, "00000001");
-$a32->add("abc");
-is($a32->hexdigest, "024d0127");
-$a32->reset;
-$a32->add("abc");
-$a32->add("abc");
-is($a32->hexdigest, "080c024d");
-$a32->reset;
-$a32->add("abcabc");
-is($a32->hexdigest, "080c024d");
-$a32->reset;
-$a32->add("\xFF" x 32);
-is($a32->hexdigest, "0e2e1fe1");
-is(adler32_data_hex("a"), "00620062");
-is(adler32_data("a"), pack("H*","00620062"));
-
-is(crc32_data_hex("a"), "e8b7be43");
-is(crc32_data_hex("libtomcrypt"), "b37376ef");
-is(crc32_data_hex("This is the test string"), "6d680973");
-is(crc32_data_int("This is the test string"), 1835534707);
-is(crc32_data_hex("This is another test string"), "806e15e9");
-is(crc32_data_int("This is another test string"), 2154698217);
-
-is(crc32_file_hex("t/data/binary-test.file"), "24111fed");
-is(crc32_file_hex("t/data/text-CR.file"), "1ca430c6");
-is(crc32_file_hex("t/data/text-CRLF.file"), "4d434dfb");
-is(crc32_file_hex("t/data/text-LF.file"), "9f9b8258");
-
-is(adler32_file_hex("t/data/binary-test.file"), "f35fb68a");
-is(adler32_file_hex("t/data/text-CR.file"), "948e2644");
-is(adler32_file_hex("t/data/text-CRLF.file"), "3f0e2702");
-is(adler32_file_hex("t/data/text-LF.file"), "86ba260b");
+use Test::More tests => 56;
+
+use Crypt::Checksum::Adler32 ':all';
+use Crypt::Checksum::CRC32 ':all';
+
+{
+ my $a32 = Crypt::Checksum::Adler32->new;
+ is($a32->hexdigest, "00000001");
+ $a32->add("a");
+ is($a32->hexdigest, "00620062");
+ $a32->reset;
+ is($a32->hexdigest, "00000001");
+ $a32->add("abc");
+ is($a32->hexdigest, "024d0127");
+ $a32->reset;
+ $a32->add("abc");
+ $a32->add("abc");
+ is($a32->hexdigest, "080c024d");
+ $a32->reset;
+ $a32->add("abc", "abc");
+ is($a32->hexdigest, "080c024d");
+ $a32->reset;
+ $a32->add("abcabc");
+ is($a32->hexdigest, "080c024d");
+ $a32->reset;
+ $a32->add("\xFF" x 32);
+ is($a32->hexdigest, "0e2e1fe1");
+ is($a32->intdigest, 237903841);
+ is($a32->digest, pack("H*", "0e2e1fe1"));
+
+ is(adler32_data_hex("aaa"), "02490124");
+ is(adler32_data_int("aaa"), 38338852);
+ is(adler32_data("aaa"), pack("H*","02490124"));
+ is(adler32_data_hex("a","a","a"), "02490124");
+ is(adler32_data_int("a","a","a"), 38338852);
+ is(adler32_data("a","a","a"), pack("H*","02490124"));
+
+ is(adler32_data_hex("libtomcrypt"), "1be804ba");
+ is(adler32_data_hex("This is the test string"), "6363088d");
+ is(adler32_data_int("This is the test string"), 1667434637);
+ is(adler32_data_hex("This is another test string"), "8b900a3d");
+ is(adler32_data_int("This is another test string"), 2341472829);
+
+ is(adler32_file("t/data/binary-test.file"), pack("H*", "f35fb68a"));
+ is(adler32_file_int("t/data/binary-test.file"), 4083136138);
+ is(adler32_file_hex("t/data/binary-test.file"), "f35fb68a");
+ is(Crypt::Checksum::Adler32->new->addfile("t/data/binary-test.file")->hexdigest, "f35fb68a");
+
+ is(adler32_file_hex("t/data/text-CR.file"), "948e2644");
+ is(adler32_file_hex("t/data/text-CRLF.file"), "3f0e2702");
+ is(adler32_file_hex("t/data/text-LF.file"), "86ba260b");
+}
+
+{
+ my $a32 = Crypt::Checksum::CRC32->new;
+ is($a32->hexdigest, "00000000");
+ $a32->add("a");
+ is($a32->hexdigest, "e8b7be43");
+ $a32->reset;
+ is($a32->hexdigest, "00000000");
+ $a32->add("abc");
+ is($a32->hexdigest, "352441c2");
+ $a32->reset;
+ $a32->add("abc");
+ $a32->add("abc");
+ is($a32->hexdigest, "726e994c");
+ $a32->reset;
+ $a32->add("abc", "abc");
+ is($a32->hexdigest, "726e994c");
+ $a32->reset;
+ $a32->add("abcabc");
+ is($a32->hexdigest, "726e994c");
+ $a32->reset;
+ $a32->add("\xFF" x 32);
+ is($a32->hexdigest, "ff6cab0b");
+ is($a32->intdigest, 4285311755);
+ is($a32->digest, pack("H*", "ff6cab0b"));
+
+ is(crc32_data_hex("aaa"), "f007732d");
+ is(crc32_data_int("aaa"), 4027020077);
+ is(crc32_data("aaa"), pack("H*","f007732d"));
+ is(crc32_data_hex("a","a","a"), "f007732d");
+ is(crc32_data_int("a","a","a"), 4027020077);
+ is(crc32_data("a","a","a"), pack("H*","f007732d"));
+
+ is(crc32_data_hex("libtomcrypt"), "b37376ef");
+ is(crc32_data_hex("This is the test string"), "6d680973");
+ is(crc32_data_int("This is the test string"), 1835534707);
+ is(crc32_data_hex("This is another test string"), "806e15e9");
+ is(crc32_data_int("This is another test string"), 2154698217);
+
+ is(crc32_file("t/data/binary-test.file"), pack("H*", "24111fed"));
+ is(crc32_file_int("t/data/binary-test.file"), 605102061);
+ is(crc32_file_hex("t/data/binary-test.file"), "24111fed");
+ is(Crypt::Checksum::CRC32->new->addfile("t/data/binary-test.file")->hexdigest, "24111fed");
+
+ is(crc32_file_hex("t/data/text-CR.file"), "1ca430c6");
+ is(crc32_file_hex("t/data/text-CRLF.file"), "4d434dfb");
+ is(crc32_file_hex("t/data/text-LF.file"), "9f9b8258");
+}
diff --git a/t/crypt-misc.t b/t/crypt-misc.t
index 9cd323d4..d8892f3a 100644
--- a/t/crypt-misc.t
+++ b/t/crypt-misc.t
@@ -1,6 +1,6 @@
use strict;
use warnings;
-use Test::More tests => 679;
+use Test::More tests => 680;
use Crypt::Misc qw( encode_b64 decode_b64
encode_b64u decode_b64u
@@ -143,3 +143,5 @@ for my $h (@hex) {
is(unpack("H*", decode_b32z(encode_b32z($b))), $h);
is(unpack("H*", decode_b32c(encode_b32c($b))), $h);
}
+
+is(decode_b58b("111OIl0"), undef, "bug: decode_b58b + invalid input");
diff --git a/t/digest_blake2b_160.t b/t/digest_blake2b_160.t
index be06610d..c8c39f33 100644
--- a/t/digest_blake2b_160.t
+++ b/t/digest_blake2b_160.t
@@ -3,7 +3,7 @@
use strict;
use warnings;
-use Test::More tests => 8*3 + 9*4 + 6;
+use Test::More tests => 8*3 + 9*4 + 10 + 6;
use Crypt::Digest qw( digest_data digest_data_hex digest_data_b64 digest_data_b64u digest_file digest_file_hex digest_file_b64 digest_file_b64u );
use Crypt::Digest::BLAKE2b_160 qw( blake2b_160 blake2b_160_hex blake2b_160_b64 blake2b_160_b64u blake2b_160_file blake2b_160_file_hex blake2b_160_file_b64 blake2b_160_file_b64u );
@@ -15,6 +15,17 @@ is( Crypt::Digest::BLAKE2b_160->hashsize, 20, 'hashsize/4');
is( Crypt::Digest->new('BLAKE2b_160')->hashsize, 20, 'hashsize/5');
is( Crypt::Digest::BLAKE2b_160->new->hashsize, 20, 'hashsize/6');
+is( blake2b_160("A","A","A"), pack("H*","14517ce78b0c7e5e5b7f096f1f3c046f01c46901"), 'blake2b_160 (raw/tripple_A)');
+is( blake2b_160_hex("A","A","A"), "14517ce78b0c7e5e5b7f096f1f3c046f01c46901", 'blake2b_160 (hex/tripple_A)');
+is( blake2b_160_b64("A","A","A"), "FFF854sMfl5bfwlvHzwEbwHEaQE=", 'blake2b_160 (base64/tripple_A)');
+is( blake2b_160_b64u("A","A","A"), "FFF854sMfl5bfwlvHzwEbwHEaQE", 'blake2b_160 (base64url/tripple_A)');
+is( digest_data('BLAKE2b_160', "A","A","A"), pack("H*","14517ce78b0c7e5e5b7f096f1f3c046f01c46901"), 'blake2b_160 (digest_data_raw/tripple_A)');
+is( digest_data_hex('BLAKE2b_160', "A","A","A"), "14517ce78b0c7e5e5b7f096f1f3c046f01c46901", 'blake2b_160 (digest_data_hex/tripple_A)');
+is( digest_data_b64('BLAKE2b_160', "A","A","A"), "FFF854sMfl5bfwlvHzwEbwHEaQE=", 'blake2b_160 (digest_data_b64/tripple_A)');
+is( digest_data_b64u('BLAKE2b_160', "A","A","A"), "FFF854sMfl5bfwlvHzwEbwHEaQE", 'blake2b_160 (digest_data_b64u/tripple_A)');
+is( Crypt::Digest::BLAKE2b_160->new->add("A","A","A")->hexdigest, "14517ce78b0c7e5e5b7f096f1f3c046f01c46901", 'blake2b_160 (OO/tripple_A)');
+is( Crypt::Digest::BLAKE2b_160->new->add("A")->add("A")->add("A")->hexdigest, "14517ce78b0c7e5e5b7f096f1f3c046f01c46901", 'blake2b_160 (OO3/tripple_A)');
+
is( blake2b_160(""), pack("H*","3345524abf6bbe1809449224b5972c41790b6cf2"), 'blake2b_160 (raw/1)');
is( blake2b_160_hex(""), "3345524abf6bbe1809449224b5972c41790b6cf2", 'blake2b_160 (hex/1)');
diff --git a/t/digest_blake2b_256.t b/t/digest_blake2b_256.t
index 1b717378..a4f1d09b 100644
--- a/t/digest_blake2b_256.t
+++ b/t/digest_blake2b_256.t
@@ -3,7 +3,7 @@
use strict;
use warnings;
-use Test::More tests => 8*3 + 9*4 + 6;
+use Test::More tests => 8*3 + 9*4 + 10 + 6;
use Crypt::Digest qw( digest_data digest_data_hex digest_data_b64 digest_data_b64u digest_file digest_file_hex digest_file_b64 digest_file_b64u );
use Crypt::Digest::BLAKE2b_256 qw( blake2b_256 blake2b_256_hex blake2b_256_b64 blake2b_256_b64u blake2b_256_file blake2b_256_file_hex blake2b_256_file_b64 blake2b_256_file_b64u );
@@ -15,6 +15,17 @@ is( Crypt::Digest::BLAKE2b_256->hashsize, 32, 'hashsize/4');
is( Crypt::Digest->new('BLAKE2b_256')->hashsize, 32, 'hashsize/5');
is( Crypt::Digest::BLAKE2b_256->new->hashsize, 32, 'hashsize/6');
+is( blake2b_256("A","A","A"), pack("H*","cdc4339296753f930aa454700fd0ded6e1e08772dea849859e17dbbd85cae649"), 'blake2b_256 (raw/tripple_A)');
+is( blake2b_256_hex("A","A","A"), "cdc4339296753f930aa454700fd0ded6e1e08772dea849859e17dbbd85cae649", 'blake2b_256 (hex/tripple_A)');
+is( blake2b_256_b64("A","A","A"), "zcQzkpZ1P5MKpFRwD9De1uHgh3LeqEmFnhfbvYXK5kk=", 'blake2b_256 (base64/tripple_A)');
+is( blake2b_256_b64u("A","A","A"), "zcQzkpZ1P5MKpFRwD9De1uHgh3LeqEmFnhfbvYXK5kk", 'blake2b_256 (base64url/tripple_A)');
+is( digest_data('BLAKE2b_256', "A","A","A"), pack("H*","cdc4339296753f930aa454700fd0ded6e1e08772dea849859e17dbbd85cae649"), 'blake2b_256 (digest_data_raw/tripple_A)');
+is( digest_data_hex('BLAKE2b_256', "A","A","A"), "cdc4339296753f930aa454700fd0ded6e1e08772dea849859e17dbbd85cae649", 'blake2b_256 (digest_data_hex/tripple_A)');
+is( digest_data_b64('BLAKE2b_256', "A","A","A"), "zcQzkpZ1P5MKpFRwD9De1uHgh3LeqEmFnhfbvYXK5kk=", 'blake2b_256 (digest_data_b64/tripple_A)');
+is( digest_data_b64u('BLAKE2b_256', "A","A","A"), "zcQzkpZ1P5MKpFRwD9De1uHgh3LeqEmFnhfbvYXK5kk", 'blake2b_256 (digest_data_b64u/tripple_A)');
+is( Crypt::Digest::BLAKE2b_256->new->add("A","A","A")->hexdigest, "cdc4339296753f930aa454700fd0ded6e1e08772dea849859e17dbbd85cae649", 'blake2b_256 (OO/tripple_A)');
+is( Crypt::Digest::BLAKE2b_256->new->add("A")->add("A")->add("A")->hexdigest, "cdc4339296753f930aa454700fd0ded6e1e08772dea849859e17dbbd85cae649", 'blake2b_256 (OO3/tripple_A)');
+
is( blake2b_256(""), pack("H*","0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8"), 'blake2b_256 (raw/1)');
is( blake2b_256_hex(""), "0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8", 'blake2b_256 (hex/1)');
diff --git a/t/digest_blake2b_384.t b/t/digest_blake2b_384.t
index 1ed548ba..f686152a 100644
--- a/t/digest_blake2b_384.t
+++ b/t/digest_blake2b_384.t
@@ -3,7 +3,7 @@
use strict;
use warnings;
-use Test::More tests => 8*3 + 9*4 + 6;
+use Test::More tests => 8*3 + 9*4 + 10 + 6;
use Crypt::Digest qw( digest_data digest_data_hex digest_data_b64 digest_data_b64u digest_file digest_file_hex digest_file_b64 digest_file_b64u );
use Crypt::Digest::BLAKE2b_384 qw( blake2b_384 blake2b_384_hex blake2b_384_b64 blake2b_384_b64u blake2b_384_file blake2b_384_file_hex blake2b_384_file_b64 blake2b_384_file_b64u );
@@ -15,6 +15,17 @@ is( Crypt::Digest::BLAKE2b_384->hashsize, 48, 'hashsize/4');
is( Crypt::Digest->new('BLAKE2b_384')->hashsize, 48, 'hashsize/5');
is( Crypt::Digest::BLAKE2b_384->new->hashsize, 48, 'hashsize/6');
+is( blake2b_384("A","A","A"), pack("H*","9aa07d9caf17bff49747fc9488eb6babcdcd575616f85a91758ee50e6e49a4884bf6fb46b424e0ae669071ccd8cb1685"), 'blake2b_384 (raw/tripple_A)');
+is( blake2b_384_hex("A","A","A"), "9aa07d9caf17bff49747fc9488eb6babcdcd575616f85a91758ee50e6e49a4884bf6fb46b424e0ae669071ccd8cb1685", 'blake2b_384 (hex/tripple_A)');
+is( blake2b_384_b64("A","A","A"), "mqB9nK8Xv/SXR/yUiOtrq83NV1YW+FqRdY7lDm5JpIhL9vtGtCTgrmaQcczYyxaF", 'blake2b_384 (base64/tripple_A)');
+is( blake2b_384_b64u("A","A","A"), "mqB9nK8Xv_SXR_yUiOtrq83NV1YW-FqRdY7lDm5JpIhL9vtGtCTgrmaQcczYyxaF", 'blake2b_384 (base64url/tripple_A)');
+is( digest_data('BLAKE2b_384', "A","A","A"), pack("H*","9aa07d9caf17bff49747fc9488eb6babcdcd575616f85a91758ee50e6e49a4884bf6fb46b424e0ae669071ccd8cb1685"), 'blake2b_384 (digest_data_raw/tripple_A)');
+is( digest_data_hex('BLAKE2b_384', "A","A","A"), "9aa07d9caf17bff49747fc9488eb6babcdcd575616f85a91758ee50e6e49a4884bf6fb46b424e0ae669071ccd8cb1685", 'blake2b_384 (digest_data_hex/tripple_A)');
+is( digest_data_b64('BLAKE2b_384', "A","A","A"), "mqB9nK8Xv/SXR/yUiOtrq83NV1YW+FqRdY7lDm5JpIhL9vtGtCTgrmaQcczYyxaF", 'blake2b_384 (digest_data_b64/tripple_A)');
+is( digest_data_b64u('BLAKE2b_384', "A","A","A"), "mqB9nK8Xv_SXR_yUiOtrq83NV1YW-FqRdY7lDm5JpIhL9vtGtCTgrmaQcczYyxaF", 'blake2b_384 (digest_data_b64u/tripple_A)');
+is( Crypt::Digest::BLAKE2b_384->new->add("A","A","A")->hexdigest, "9aa07d9caf17bff49747fc9488eb6babcdcd575616f85a91758ee50e6e49a4884bf6fb46b424e0ae669071ccd8cb1685", 'blake2b_384 (OO/tripple_A)');
+is( Crypt::Digest::BLAKE2b_384->new->add("A")->add("A")->add("A")->hexdigest, "9aa07d9caf17bff49747fc9488eb6babcdcd575616f85a91758ee50e6e49a4884bf6fb46b424e0ae669071ccd8cb1685", 'blake2b_384 (OO3/tripple_A)');
+
is( blake2b_384(""), pack("H*","b32811423377f52d7862286ee1a72ee540524380fda1724a6f25d7978c6fd3244a6caf0498812673c5e05ef583825100"), 'blake2b_384 (raw/1)');
is( blake2b_384_hex(""), "b32811423377f52d7862286ee1a72ee540524380fda1724a6f25d7978c6fd3244a6caf0498812673c5e05ef583825100", 'blake2b_384 (hex/1)');
diff --git a/t/digest_blake2b_512.t b/t/digest_blake2b_512.t
index 02d2a33b..ac1132a4 100644
--- a/t/digest_blake2b_512.t
+++ b/t/digest_blake2b_512.t
@@ -3,7 +3,7 @@
use strict;
use warnings;
-use Test::More tests => 8*3 + 9*4 + 6;
+use Test::More tests => 8*3 + 9*4 + 10 + 6;
use Crypt::Digest qw( digest_data digest_data_hex digest_data_b64 digest_data_b64u digest_file digest_file_hex digest_file_b64 digest_file_b64u );
use Crypt::Digest::BLAKE2b_512 qw( blake2b_512 blake2b_512_hex blake2b_512_b64 blake2b_512_b64u blake2b_512_file blake2b_512_file_hex blake2b_512_file_b64 blake2b_512_file_b64u );
@@ -15,6 +15,17 @@ is( Crypt::Digest::BLAKE2b_512->hashsize, 64, 'hashsize/4');
is( Crypt::Digest->new('BLAKE2b_512')->hashsize, 64, 'hashsize/5');
is( Crypt::Digest::BLAKE2b_512->new->hashsize, 64, 'hashsize/6');
+is( blake2b_512("A","A","A"), pack("H*","dda5c92ae5adba047d317f99dc58a9059b5a8c0907f95d8cddcf5bfdaa8e4c74ddd84bc2683cdc2d16a340ff5798e1bf4bd2c838332611f266bb62870d33b823"), 'blake2b_512 (raw/tripple_A)');
+is( blake2b_512_hex("A","A","A"), "dda5c92ae5adba047d317f99dc58a9059b5a8c0907f95d8cddcf5bfdaa8e4c74ddd84bc2683cdc2d16a340ff5798e1bf4bd2c838332611f266bb62870d33b823", 'blake2b_512 (hex/tripple_A)');
+is( blake2b_512_b64("A","A","A"), "3aXJKuWtugR9MX+Z3FipBZtajAkH+V2M3c9b/aqOTHTd2EvCaDzcLRajQP9XmOG/S9LIODMmEfJmu2KHDTO4Iw==", 'blake2b_512 (base64/tripple_A)');
+is( blake2b_512_b64u("A","A","A"), "3aXJKuWtugR9MX-Z3FipBZtajAkH-V2M3c9b_aqOTHTd2EvCaDzcLRajQP9XmOG_S9LIODMmEfJmu2KHDTO4Iw", 'blake2b_512 (base64url/tripple_A)');
+is( digest_data('BLAKE2b_512', "A","A","A"), pack("H*","dda5c92ae5adba047d317f99dc58a9059b5a8c0907f95d8cddcf5bfdaa8e4c74ddd84bc2683cdc2d16a340ff5798e1bf4bd2c838332611f266bb62870d33b823"), 'blake2b_512 (digest_data_raw/tripple_A)');
+is( digest_data_hex('BLAKE2b_512', "A","A","A"), "dda5c92ae5adba047d317f99dc58a9059b5a8c0907f95d8cddcf5bfdaa8e4c74ddd84bc2683cdc2d16a340ff5798e1bf4bd2c838332611f266bb62870d33b823", 'blake2b_512 (digest_data_hex/tripple_A)');
+is( digest_data_b64('BLAKE2b_512', "A","A","A"), "3aXJKuWtugR9MX+Z3FipBZtajAkH+V2M3c9b/aqOTHTd2EvCaDzcLRajQP9XmOG/S9LIODMmEfJmu2KHDTO4Iw==", 'blake2b_512 (digest_data_b64/tripple_A)');
+is( digest_data_b64u('BLAKE2b_512', "A","A","A"), "3aXJKuWtugR9MX-Z3FipBZtajAkH-V2M3c9b_aqOTHTd2EvCaDzcLRajQP9XmOG_S9LIODMmEfJmu2KHDTO4Iw", 'blake2b_512 (digest_data_b64u/tripple_A)');
+is( Crypt::Digest::BLAKE2b_512->new->add("A","A","A")->hexdigest, "dda5c92ae5adba047d317f99dc58a9059b5a8c0907f95d8cddcf5bfdaa8e4c74ddd84bc2683cdc2d16a340ff5798e1bf4bd2c838332611f266bb62870d33b823", 'blake2b_512 (OO/tripple_A)');
+is( Crypt::Digest::BLAKE2b_512->new->add("A")->add("A")->add("A")->hexdigest, "dda5c92ae5adba047d317f99dc58a9059b5a8c0907f95d8cddcf5bfdaa8e4c74ddd84bc2683cdc2d16a340ff5798e1bf4bd2c838332611f266bb62870d33b823", 'blake2b_512 (OO3/tripple_A)');
+
is( blake2b_512(""), pack("H*","786a02f742015903c6c6fd852552d272912f4740e15847618a86e217f71f5419d25e1031afee585313896444934eb04b903a685b1448b755d56f701afe9be2ce"), 'blake2b_512 (raw/1)');
is( blake2b_512_hex(""), "786a02f742015903c6c6fd852552d272912f4740e15847618a86e217f71f5419d25e1031afee585313896444934eb04b903a685b1448b755d56f701afe9be2ce", 'blake2b_512 (hex/1)');
diff --git a/t/digest_blake2s_128.t b/t/digest_blake2s_128.t
index eafbcf7f..b46783ba 100644
--- a/t/digest_blake2s_128.t
+++ b/t/digest_blake2s_128.t
@@ -3,7 +3,7 @@
use strict;
use warnings;
-use Test::More tests => 8*3 + 9*4 + 6;
+use Test::More tests => 8*3 + 9*4 + 10 + 6;
use Crypt::Digest qw( digest_data digest_data_hex digest_data_b64 digest_data_b64u digest_file digest_file_hex digest_file_b64 digest_file_b64u );
use Crypt::Digest::BLAKE2s_128 qw( blake2s_128 blake2s_128_hex blake2s_128_b64 blake2s_128_b64u blake2s_128_file blake2s_128_file_hex blake2s_128_file_b64 blake2s_128_file_b64u );
@@ -15,6 +15,17 @@ is( Crypt::Digest::BLAKE2s_128->hashsize, 16, 'hashsize/4');
is( Crypt::Digest->new('BLAKE2s_128')->hashsize, 16, 'hashsize/5');
is( Crypt::Digest::BLAKE2s_128->new->hashsize, 16, 'hashsize/6');
+is( blake2s_128("A","A","A"), pack("H*","a2a5699c7579ee354f4d20fa75f09cb6"), 'blake2s_128 (raw/tripple_A)');
+is( blake2s_128_hex("A","A","A"), "a2a5699c7579ee354f4d20fa75f09cb6", 'blake2s_128 (hex/tripple_A)');
+is( blake2s_128_b64("A","A","A"), "oqVpnHV57jVPTSD6dfCctg==", 'blake2s_128 (base64/tripple_A)');
+is( blake2s_128_b64u("A","A","A"), "oqVpnHV57jVPTSD6dfCctg", 'blake2s_128 (base64url/tripple_A)');
+is( digest_data('BLAKE2s_128', "A","A","A"), pack("H*","a2a5699c7579ee354f4d20fa75f09cb6"), 'blake2s_128 (digest_data_raw/tripple_A)');
+is( digest_data_hex('BLAKE2s_128', "A","A","A"), "a2a5699c7579ee354f4d20fa75f09cb6", 'blake2s_128 (digest_data_hex/tripple_A)');
+is( digest_data_b64('BLAKE2s_128', "A","A","A"), "oqVpnHV57jVPTSD6dfCctg==", 'blake2s_128 (digest_data_b64/tripple_A)');
+is( digest_data_b64u('BLAKE2s_128', "A","A","A"), "oqVpnHV57jVPTSD6dfCctg", 'blake2s_128 (digest_data_b64u/tripple_A)');
+is( Crypt::Digest::BLAKE2s_128->new->add("A","A","A")->hexdigest, "a2a5699c7579ee354f4d20fa75f09cb6", 'blake2s_128 (OO/tripple_A)');
+is( Crypt::Digest::BLAKE2s_128->new->add("A")->add("A")->add("A")->hexdigest, "a2a5699c7579ee354f4d20fa75f09cb6", 'blake2s_128 (OO3/tripple_A)');
+
is( blake2s_128(""), pack("H*","64550d6ffe2c0a01a14aba1eade0200c"), 'blake2s_128 (raw/1)');
is( blake2s_128_hex(""), "64550d6ffe2c0a01a14aba1eade0200c", 'blake2s_128 (hex/1)');
diff --git a/t/digest_blake2s_160.t b/t/digest_blake2s_160.t
index e30a01b5..03802391 100644
--- a/t/digest_blake2s_160.t
+++ b/t/digest_blake2s_160.t
@@ -3,7 +3,7 @@
use strict;
use warnings;
-use Test::More tests => 8*3 + 9*4 + 6;
+use Test::More tests => 8*3 + 9*4 + 10 + 6;
use Crypt::Digest qw( digest_data digest_data_hex digest_data_b64 digest_data_b64u digest_file digest_file_hex digest_file_b64 digest_file_b64u );
use Crypt::Digest::BLAKE2s_160 qw( blake2s_160 blake2s_160_hex blake2s_160_b64 blake2s_160_b64u blake2s_160_file blake2s_160_file_hex blake2s_160_file_b64 blake2s_160_file_b64u );
@@ -15,6 +15,17 @@ is( Crypt::Digest::BLAKE2s_160->hashsize, 20, 'hashsize/4');
is( Crypt::Digest->new('BLAKE2s_160')->hashsize, 20, 'hashsize/5');
is( Crypt::Digest::BLAKE2s_160->new->hashsize, 20, 'hashsize/6');
+is( blake2s_160("A","A","A"), pack("H*","f44c709aebd62a7a13bd6ee5979981970a60e117"), 'blake2s_160 (raw/tripple_A)');
+is( blake2s_160_hex("A","A","A"), "f44c709aebd62a7a13bd6ee5979981970a60e117", 'blake2s_160 (hex/tripple_A)');
+is( blake2s_160_b64("A","A","A"), "9ExwmuvWKnoTvW7ll5mBlwpg4Rc=", 'blake2s_160 (base64/tripple_A)');
+is( blake2s_160_b64u("A","A","A"), "9ExwmuvWKnoTvW7ll5mBlwpg4Rc", 'blake2s_160 (base64url/tripple_A)');
+is( digest_data('BLAKE2s_160', "A","A","A"), pack("H*","f44c709aebd62a7a13bd6ee5979981970a60e117"), 'blake2s_160 (digest_data_raw/tripple_A)');
+is( digest_data_hex('BLAKE2s_160', "A","A","A"), "f44c709aebd62a7a13bd6ee5979981970a60e117", 'blake2s_160 (digest_data_hex/tripple_A)');
+is( digest_data_b64('BLAKE2s_160', "A","A","A"), "9ExwmuvWKnoTvW7ll5mBlwpg4Rc=", 'blake2s_160 (digest_data_b64/tripple_A)');
+is( digest_data_b64u('BLAKE2s_160', "A","A","A"), "9ExwmuvWKnoTvW7ll5mBlwpg4Rc", 'blake2s_160 (digest_data_b64u/tripple_A)');
+is( Crypt::Digest::BLAKE2s_160->new->add("A","A","A")->hexdigest, "f44c709aebd62a7a13bd6ee5979981970a60e117", 'blake2s_160 (OO/tripple_A)');
+is( Crypt::Digest::BLAKE2s_160->new->add("A")->add("A")->add("A")->hexdigest, "f44c709aebd62a7a13bd6ee5979981970a60e117", 'blake2s_160 (OO3/tripple_A)');
+
is( blake2s_160(""), pack("H*","354c9c33f735962418bdacb9479873429c34916f"), 'blake2s_160 (raw/1)');
is( blake2s_160_hex(""), "354c9c33f735962418bdacb9479873429c34916f", 'blake2s_160 (hex/1)');
diff --git a/t/digest_blake2s_224.t b/t/digest_blake2s_224.t
index b96349a9..eeb96f77 100644
--- a/t/digest_blake2s_224.t
+++ b/t/digest_blake2s_224.t
@@ -3,7 +3,7 @@
use strict;
use warnings;
-use Test::More tests => 8*3 + 9*4 + 6;
+use Test::More tests => 8*3 + 9*4 + 10 + 6;
use Crypt::Digest qw( digest_data digest_data_hex digest_data_b64 digest_data_b64u digest_file digest_file_hex digest_file_b64 digest_file_b64u );
use Crypt::Digest::BLAKE2s_224 qw( blake2s_224 blake2s_224_hex blake2s_224_b64 blake2s_224_b64u blake2s_224_file blake2s_224_file_hex blake2s_224_file_b64 blake2s_224_file_b64u );
@@ -15,6 +15,17 @@ is( Crypt::Digest::BLAKE2s_224->hashsize, 28, 'hashsize/4');
is( Crypt::Digest->new('BLAKE2s_224')->hashsize, 28, 'hashsize/5');
is( Crypt::Digest::BLAKE2s_224->new->hashsize, 28, 'hashsize/6');
+is( blake2s_224("A","A","A"), pack("H*","8c2738e18d0b9645870d7da4b52756cef46c5f3d185f4ea93c361006"), 'blake2s_224 (raw/tripple_A)');
+is( blake2s_224_hex("A","A","A"), "8c2738e18d0b9645870d7da4b52756cef46c5f3d185f4ea93c361006", 'blake2s_224 (hex/tripple_A)');
+is( blake2s_224_b64("A","A","A"), "jCc44Y0LlkWHDX2ktSdWzvRsXz0YX06pPDYQBg==", 'blake2s_224 (base64/tripple_A)');
+is( blake2s_224_b64u("A","A","A"), "jCc44Y0LlkWHDX2ktSdWzvRsXz0YX06pPDYQBg", 'blake2s_224 (base64url/tripple_A)');
+is( digest_data('BLAKE2s_224', "A","A","A"), pack("H*","8c2738e18d0b9645870d7da4b52756cef46c5f3d185f4ea93c361006"), 'blake2s_224 (digest_data_raw/tripple_A)');
+is( digest_data_hex('BLAKE2s_224', "A","A","A"), "8c2738e18d0b9645870d7da4b52756cef46c5f3d185f4ea93c361006", 'blake2s_224 (digest_data_hex/tripple_A)');
+is( digest_data_b64('BLAKE2s_224', "A","A","A"), "jCc44Y0LlkWHDX2ktSdWzvRsXz0YX06pPDYQBg==", 'blake2s_224 (digest_data_b64/tripple_A)');
+is( digest_data_b64u('BLAKE2s_224', "A","A","A"), "jCc44Y0LlkWHDX2ktSdWzvRsXz0YX06pPDYQBg", 'blake2s_224 (digest_data_b64u/tripple_A)');
+is( Crypt::Digest::BLAKE2s_224->new->add("A","A","A")->hexdigest, "8c2738e18d0b9645870d7da4b52756cef46c5f3d185f4ea93c361006", 'blake2s_224 (OO/tripple_A)');
+is( Crypt::Digest::BLAKE2s_224->new->add("A")->add("A")->add("A")->hexdigest, "8c2738e18d0b9645870d7da4b52756cef46c5f3d185f4ea93c361006", 'blake2s_224 (OO3/tripple_A)');
+
is( blake2s_224(""), pack("H*","1fa1291e65248b37b3433475b2a0dd63d54a11ecc4e3e034e7bc1ef4"), 'blake2s_224 (raw/1)');
is( blake2s_224_hex(""), "1fa1291e65248b37b3433475b2a0dd63d54a11ecc4e3e034e7bc1ef4", 'blake2s_224 (hex/1)');
diff --git a/t/digest_blake2s_256.t b/t/digest_blake2s_256.t
index 7441c1b0..71ff957e 100644
--- a/t/digest_blake2s_256.t
+++ b/t/digest_blake2s_256.t
@@ -3,7 +3,7 @@
use strict;
use warnings;
-use Test::More tests => 8*3 + 9*4 + 6;
+use Test::More tests => 8*3 + 9*4 + 10 + 6;
use Crypt::Digest qw( digest_data digest_data_hex digest_data_b64 digest_data_b64u digest_file digest_file_hex digest_file_b64 digest_file_b64u );
use Crypt::Digest::BLAKE2s_256 qw( blake2s_256 blake2s_256_hex blake2s_256_b64 blake2s_256_b64u blake2s_256_file blake2s_256_file_hex blake2s_256_file_b64 blake2s_256_file_b64u );
@@ -15,6 +15,17 @@ is( Crypt::Digest::BLAKE2s_256->hashsize, 32, 'hashsize/4');
is( Crypt::Digest->new('BLAKE2s_256')->hashsize, 32, 'hashsize/5');
is( Crypt::Digest::BLAKE2s_256->new->hashsize, 32, 'hashsize/6');
+is( blake2s_256("A","A","A"), pack("H*","8d4fe9f5368ff397ce7444640f522f090597591c21392262138da6750bf1dff6"), 'blake2s_256 (raw/tripple_A)');
+is( blake2s_256_hex("A","A","A"), "8d4fe9f5368ff397ce7444640f522f090597591c21392262138da6750bf1dff6", 'blake2s_256 (hex/tripple_A)');
+is( blake2s_256_b64("A","A","A"), "jU/p9TaP85fOdERkD1IvCQWXWRwhOSJiE42mdQvx3/Y=", 'blake2s_256 (base64/tripple_A)');
+is( blake2s_256_b64u("A","A","A"), "jU_p9TaP85fOdERkD1IvCQWXWRwhOSJiE42mdQvx3_Y", 'blake2s_256 (base64url/tripple_A)');
+is( digest_data('BLAKE2s_256', "A","A","A"), pack("H*","8d4fe9f5368ff397ce7444640f522f090597591c21392262138da6750bf1dff6"), 'blake2s_256 (digest_data_raw/tripple_A)');
+is( digest_data_hex('BLAKE2s_256', "A","A","A"), "8d4fe9f5368ff397ce7444640f522f090597591c21392262138da6750bf1dff6", 'blake2s_256 (digest_data_hex/tripple_A)');
+is( digest_data_b64('BLAKE2s_256', "A","A","A"), "jU/p9TaP85fOdERkD1IvCQWXWRwhOSJiE42mdQvx3/Y=", 'blake2s_256 (digest_data_b64/tripple_A)');
+is( digest_data_b64u('BLAKE2s_256', "A","A","A"), "jU_p9TaP85fOdERkD1IvCQWXWRwhOSJiE42mdQvx3_Y", 'blake2s_256 (digest_data_b64u/tripple_A)');
+is( Crypt::Digest::BLAKE2s_256->new->add("A","A","A")->hexdigest, "8d4fe9f5368ff397ce7444640f522f090597591c21392262138da6750bf1dff6", 'blake2s_256 (OO/tripple_A)');
+is( Crypt::Digest::BLAKE2s_256->new->add("A")->add("A")->add("A")->hexdigest, "8d4fe9f5368ff397ce7444640f522f090597591c21392262138da6750bf1dff6", 'blake2s_256 (OO3/tripple_A)');
+
is( blake2s_256(""), pack("H*","69217a3079908094e11121d042354a7c1f55b6482ca1a51e1b250dfd1ed0eef9"), 'blake2s_256 (raw/1)');
is( blake2s_256_hex(""), "69217a3079908094e11121d042354a7c1f55b6482ca1a51e1b250dfd1ed0eef9", 'blake2s_256 (hex/1)');
diff --git a/t/digest_chaes.t b/t/digest_chaes.t
index 82534d19..82b496e6 100644
--- a/t/digest_chaes.t
+++ b/t/digest_chaes.t
@@ -3,7 +3,7 @@
use strict;
use warnings;
-use Test::More tests => 8*3 + 9*4 + 6;
+use Test::More tests => 8*3 + 9*4 + 10 + 6;
use Crypt::Digest qw( digest_data digest_data_hex digest_data_b64 digest_data_b64u digest_file digest_file_hex digest_file_b64 digest_file_b64u );
use Crypt::Digest::CHAES qw( chaes chaes_hex chaes_b64 chaes_b64u chaes_file chaes_file_hex chaes_file_b64 chaes_file_b64u );
@@ -15,6 +15,17 @@ is( Crypt::Digest::CHAES->hashsize, 16, 'hashsize/4');
is( Crypt::Digest->new('CHAES')->hashsize, 16, 'hashsize/5');
is( Crypt::Digest::CHAES->new->hashsize, 16, 'hashsize/6');
+is( chaes("A","A","A"), pack("H*","f01416b4c3f6389816b2fcd0b4cf9e41"), 'chaes (raw/tripple_A)');
+is( chaes_hex("A","A","A"), "f01416b4c3f6389816b2fcd0b4cf9e41", 'chaes (hex/tripple_A)');
+is( chaes_b64("A","A","A"), "8BQWtMP2OJgWsvzQtM+eQQ==", 'chaes (base64/tripple_A)');
+is( chaes_b64u("A","A","A"), "8BQWtMP2OJgWsvzQtM-eQQ", 'chaes (base64url/tripple_A)');
+is( digest_data('CHAES', "A","A","A"), pack("H*","f01416b4c3f6389816b2fcd0b4cf9e41"), 'chaes (digest_data_raw/tripple_A)');
+is( digest_data_hex('CHAES', "A","A","A"), "f01416b4c3f6389816b2fcd0b4cf9e41", 'chaes (digest_data_hex/tripple_A)');
+is( digest_data_b64('CHAES', "A","A","A"), "8BQWtMP2OJgWsvzQtM+eQQ==", 'chaes (digest_data_b64/tripple_A)');
+is( digest_data_b64u('CHAES', "A","A","A"), "8BQWtMP2OJgWsvzQtM-eQQ", 'chaes (digest_data_b64u/tripple_A)');
+is( Crypt::Digest::CHAES->new->add("A","A","A")->hexdigest, "f01416b4c3f6389816b2fcd0b4cf9e41", 'chaes (OO/tripple_A)');
+is( Crypt::Digest::CHAES->new->add("A")->add("A")->add("A")->hexdigest, "f01416b4c3f6389816b2fcd0b4cf9e41", 'chaes (OO3/tripple_A)');
+
is( chaes(""), pack("H*","4047929f1f572643b55f829eb3291d11"), 'chaes (raw/1)');
is( chaes_hex(""), "4047929f1f572643b55f829eb3291d11", 'chaes (hex/1)');
diff --git a/t/digest_keccak224.t b/t/digest_keccak224.t
new file mode 100644
index 00000000..10daf0e6
--- /dev/null
+++ b/t/digest_keccak224.t
@@ -0,0 +1,116 @@
+### BEWARE - GENERATED FILE, DO NOT EDIT MANUALLY!
+
+use strict;
+use warnings;
+
+use Test::More tests => 8*3 + 9*4 + 10 + 6;
+
+use Crypt::Digest qw( digest_data digest_data_hex digest_data_b64 digest_data_b64u digest_file digest_file_hex digest_file_b64 digest_file_b64u );
+use Crypt::Digest::Keccak224 qw( keccak224 keccak224_hex keccak224_b64 keccak224_b64u keccak224_file keccak224_file_hex keccak224_file_b64 keccak224_file_b64u );
+
+is( Crypt::Digest::hashsize('Keccak224'), 28, 'hashsize/1');
+is( Crypt::Digest->hashsize('Keccak224'), 28, 'hashsize/2');
+is( Crypt::Digest::Keccak224::hashsize, 28, 'hashsize/3');
+is( Crypt::Digest::Keccak224->hashsize, 28, 'hashsize/4');
+is( Crypt::Digest->new('Keccak224')->hashsize, 28, 'hashsize/5');
+is( Crypt::Digest::Keccak224->new->hashsize, 28, 'hashsize/6');
+
+is( keccak224("A","A","A"), pack("H*","92b9d2a25222d2a036c53bd4dd246b4073d100e0ae20ac7240f5b252"), 'keccak224 (raw/tripple_A)');
+is( keccak224_hex("A","A","A"), "92b9d2a25222d2a036c53bd4dd246b4073d100e0ae20ac7240f5b252", 'keccak224 (hex/tripple_A)');
+is( keccak224_b64("A","A","A"), "krnSolIi0qA2xTvU3SRrQHPRAOCuIKxyQPWyUg==", 'keccak224 (base64/tripple_A)');
+is( keccak224_b64u("A","A","A"), "krnSolIi0qA2xTvU3SRrQHPRAOCuIKxyQPWyUg", 'keccak224 (base64url/tripple_A)');
+is( digest_data('Keccak224', "A","A","A"), pack("H*","92b9d2a25222d2a036c53bd4dd246b4073d100e0ae20ac7240f5b252"), 'keccak224 (digest_data_raw/tripple_A)');
+is( digest_data_hex('Keccak224', "A","A","A"), "92b9d2a25222d2a036c53bd4dd246b4073d100e0ae20ac7240f5b252", 'keccak224 (digest_data_hex/tripple_A)');
+is( digest_data_b64('Keccak224', "A","A","A"), "krnSolIi0qA2xTvU3SRrQHPRAOCuIKxyQPWyUg==", 'keccak224 (digest_data_b64/tripple_A)');
+is( digest_data_b64u('Keccak224', "A","A","A"), "krnSolIi0qA2xTvU3SRrQHPRAOCuIKxyQPWyUg", 'keccak224 (digest_data_b64u/tripple_A)');
+is( Crypt::Digest::Keccak224->new->add("A","A","A")->hexdigest, "92b9d2a25222d2a036c53bd4dd246b4073d100e0ae20ac7240f5b252", 'keccak224 (OO/tripple_A)');
+is( Crypt::Digest::Keccak224->new->add("A")->add("A")->add("A")->hexdigest, "92b9d2a25222d2a036c53bd4dd246b4073d100e0ae20ac7240f5b252", 'keccak224 (OO3/tripple_A)');
+
+
+is( keccak224(""), pack("H*","f71837502ba8e10837bdd8d365adb85591895602fc552b48b7390abd"), 'keccak224 (raw/1)');
+is( keccak224_hex(""), "f71837502ba8e10837bdd8d365adb85591895602fc552b48b7390abd", 'keccak224 (hex/1)');
+is( keccak224_b64(""), "9xg3UCuo4Qg3vdjTZa24VZGJVgL8VStItzkKvQ==", 'keccak224 (base64/1)');
+is( digest_data('Keccak224', ""), pack("H*","f71837502ba8e10837bdd8d365adb85591895602fc552b48b7390abd"), 'keccak224 (digest_data_raw/1)');
+is( digest_data_hex('Keccak224', ""), "f71837502ba8e10837bdd8d365adb85591895602fc552b48b7390abd", 'keccak224 (digest_data_hex/1)');
+is( digest_data_b64('Keccak224', ""), "9xg3UCuo4Qg3vdjTZa24VZGJVgL8VStItzkKvQ==", 'keccak224 (digest_data_b64/1)');
+is( digest_data_b64u('Keccak224', ""), "9xg3UCuo4Qg3vdjTZa24VZGJVgL8VStItzkKvQ", 'keccak224 (digest_data_b64u/1)');
+is( Crypt::Digest::Keccak224->new->add("")->hexdigest, "f71837502ba8e10837bdd8d365adb85591895602fc552b48b7390abd", 'keccak224 (OO/1)');
+
+is( keccak224("123"), pack("H*","5c52615361ce4c5469f9d8c90113c7a543a4bf43490782d291cb32d8"), 'keccak224 (raw/2)');
+is( keccak224_hex("123"), "5c52615361ce4c5469f9d8c90113c7a543a4bf43490782d291cb32d8", 'keccak224 (hex/2)');
+is( keccak224_b64("123"), "XFJhU2HOTFRp+djJARPHpUOkv0NJB4LSkcsy2A==", 'keccak224 (base64/2)');
+is( digest_data('Keccak224', "123"), pack("H*","5c52615361ce4c5469f9d8c90113c7a543a4bf43490782d291cb32d8"), 'keccak224 (digest_data_raw/2)');
+is( digest_data_hex('Keccak224', "123"), "5c52615361ce4c5469f9d8c90113c7a543a4bf43490782d291cb32d8", 'keccak224 (digest_data_hex/2)');
+is( digest_data_b64('Keccak224', "123"), "XFJhU2HOTFRp+djJARPHpUOkv0NJB4LSkcsy2A==", 'keccak224 (digest_data_b64/2)');
+is( digest_data_b64u('Keccak224', "123"), "XFJhU2HOTFRp-djJARPHpUOkv0NJB4LSkcsy2A", 'keccak224 (digest_data_b64u/2)');
+is( Crypt::Digest::Keccak224->new->add("123")->hexdigest, "5c52615361ce4c5469f9d8c90113c7a543a4bf43490782d291cb32d8", 'keccak224 (OO/2)');
+
+is( keccak224("test\0test\0test\n"), pack("H*","7cbb8e9a6026e7c8324ab2f1cba55a1aff03b7b0424b8915b0439179"), 'keccak224 (raw/3)');
+is( keccak224_hex("test\0test\0test\n"), "7cbb8e9a6026e7c8324ab2f1cba55a1aff03b7b0424b8915b0439179", 'keccak224 (hex/3)');
+is( keccak224_b64("test\0test\0test\n"), "fLuOmmAm58gySrLxy6VaGv8Dt7BCS4kVsEOReQ==", 'keccak224 (base64/3)');
+is( digest_data('Keccak224', "test\0test\0test\n"), pack("H*","7cbb8e9a6026e7c8324ab2f1cba55a1aff03b7b0424b8915b0439179"), 'keccak224 (digest_data_raw/3)');
+is( digest_data_hex('Keccak224', "test\0test\0test\n"), "7cbb8e9a6026e7c8324ab2f1cba55a1aff03b7b0424b8915b0439179", 'keccak224 (digest_data_hex/3)');
+is( digest_data_b64('Keccak224', "test\0test\0test\n"), "fLuOmmAm58gySrLxy6VaGv8Dt7BCS4kVsEOReQ==", 'keccak224 (digest_data_b64/3)');
+is( digest_data_b64u('Keccak224', "test\0test\0test\n"), "fLuOmmAm58gySrLxy6VaGv8Dt7BCS4kVsEOReQ", 'keccak224 (digest_data_b64u/3)');
+is( Crypt::Digest::Keccak224->new->add("test\0test\0test\n")->hexdigest, "7cbb8e9a6026e7c8324ab2f1cba55a1aff03b7b0424b8915b0439179", 'keccak224 (OO/3)');
+
+
+is( keccak224_file('t/data/binary-test.file'), pack("H*","8f1651ffab903619314a1b3d7c89aefbc1f8f541289b1889320b1a8e"), 'keccak224 (raw/file/1)');
+is( keccak224_file_hex('t/data/binary-test.file'), "8f1651ffab903619314a1b3d7c89aefbc1f8f541289b1889320b1a8e", 'keccak224 (hex/file/1)');
+is( keccak224_file_b64('t/data/binary-test.file'), "jxZR/6uQNhkxShs9fImu+8H49UEomxiJMgsajg==", 'keccak224 (base64/file/1)');
+is( digest_file('Keccak224', 't/data/binary-test.file'), pack("H*","8f1651ffab903619314a1b3d7c89aefbc1f8f541289b1889320b1a8e"), 'keccak224 (digest_file_raw/file/1)');
+is( digest_file_hex('Keccak224', 't/data/binary-test.file'), "8f1651ffab903619314a1b3d7c89aefbc1f8f541289b1889320b1a8e", 'keccak224 (digest_file_hex/file/1)');
+is( digest_file_b64('Keccak224', 't/data/binary-test.file'), "jxZR/6uQNhkxShs9fImu+8H49UEomxiJMgsajg==", 'keccak224 (digest_file_b64/file/1)');
+is( digest_file_b64u('Keccak224', 't/data/binary-test.file'), "jxZR_6uQNhkxShs9fImu-8H49UEomxiJMgsajg", 'keccak224 (digest_file_b64u/file/1)');
+is( Crypt::Digest::Keccak224->new->addfile('t/data/binary-test.file')->hexdigest, "8f1651ffab903619314a1b3d7c89aefbc1f8f541289b1889320b1a8e", 'keccak224 (OO/file/1)');
+{
+ open(my $fh, '<', 't/data/binary-test.file');
+ binmode($fh);
+ is( Crypt::Digest::Keccak224->new->addfile($fh)->hexdigest, "8f1651ffab903619314a1b3d7c89aefbc1f8f541289b1889320b1a8e", 'keccak224 (OO/filehandle/1)');
+ close($fh);
+}
+
+is( keccak224_file('t/data/text-CR.file'), pack("H*","28ff8a17382e1fa11c37cd6e2543bf257f914aae3760ef77073987c8"), 'keccak224 (raw/file/2)');
+is( keccak224_file_hex('t/data/text-CR.file'), "28ff8a17382e1fa11c37cd6e2543bf257f914aae3760ef77073987c8", 'keccak224 (hex/file/2)');
+is( keccak224_file_b64('t/data/text-CR.file'), "KP+KFzguH6EcN81uJUO/JX+RSq43YO93BzmHyA==", 'keccak224 (base64/file/2)');
+is( digest_file('Keccak224', 't/data/text-CR.file'), pack("H*","28ff8a17382e1fa11c37cd6e2543bf257f914aae3760ef77073987c8"), 'keccak224 (digest_file_raw/file/2)');
+is( digest_file_hex('Keccak224', 't/data/text-CR.file'), "28ff8a17382e1fa11c37cd6e2543bf257f914aae3760ef77073987c8", 'keccak224 (digest_file_hex/file/2)');
+is( digest_file_b64('Keccak224', 't/data/text-CR.file'), "KP+KFzguH6EcN81uJUO/JX+RSq43YO93BzmHyA==", 'keccak224 (digest_file_b64/file/2)');
+is( digest_file_b64u('Keccak224', 't/data/text-CR.file'), "KP-KFzguH6EcN81uJUO_JX-RSq43YO93BzmHyA", 'keccak224 (digest_file_b64u/file/2)');
+is( Crypt::Digest::Keccak224->new->addfile('t/data/text-CR.file')->hexdigest, "28ff8a17382e1fa11c37cd6e2543bf257f914aae3760ef77073987c8", 'keccak224 (OO/file/2)');
+{
+ open(my $fh, '<', 't/data/text-CR.file');
+ binmode($fh);
+ is( Crypt::Digest::Keccak224->new->addfile($fh)->hexdigest, "28ff8a17382e1fa11c37cd6e2543bf257f914aae3760ef77073987c8", 'keccak224 (OO/filehandle/2)');
+ close($fh);
+}
+
+is( keccak224_file('t/data/text-CRLF.file'), pack("H*","26659008759423cde44c4984748af6b61d7d4ea5c7e81be58fb72faa"), 'keccak224 (raw/file/3)');
+is( keccak224_file_hex('t/data/text-CRLF.file'), "26659008759423cde44c4984748af6b61d7d4ea5c7e81be58fb72faa", 'keccak224 (hex/file/3)');
+is( keccak224_file_b64('t/data/text-CRLF.file'), "JmWQCHWUI83kTEmEdIr2th19TqXH6Bvlj7cvqg==", 'keccak224 (base64/file/3)');
+is( digest_file('Keccak224', 't/data/text-CRLF.file'), pack("H*","26659008759423cde44c4984748af6b61d7d4ea5c7e81be58fb72faa"), 'keccak224 (digest_file_raw/file/3)');
+is( digest_file_hex('Keccak224', 't/data/text-CRLF.file'), "26659008759423cde44c4984748af6b61d7d4ea5c7e81be58fb72faa", 'keccak224 (digest_file_hex/file/3)');
+is( digest_file_b64('Keccak224', 't/data/text-CRLF.file'), "JmWQCHWUI83kTEmEdIr2th19TqXH6Bvlj7cvqg==", 'keccak224 (digest_file_b64/file/3)');
+is( digest_file_b64u('Keccak224', 't/data/text-CRLF.file'), "JmWQCHWUI83kTEmEdIr2th19TqXH6Bvlj7cvqg", 'keccak224 (digest_file_b64u/file/3)');
+is( Crypt::Digest::Keccak224->new->addfile('t/data/text-CRLF.file')->hexdigest, "26659008759423cde44c4984748af6b61d7d4ea5c7e81be58fb72faa", 'keccak224 (OO/file/3)');
+{
+ open(my $fh, '<', 't/data/text-CRLF.file');
+ binmode($fh);
+ is( Crypt::Digest::Keccak224->new->addfile($fh)->hexdigest, "26659008759423cde44c4984748af6b61d7d4ea5c7e81be58fb72faa", 'keccak224 (OO/filehandle/3)');
+ close($fh);
+}
+
+is( keccak224_file('t/data/text-LF.file'), pack("H*","2021717d16f99f493960d0839a3cb2b01be8078c28b425d7f1c8662b"), 'keccak224 (raw/file/4)');
+is( keccak224_file_hex('t/data/text-LF.file'), "2021717d16f99f493960d0839a3cb2b01be8078c28b425d7f1c8662b", 'keccak224 (hex/file/4)');
+is( keccak224_file_b64('t/data/text-LF.file'), "ICFxfRb5n0k5YNCDmjyysBvoB4wotCXX8chmKw==", 'keccak224 (base64/file/4)');
+is( digest_file('Keccak224', 't/data/text-LF.file'), pack("H*","2021717d16f99f493960d0839a3cb2b01be8078c28b425d7f1c8662b"), 'keccak224 (digest_file_raw/file/4)');
+is( digest_file_hex('Keccak224', 't/data/text-LF.file'), "2021717d16f99f493960d0839a3cb2b01be8078c28b425d7f1c8662b", 'keccak224 (digest_file_hex/file/4)');
+is( digest_file_b64('Keccak224', 't/data/text-LF.file'), "ICFxfRb5n0k5YNCDmjyysBvoB4wotCXX8chmKw==", 'keccak224 (digest_file_b64/file/4)');
+is( digest_file_b64u('Keccak224', 't/data/text-LF.file'), "ICFxfRb5n0k5YNCDmjyysBvoB4wotCXX8chmKw", 'keccak224 (digest_file_b64u/file/4)');
+is( Crypt::Digest::Keccak224->new->addfile('t/data/text-LF.file')->hexdigest, "2021717d16f99f493960d0839a3cb2b01be8078c28b425d7f1c8662b", 'keccak224 (OO/file/4)');
+{
+ open(my $fh, '<', 't/data/text-LF.file');
+ binmode($fh);
+ is( Crypt::Digest::Keccak224->new->addfile($fh)->hexdigest, "2021717d16f99f493960d0839a3cb2b01be8078c28b425d7f1c8662b", 'keccak224 (OO/filehandle/4)');
+ close($fh);
+}
diff --git a/t/digest_keccak256.t b/t/digest_keccak256.t
new file mode 100644
index 00000000..25821470
--- /dev/null
+++ b/t/digest_keccak256.t
@@ -0,0 +1,116 @@
+### BEWARE - GENERATED FILE, DO NOT EDIT MANUALLY!
+
+use strict;
+use warnings;
+
+use Test::More tests => 8*3 + 9*4 + 10 + 6;
+
+use Crypt::Digest qw( digest_data digest_data_hex digest_data_b64 digest_data_b64u digest_file digest_file_hex digest_file_b64 digest_file_b64u );
+use Crypt::Digest::Keccak256 qw( keccak256 keccak256_hex keccak256_b64 keccak256_b64u keccak256_file keccak256_file_hex keccak256_file_b64 keccak256_file_b64u );
+
+is( Crypt::Digest::hashsize('Keccak256'), 32, 'hashsize/1');
+is( Crypt::Digest->hashsize('Keccak256'), 32, 'hashsize/2');
+is( Crypt::Digest::Keccak256::hashsize, 32, 'hashsize/3');
+is( Crypt::Digest::Keccak256->hashsize, 32, 'hashsize/4');
+is( Crypt::Digest->new('Keccak256')->hashsize, 32, 'hashsize/5');
+is( Crypt::Digest::Keccak256->new->hashsize, 32, 'hashsize/6');
+
+is( keccak256("A","A","A"), pack("H*","2070504003a07b4713d783ae7a6642ab3b959b7c575c6e4fa4f33eb743db631a"), 'keccak256 (raw/tripple_A)');
+is( keccak256_hex("A","A","A"), "2070504003a07b4713d783ae7a6642ab3b959b7c575c6e4fa4f33eb743db631a", 'keccak256 (hex/tripple_A)');
+is( keccak256_b64("A","A","A"), "IHBQQAOge0cT14OuemZCqzuVm3xXXG5PpPM+t0PbYxo=", 'keccak256 (base64/tripple_A)');
+is( keccak256_b64u("A","A","A"), "IHBQQAOge0cT14OuemZCqzuVm3xXXG5PpPM-t0PbYxo", 'keccak256 (base64url/tripple_A)');
+is( digest_data('Keccak256', "A","A","A"), pack("H*","2070504003a07b4713d783ae7a6642ab3b959b7c575c6e4fa4f33eb743db631a"), 'keccak256 (digest_data_raw/tripple_A)');
+is( digest_data_hex('Keccak256', "A","A","A"), "2070504003a07b4713d783ae7a6642ab3b959b7c575c6e4fa4f33eb743db631a", 'keccak256 (digest_data_hex/tripple_A)');
+is( digest_data_b64('Keccak256', "A","A","A"), "IHBQQAOge0cT14OuemZCqzuVm3xXXG5PpPM+t0PbYxo=", 'keccak256 (digest_data_b64/tripple_A)');
+is( digest_data_b64u('Keccak256', "A","A","A"), "IHBQQAOge0cT14OuemZCqzuVm3xXXG5PpPM-t0PbYxo", 'keccak256 (digest_data_b64u/tripple_A)');
+is( Crypt::Digest::Keccak256->new->add("A","A","A")->hexdigest, "2070504003a07b4713d783ae7a6642ab3b959b7c575c6e4fa4f33eb743db631a", 'keccak256 (OO/tripple_A)');
+is( Crypt::Digest::Keccak256->new->add("A")->add("A")->add("A")->hexdigest, "2070504003a07b4713d783ae7a6642ab3b959b7c575c6e4fa4f33eb743db631a", 'keccak256 (OO3/tripple_A)');
+
+
+is( keccak256(""), pack("H*","c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"), 'keccak256 (raw/1)');
+is( keccak256_hex(""), "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", 'keccak256 (hex/1)');
+is( keccak256_b64(""), "xdJGAYb3IzySfn2y3McDwOUAtlPKgic7e/rYBF2FpHA=", 'keccak256 (base64/1)');
+is( digest_data('Keccak256', ""), pack("H*","c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"), 'keccak256 (digest_data_raw/1)');
+is( digest_data_hex('Keccak256', ""), "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", 'keccak256 (digest_data_hex/1)');
+is( digest_data_b64('Keccak256', ""), "xdJGAYb3IzySfn2y3McDwOUAtlPKgic7e/rYBF2FpHA=", 'keccak256 (digest_data_b64/1)');
+is( digest_data_b64u('Keccak256', ""), "xdJGAYb3IzySfn2y3McDwOUAtlPKgic7e_rYBF2FpHA", 'keccak256 (digest_data_b64u/1)');
+is( Crypt::Digest::Keccak256->new->add("")->hexdigest, "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", 'keccak256 (OO/1)');
+
+is( keccak256("123"), pack("H*","64e604787cbf194841e7b68d7cd28786f6c9a0a3ab9f8b0a0e87cb4387ab0107"), 'keccak256 (raw/2)');
+is( keccak256_hex("123"), "64e604787cbf194841e7b68d7cd28786f6c9a0a3ab9f8b0a0e87cb4387ab0107", 'keccak256 (hex/2)');
+is( keccak256_b64("123"), "ZOYEeHy/GUhB57aNfNKHhvbJoKOrn4sKDofLQ4erAQc=", 'keccak256 (base64/2)');
+is( digest_data('Keccak256', "123"), pack("H*","64e604787cbf194841e7b68d7cd28786f6c9a0a3ab9f8b0a0e87cb4387ab0107"), 'keccak256 (digest_data_raw/2)');
+is( digest_data_hex('Keccak256', "123"), "64e604787cbf194841e7b68d7cd28786f6c9a0a3ab9f8b0a0e87cb4387ab0107", 'keccak256 (digest_data_hex/2)');
+is( digest_data_b64('Keccak256', "123"), "ZOYEeHy/GUhB57aNfNKHhvbJoKOrn4sKDofLQ4erAQc=", 'keccak256 (digest_data_b64/2)');
+is( digest_data_b64u('Keccak256', "123"), "ZOYEeHy_GUhB57aNfNKHhvbJoKOrn4sKDofLQ4erAQc", 'keccak256 (digest_data_b64u/2)');
+is( Crypt::Digest::Keccak256->new->add("123")->hexdigest, "64e604787cbf194841e7b68d7cd28786f6c9a0a3ab9f8b0a0e87cb4387ab0107", 'keccak256 (OO/2)');
+
+is( keccak256("test\0test\0test\n"), pack("H*","fbc121310d505fb7172a28e0e9e8c7d2976c9f63a739fe60bc298467bc72bb86"), 'keccak256 (raw/3)');
+is( keccak256_hex("test\0test\0test\n"), "fbc121310d505fb7172a28e0e9e8c7d2976c9f63a739fe60bc298467bc72bb86", 'keccak256 (hex/3)');
+is( keccak256_b64("test\0test\0test\n"), "+8EhMQ1QX7cXKijg6ejH0pdsn2OnOf5gvCmEZ7xyu4Y=", 'keccak256 (base64/3)');
+is( digest_data('Keccak256', "test\0test\0test\n"), pack("H*","fbc121310d505fb7172a28e0e9e8c7d2976c9f63a739fe60bc298467bc72bb86"), 'keccak256 (digest_data_raw/3)');
+is( digest_data_hex('Keccak256', "test\0test\0test\n"), "fbc121310d505fb7172a28e0e9e8c7d2976c9f63a739fe60bc298467bc72bb86", 'keccak256 (digest_data_hex/3)');
+is( digest_data_b64('Keccak256', "test\0test\0test\n"), "+8EhMQ1QX7cXKijg6ejH0pdsn2OnOf5gvCmEZ7xyu4Y=", 'keccak256 (digest_data_b64/3)');
+is( digest_data_b64u('Keccak256', "test\0test\0test\n"), "-8EhMQ1QX7cXKijg6ejH0pdsn2OnOf5gvCmEZ7xyu4Y", 'keccak256 (digest_data_b64u/3)');
+is( Crypt::Digest::Keccak256->new->add("test\0test\0test\n")->hexdigest, "fbc121310d505fb7172a28e0e9e8c7d2976c9f63a739fe60bc298467bc72bb86", 'keccak256 (OO/3)');
+
+
+is( keccak256_file('t/data/binary-test.file'), pack("H*","7046f5fad76cf793a1f44c159b656277ada3f428057ac8160d04fdcdc5b0fcb8"), 'keccak256 (raw/file/1)');
+is( keccak256_file_hex('t/data/binary-test.file'), "7046f5fad76cf793a1f44c159b656277ada3f428057ac8160d04fdcdc5b0fcb8", 'keccak256 (hex/file/1)');
+is( keccak256_file_b64('t/data/binary-test.file'), "cEb1+tds95Oh9EwVm2Vid62j9CgFesgWDQT9zcWw/Lg=", 'keccak256 (base64/file/1)');
+is( digest_file('Keccak256', 't/data/binary-test.file'), pack("H*","7046f5fad76cf793a1f44c159b656277ada3f428057ac8160d04fdcdc5b0fcb8"), 'keccak256 (digest_file_raw/file/1)');
+is( digest_file_hex('Keccak256', 't/data/binary-test.file'), "7046f5fad76cf793a1f44c159b656277ada3f428057ac8160d04fdcdc5b0fcb8", 'keccak256 (digest_file_hex/file/1)');
+is( digest_file_b64('Keccak256', 't/data/binary-test.file'), "cEb1+tds95Oh9EwVm2Vid62j9CgFesgWDQT9zcWw/Lg=", 'keccak256 (digest_file_b64/file/1)');
+is( digest_file_b64u('Keccak256', 't/data/binary-test.file'), "cEb1-tds95Oh9EwVm2Vid62j9CgFesgWDQT9zcWw_Lg", 'keccak256 (digest_file_b64u/file/1)');
+is( Crypt::Digest::Keccak256->new->addfile('t/data/binary-test.file')->hexdigest, "7046f5fad76cf793a1f44c159b656277ada3f428057ac8160d04fdcdc5b0fcb8", 'keccak256 (OO/file/1)');
+{
+ open(my $fh, '<', 't/data/binary-test.file');
+ binmode($fh);
+ is( Crypt::Digest::Keccak256->new->addfile($fh)->hexdigest, "7046f5fad76cf793a1f44c159b656277ada3f428057ac8160d04fdcdc5b0fcb8", 'keccak256 (OO/filehandle/1)');
+ close($fh);
+}
+
+is( keccak256_file('t/data/text-CR.file'), pack("H*","288d47897222a6fbd6d8593cd06796e6c3eb5637a6eaf8fc033dc9243ce01c18"), 'keccak256 (raw/file/2)');
+is( keccak256_file_hex('t/data/text-CR.file'), "288d47897222a6fbd6d8593cd06796e6c3eb5637a6eaf8fc033dc9243ce01c18", 'keccak256 (hex/file/2)');
+is( keccak256_file_b64('t/data/text-CR.file'), "KI1HiXIipvvW2Fk80GeW5sPrVjem6vj8Az3JJDzgHBg=", 'keccak256 (base64/file/2)');
+is( digest_file('Keccak256', 't/data/text-CR.file'), pack("H*","288d47897222a6fbd6d8593cd06796e6c3eb5637a6eaf8fc033dc9243ce01c18"), 'keccak256 (digest_file_raw/file/2)');
+is( digest_file_hex('Keccak256', 't/data/text-CR.file'), "288d47897222a6fbd6d8593cd06796e6c3eb5637a6eaf8fc033dc9243ce01c18", 'keccak256 (digest_file_hex/file/2)');
+is( digest_file_b64('Keccak256', 't/data/text-CR.file'), "KI1HiXIipvvW2Fk80GeW5sPrVjem6vj8Az3JJDzgHBg=", 'keccak256 (digest_file_b64/file/2)');
+is( digest_file_b64u('Keccak256', 't/data/text-CR.file'), "KI1HiXIipvvW2Fk80GeW5sPrVjem6vj8Az3JJDzgHBg", 'keccak256 (digest_file_b64u/file/2)');
+is( Crypt::Digest::Keccak256->new->addfile('t/data/text-CR.file')->hexdigest, "288d47897222a6fbd6d8593cd06796e6c3eb5637a6eaf8fc033dc9243ce01c18", 'keccak256 (OO/file/2)');
+{
+ open(my $fh, '<', 't/data/text-CR.file');
+ binmode($fh);
+ is( Crypt::Digest::Keccak256->new->addfile($fh)->hexdigest, "288d47897222a6fbd6d8593cd06796e6c3eb5637a6eaf8fc033dc9243ce01c18", 'keccak256 (OO/filehandle/2)');
+ close($fh);
+}
+
+is( keccak256_file('t/data/text-CRLF.file'), pack("H*","a44703b85d5ee7f35b3c0c21c646d695978d0ec5ea36a1a05a77427c5f964ee1"), 'keccak256 (raw/file/3)');
+is( keccak256_file_hex('t/data/text-CRLF.file'), "a44703b85d5ee7f35b3c0c21c646d695978d0ec5ea36a1a05a77427c5f964ee1", 'keccak256 (hex/file/3)');
+is( keccak256_file_b64('t/data/text-CRLF.file'), "pEcDuF1e5/NbPAwhxkbWlZeNDsXqNqGgWndCfF+WTuE=", 'keccak256 (base64/file/3)');
+is( digest_file('Keccak256', 't/data/text-CRLF.file'), pack("H*","a44703b85d5ee7f35b3c0c21c646d695978d0ec5ea36a1a05a77427c5f964ee1"), 'keccak256 (digest_file_raw/file/3)');
+is( digest_file_hex('Keccak256', 't/data/text-CRLF.file'), "a44703b85d5ee7f35b3c0c21c646d695978d0ec5ea36a1a05a77427c5f964ee1", 'keccak256 (digest_file_hex/file/3)');
+is( digest_file_b64('Keccak256', 't/data/text-CRLF.file'), "pEcDuF1e5/NbPAwhxkbWlZeNDsXqNqGgWndCfF+WTuE=", 'keccak256 (digest_file_b64/file/3)');
+is( digest_file_b64u('Keccak256', 't/data/text-CRLF.file'), "pEcDuF1e5_NbPAwhxkbWlZeNDsXqNqGgWndCfF-WTuE", 'keccak256 (digest_file_b64u/file/3)');
+is( Crypt::Digest::Keccak256->new->addfile('t/data/text-CRLF.file')->hexdigest, "a44703b85d5ee7f35b3c0c21c646d695978d0ec5ea36a1a05a77427c5f964ee1", 'keccak256 (OO/file/3)');
+{
+ open(my $fh, '<', 't/data/text-CRLF.file');
+ binmode($fh);
+ is( Crypt::Digest::Keccak256->new->addfile($fh)->hexdigest, "a44703b85d5ee7f35b3c0c21c646d695978d0ec5ea36a1a05a77427c5f964ee1", 'keccak256 (OO/filehandle/3)');
+ close($fh);
+}
+
+is( keccak256_file('t/data/text-LF.file'), pack("H*","188476c71de2afcb7eda9dbc560b5eb5e4e681a558568a41068eb6d738efa4f4"), 'keccak256 (raw/file/4)');
+is( keccak256_file_hex('t/data/text-LF.file'), "188476c71de2afcb7eda9dbc560b5eb5e4e681a558568a41068eb6d738efa4f4", 'keccak256 (hex/file/4)');
+is( keccak256_file_b64('t/data/text-LF.file'), "GIR2xx3ir8t+2p28VgteteTmgaVYVopBBo621zjvpPQ=", 'keccak256 (base64/file/4)');
+is( digest_file('Keccak256', 't/data/text-LF.file'), pack("H*","188476c71de2afcb7eda9dbc560b5eb5e4e681a558568a41068eb6d738efa4f4"), 'keccak256 (digest_file_raw/file/4)');
+is( digest_file_hex('Keccak256', 't/data/text-LF.file'), "188476c71de2afcb7eda9dbc560b5eb5e4e681a558568a41068eb6d738efa4f4", 'keccak256 (digest_file_hex/file/4)');
+is( digest_file_b64('Keccak256', 't/data/text-LF.file'), "GIR2xx3ir8t+2p28VgteteTmgaVYVopBBo621zjvpPQ=", 'keccak256 (digest_file_b64/file/4)');
+is( digest_file_b64u('Keccak256', 't/data/text-LF.file'), "GIR2xx3ir8t-2p28VgteteTmgaVYVopBBo621zjvpPQ", 'keccak256 (digest_file_b64u/file/4)');
+is( Crypt::Digest::Keccak256->new->addfile('t/data/text-LF.file')->hexdigest, "188476c71de2afcb7eda9dbc560b5eb5e4e681a558568a41068eb6d738efa4f4", 'keccak256 (OO/file/4)');
+{
+ open(my $fh, '<', 't/data/text-LF.file');
+ binmode($fh);
+ is( Crypt::Digest::Keccak256->new->addfile($fh)->hexdigest, "188476c71de2afcb7eda9dbc560b5eb5e4e681a558568a41068eb6d738efa4f4", 'keccak256 (OO/filehandle/4)');
+ close($fh);
+}
diff --git a/t/digest_keccak384.t b/t/digest_keccak384.t
new file mode 100644
index 00000000..935816dd
--- /dev/null
+++ b/t/digest_keccak384.t
@@ -0,0 +1,116 @@
+### BEWARE - GENERATED FILE, DO NOT EDIT MANUALLY!
+
+use strict;
+use warnings;
+
+use Test::More tests => 8*3 + 9*4 + 10 + 6;
+
+use Crypt::Digest qw( digest_data digest_data_hex digest_data_b64 digest_data_b64u digest_file digest_file_hex digest_file_b64 digest_file_b64u );
+use Crypt::Digest::Keccak384 qw( keccak384 keccak384_hex keccak384_b64 keccak384_b64u keccak384_file keccak384_file_hex keccak384_file_b64 keccak384_file_b64u );
+
+is( Crypt::Digest::hashsize('Keccak384'), 48, 'hashsize/1');
+is( Crypt::Digest->hashsize('Keccak384'), 48, 'hashsize/2');
+is( Crypt::Digest::Keccak384::hashsize, 48, 'hashsize/3');
+is( Crypt::Digest::Keccak384->hashsize, 48, 'hashsize/4');
+is( Crypt::Digest->new('Keccak384')->hashsize, 48, 'hashsize/5');
+is( Crypt::Digest::Keccak384->new->hashsize, 48, 'hashsize/6');
+
+is( keccak384("A","A","A"), pack("H*","173b545e0fd81784f8c024ca803641936082eef9a5ace73faf73ad68ecde6029cc345a5c549384e0d7627dcbf58d0297"), 'keccak384 (raw/tripple_A)');
+is( keccak384_hex("A","A","A"), "173b545e0fd81784f8c024ca803641936082eef9a5ace73faf73ad68ecde6029cc345a5c549384e0d7627dcbf58d0297", 'keccak384 (hex/tripple_A)');
+is( keccak384_b64("A","A","A"), "FztUXg/YF4T4wCTKgDZBk2CC7vmlrOc/r3OtaOzeYCnMNFpcVJOE4Ndifcv1jQKX", 'keccak384 (base64/tripple_A)');
+is( keccak384_b64u("A","A","A"), "FztUXg_YF4T4wCTKgDZBk2CC7vmlrOc_r3OtaOzeYCnMNFpcVJOE4Ndifcv1jQKX", 'keccak384 (base64url/tripple_A)');
+is( digest_data('Keccak384', "A","A","A"), pack("H*","173b545e0fd81784f8c024ca803641936082eef9a5ace73faf73ad68ecde6029cc345a5c549384e0d7627dcbf58d0297"), 'keccak384 (digest_data_raw/tripple_A)');
+is( digest_data_hex('Keccak384', "A","A","A"), "173b545e0fd81784f8c024ca803641936082eef9a5ace73faf73ad68ecde6029cc345a5c549384e0d7627dcbf58d0297", 'keccak384 (digest_data_hex/tripple_A)');
+is( digest_data_b64('Keccak384', "A","A","A"), "FztUXg/YF4T4wCTKgDZBk2CC7vmlrOc/r3OtaOzeYCnMNFpcVJOE4Ndifcv1jQKX", 'keccak384 (digest_data_b64/tripple_A)');
+is( digest_data_b64u('Keccak384', "A","A","A"), "FztUXg_YF4T4wCTKgDZBk2CC7vmlrOc_r3OtaOzeYCnMNFpcVJOE4Ndifcv1jQKX", 'keccak384 (digest_data_b64u/tripple_A)');
+is( Crypt::Digest::Keccak384->new->add("A","A","A")->hexdigest, "173b545e0fd81784f8c024ca803641936082eef9a5ace73faf73ad68ecde6029cc345a5c549384e0d7627dcbf58d0297", 'keccak384 (OO/tripple_A)');
+is( Crypt::Digest::Keccak384->new->add("A")->add("A")->add("A")->hexdigest, "173b545e0fd81784f8c024ca803641936082eef9a5ace73faf73ad68ecde6029cc345a5c549384e0d7627dcbf58d0297", 'keccak384 (OO3/tripple_A)');
+
+
+is( keccak384(""), pack("H*","2c23146a63a29acf99e73b88f8c24eaa7dc60aa771780ccc006afbfa8fe2479b2dd2b21362337441ac12b515911957ff"), 'keccak384 (raw/1)');
+is( keccak384_hex(""), "2c23146a63a29acf99e73b88f8c24eaa7dc60aa771780ccc006afbfa8fe2479b2dd2b21362337441ac12b515911957ff", 'keccak384 (hex/1)');
+is( keccak384_b64(""), "LCMUamOims+Z5zuI+MJOqn3GCqdxeAzMAGr7+o/iR5st0rITYjN0QawStRWRGVf/", 'keccak384 (base64/1)');
+is( digest_data('Keccak384', ""), pack("H*","2c23146a63a29acf99e73b88f8c24eaa7dc60aa771780ccc006afbfa8fe2479b2dd2b21362337441ac12b515911957ff"), 'keccak384 (digest_data_raw/1)');
+is( digest_data_hex('Keccak384', ""), "2c23146a63a29acf99e73b88f8c24eaa7dc60aa771780ccc006afbfa8fe2479b2dd2b21362337441ac12b515911957ff", 'keccak384 (digest_data_hex/1)');
+is( digest_data_b64('Keccak384', ""), "LCMUamOims+Z5zuI+MJOqn3GCqdxeAzMAGr7+o/iR5st0rITYjN0QawStRWRGVf/", 'keccak384 (digest_data_b64/1)');
+is( digest_data_b64u('Keccak384', ""), "LCMUamOims-Z5zuI-MJOqn3GCqdxeAzMAGr7-o_iR5st0rITYjN0QawStRWRGVf_", 'keccak384 (digest_data_b64u/1)');
+is( Crypt::Digest::Keccak384->new->add("")->hexdigest, "2c23146a63a29acf99e73b88f8c24eaa7dc60aa771780ccc006afbfa8fe2479b2dd2b21362337441ac12b515911957ff", 'keccak384 (OO/1)');
+
+is( keccak384("123"), pack("H*","7dd34ccaae92bfc7eb541056d200db23b6bbeefe95be0d2bb43625113361906f0afc701dbef1cfb615bf98b1535a84c1"), 'keccak384 (raw/2)');
+is( keccak384_hex("123"), "7dd34ccaae92bfc7eb541056d200db23b6bbeefe95be0d2bb43625113361906f0afc701dbef1cfb615bf98b1535a84c1", 'keccak384 (hex/2)');
+is( keccak384_b64("123"), "fdNMyq6Sv8frVBBW0gDbI7a77v6Vvg0rtDYlETNhkG8K/HAdvvHPthW/mLFTWoTB", 'keccak384 (base64/2)');
+is( digest_data('Keccak384', "123"), pack("H*","7dd34ccaae92bfc7eb541056d200db23b6bbeefe95be0d2bb43625113361906f0afc701dbef1cfb615bf98b1535a84c1"), 'keccak384 (digest_data_raw/2)');
+is( digest_data_hex('Keccak384', "123"), "7dd34ccaae92bfc7eb541056d200db23b6bbeefe95be0d2bb43625113361906f0afc701dbef1cfb615bf98b1535a84c1", 'keccak384 (digest_data_hex/2)');
+is( digest_data_b64('Keccak384', "123"), "fdNMyq6Sv8frVBBW0gDbI7a77v6Vvg0rtDYlETNhkG8K/HAdvvHPthW/mLFTWoTB", 'keccak384 (digest_data_b64/2)');
+is( digest_data_b64u('Keccak384', "123"), "fdNMyq6Sv8frVBBW0gDbI7a77v6Vvg0rtDYlETNhkG8K_HAdvvHPthW_mLFTWoTB", 'keccak384 (digest_data_b64u/2)');
+is( Crypt::Digest::Keccak384->new->add("123")->hexdigest, "7dd34ccaae92bfc7eb541056d200db23b6bbeefe95be0d2bb43625113361906f0afc701dbef1cfb615bf98b1535a84c1", 'keccak384 (OO/2)');
+
+is( keccak384("test\0test\0test\n"), pack("H*","d05c31062f5401c5d370cf84949937c52764626a61d2bbd5bf5c50f6f742ebcf9269691a3c70ef83dc49f4e186e5d908"), 'keccak384 (raw/3)');
+is( keccak384_hex("test\0test\0test\n"), "d05c31062f5401c5d370cf84949937c52764626a61d2bbd5bf5c50f6f742ebcf9269691a3c70ef83dc49f4e186e5d908", 'keccak384 (hex/3)');
+is( keccak384_b64("test\0test\0test\n"), "0FwxBi9UAcXTcM+ElJk3xSdkYmph0rvVv1xQ9vdC68+SaWkaPHDvg9xJ9OGG5dkI", 'keccak384 (base64/3)');
+is( digest_data('Keccak384', "test\0test\0test\n"), pack("H*","d05c31062f5401c5d370cf84949937c52764626a61d2bbd5bf5c50f6f742ebcf9269691a3c70ef83dc49f4e186e5d908"), 'keccak384 (digest_data_raw/3)');
+is( digest_data_hex('Keccak384', "test\0test\0test\n"), "d05c31062f5401c5d370cf84949937c52764626a61d2bbd5bf5c50f6f742ebcf9269691a3c70ef83dc49f4e186e5d908", 'keccak384 (digest_data_hex/3)');
+is( digest_data_b64('Keccak384', "test\0test\0test\n"), "0FwxBi9UAcXTcM+ElJk3xSdkYmph0rvVv1xQ9vdC68+SaWkaPHDvg9xJ9OGG5dkI", 'keccak384 (digest_data_b64/3)');
+is( digest_data_b64u('Keccak384', "test\0test\0test\n"), "0FwxBi9UAcXTcM-ElJk3xSdkYmph0rvVv1xQ9vdC68-SaWkaPHDvg9xJ9OGG5dkI", 'keccak384 (digest_data_b64u/3)');
+is( Crypt::Digest::Keccak384->new->add("test\0test\0test\n")->hexdigest, "d05c31062f5401c5d370cf84949937c52764626a61d2bbd5bf5c50f6f742ebcf9269691a3c70ef83dc49f4e186e5d908", 'keccak384 (OO/3)');
+
+
+is( keccak384_file('t/data/binary-test.file'), pack("H*","16a5a7d82de1eec1cbbb51c403dd0fc02560ddf488c1b8c69b9b4cf1585e751424dfcc06cf0baf2ff73d931c6f7240bc"), 'keccak384 (raw/file/1)');
+is( keccak384_file_hex('t/data/binary-test.file'), "16a5a7d82de1eec1cbbb51c403dd0fc02560ddf488c1b8c69b9b4cf1585e751424dfcc06cf0baf2ff73d931c6f7240bc", 'keccak384 (hex/file/1)');
+is( keccak384_file_b64('t/data/binary-test.file'), "FqWn2C3h7sHLu1HEA90PwCVg3fSIwbjGm5tM8VhedRQk38wGzwuvL/c9kxxvckC8", 'keccak384 (base64/file/1)');
+is( digest_file('Keccak384', 't/data/binary-test.file'), pack("H*","16a5a7d82de1eec1cbbb51c403dd0fc02560ddf488c1b8c69b9b4cf1585e751424dfcc06cf0baf2ff73d931c6f7240bc"), 'keccak384 (digest_file_raw/file/1)');
+is( digest_file_hex('Keccak384', 't/data/binary-test.file'), "16a5a7d82de1eec1cbbb51c403dd0fc02560ddf488c1b8c69b9b4cf1585e751424dfcc06cf0baf2ff73d931c6f7240bc", 'keccak384 (digest_file_hex/file/1)');
+is( digest_file_b64('Keccak384', 't/data/binary-test.file'), "FqWn2C3h7sHLu1HEA90PwCVg3fSIwbjGm5tM8VhedRQk38wGzwuvL/c9kxxvckC8", 'keccak384 (digest_file_b64/file/1)');
+is( digest_file_b64u('Keccak384', 't/data/binary-test.file'), "FqWn2C3h7sHLu1HEA90PwCVg3fSIwbjGm5tM8VhedRQk38wGzwuvL_c9kxxvckC8", 'keccak384 (digest_file_b64u/file/1)');
+is( Crypt::Digest::Keccak384->new->addfile('t/data/binary-test.file')->hexdigest, "16a5a7d82de1eec1cbbb51c403dd0fc02560ddf488c1b8c69b9b4cf1585e751424dfcc06cf0baf2ff73d931c6f7240bc", 'keccak384 (OO/file/1)');
+{
+ open(my $fh, '<', 't/data/binary-test.file');
+ binmode($fh);
+ is( Crypt::Digest::Keccak384->new->addfile($fh)->hexdigest, "16a5a7d82de1eec1cbbb51c403dd0fc02560ddf488c1b8c69b9b4cf1585e751424dfcc06cf0baf2ff73d931c6f7240bc", 'keccak384 (OO/filehandle/1)');
+ close($fh);
+}
+
+is( keccak384_file('t/data/text-CR.file'), pack("H*","d42a0bfb2a95bbfeba375b146ebe37ef9972d25809b93a18fd1754fb86ad9139ac2ca71e5cd1713024ecda06263a39cc"), 'keccak384 (raw/file/2)');
+is( keccak384_file_hex('t/data/text-CR.file'), "d42a0bfb2a95bbfeba375b146ebe37ef9972d25809b93a18fd1754fb86ad9139ac2ca71e5cd1713024ecda06263a39cc", 'keccak384 (hex/file/2)');
+is( keccak384_file_b64('t/data/text-CR.file'), "1CoL+yqVu/66N1sUbr4375ly0lgJuToY/RdU+4atkTmsLKceXNFxMCTs2gYmOjnM", 'keccak384 (base64/file/2)');
+is( digest_file('Keccak384', 't/data/text-CR.file'), pack("H*","d42a0bfb2a95bbfeba375b146ebe37ef9972d25809b93a18fd1754fb86ad9139ac2ca71e5cd1713024ecda06263a39cc"), 'keccak384 (digest_file_raw/file/2)');
+is( digest_file_hex('Keccak384', 't/data/text-CR.file'), "d42a0bfb2a95bbfeba375b146ebe37ef9972d25809b93a18fd1754fb86ad9139ac2ca71e5cd1713024ecda06263a39cc", 'keccak384 (digest_file_hex/file/2)');
+is( digest_file_b64('Keccak384', 't/data/text-CR.file'), "1CoL+yqVu/66N1sUbr4375ly0lgJuToY/RdU+4atkTmsLKceXNFxMCTs2gYmOjnM", 'keccak384 (digest_file_b64/file/2)');
+is( digest_file_b64u('Keccak384', 't/data/text-CR.file'), "1CoL-yqVu_66N1sUbr4375ly0lgJuToY_RdU-4atkTmsLKceXNFxMCTs2gYmOjnM", 'keccak384 (digest_file_b64u/file/2)');
+is( Crypt::Digest::Keccak384->new->addfile('t/data/text-CR.file')->hexdigest, "d42a0bfb2a95bbfeba375b146ebe37ef9972d25809b93a18fd1754fb86ad9139ac2ca71e5cd1713024ecda06263a39cc", 'keccak384 (OO/file/2)');
+{
+ open(my $fh, '<', 't/data/text-CR.file');
+ binmode($fh);
+ is( Crypt::Digest::Keccak384->new->addfile($fh)->hexdigest, "d42a0bfb2a95bbfeba375b146ebe37ef9972d25809b93a18fd1754fb86ad9139ac2ca71e5cd1713024ecda06263a39cc", 'keccak384 (OO/filehandle/2)');
+ close($fh);
+}
+
+is( keccak384_file('t/data/text-CRLF.file'), pack("H*","06288b3506e5080aebbcdfaaba5985ac89e3e4227fd32b8a532640064c98bfea991a5e88cc00b307fd0dd2d1c87a3982"), 'keccak384 (raw/file/3)');
+is( keccak384_file_hex('t/data/text-CRLF.file'), "06288b3506e5080aebbcdfaaba5985ac89e3e4227fd32b8a532640064c98bfea991a5e88cc00b307fd0dd2d1c87a3982", 'keccak384 (hex/file/3)');
+is( keccak384_file_b64('t/data/text-CRLF.file'), "BiiLNQblCArrvN+qulmFrInj5CJ/0yuKUyZABkyYv+qZGl6IzACzB/0N0tHIejmC", 'keccak384 (base64/file/3)');
+is( digest_file('Keccak384', 't/data/text-CRLF.file'), pack("H*","06288b3506e5080aebbcdfaaba5985ac89e3e4227fd32b8a532640064c98bfea991a5e88cc00b307fd0dd2d1c87a3982"), 'keccak384 (digest_file_raw/file/3)');
+is( digest_file_hex('Keccak384', 't/data/text-CRLF.file'), "06288b3506e5080aebbcdfaaba5985ac89e3e4227fd32b8a532640064c98bfea991a5e88cc00b307fd0dd2d1c87a3982", 'keccak384 (digest_file_hex/file/3)');
+is( digest_file_b64('Keccak384', 't/data/text-CRLF.file'), "BiiLNQblCArrvN+qulmFrInj5CJ/0yuKUyZABkyYv+qZGl6IzACzB/0N0tHIejmC", 'keccak384 (digest_file_b64/file/3)');
+is( digest_file_b64u('Keccak384', 't/data/text-CRLF.file'), "BiiLNQblCArrvN-qulmFrInj5CJ_0yuKUyZABkyYv-qZGl6IzACzB_0N0tHIejmC", 'keccak384 (digest_file_b64u/file/3)');
+is( Crypt::Digest::Keccak384->new->addfile('t/data/text-CRLF.file')->hexdigest, "06288b3506e5080aebbcdfaaba5985ac89e3e4227fd32b8a532640064c98bfea991a5e88cc00b307fd0dd2d1c87a3982", 'keccak384 (OO/file/3)');
+{
+ open(my $fh, '<', 't/data/text-CRLF.file');
+ binmode($fh);
+ is( Crypt::Digest::Keccak384->new->addfile($fh)->hexdigest, "06288b3506e5080aebbcdfaaba5985ac89e3e4227fd32b8a532640064c98bfea991a5e88cc00b307fd0dd2d1c87a3982", 'keccak384 (OO/filehandle/3)');
+ close($fh);
+}
+
+is( keccak384_file('t/data/text-LF.file'), pack("H*","14b54d1188154f7017ff7b33e21e42ef93c91d79ea6b44a223002adc6d89b875d3bcb25c189aea827560540afbe5cf71"), 'keccak384 (raw/file/4)');
+is( keccak384_file_hex('t/data/text-LF.file'), "14b54d1188154f7017ff7b33e21e42ef93c91d79ea6b44a223002adc6d89b875d3bcb25c189aea827560540afbe5cf71", 'keccak384 (hex/file/4)');
+is( keccak384_file_b64('t/data/text-LF.file'), "FLVNEYgVT3AX/3sz4h5C75PJHXnqa0SiIwAq3G2JuHXTvLJcGJrqgnVgVAr75c9x", 'keccak384 (base64/file/4)');
+is( digest_file('Keccak384', 't/data/text-LF.file'), pack("H*","14b54d1188154f7017ff7b33e21e42ef93c91d79ea6b44a223002adc6d89b875d3bcb25c189aea827560540afbe5cf71"), 'keccak384 (digest_file_raw/file/4)');
+is( digest_file_hex('Keccak384', 't/data/text-LF.file'), "14b54d1188154f7017ff7b33e21e42ef93c91d79ea6b44a223002adc6d89b875d3bcb25c189aea827560540afbe5cf71", 'keccak384 (digest_file_hex/file/4)');
+is( digest_file_b64('Keccak384', 't/data/text-LF.file'), "FLVNEYgVT3AX/3sz4h5C75PJHXnqa0SiIwAq3G2JuHXTvLJcGJrqgnVgVAr75c9x", 'keccak384 (digest_file_b64/file/4)');
+is( digest_file_b64u('Keccak384', 't/data/text-LF.file'), "FLVNEYgVT3AX_3sz4h5C75PJHXnqa0SiIwAq3G2JuHXTvLJcGJrqgnVgVAr75c9x", 'keccak384 (digest_file_b64u/file/4)');
+is( Crypt::Digest::Keccak384->new->addfile('t/data/text-LF.file')->hexdigest, "14b54d1188154f7017ff7b33e21e42ef93c91d79ea6b44a223002adc6d89b875d3bcb25c189aea827560540afbe5cf71", 'keccak384 (OO/file/4)');
+{
+ open(my $fh, '<', 't/data/text-LF.file');
+ binmode($fh);
+ is( Crypt::Digest::Keccak384->new->addfile($fh)->hexdigest, "14b54d1188154f7017ff7b33e21e42ef93c91d79ea6b44a223002adc6d89b875d3bcb25c189aea827560540afbe5cf71", 'keccak384 (OO/filehandle/4)');
+ close($fh);
+}
diff --git a/t/digest_keccak512.t b/t/digest_keccak512.t
new file mode 100644
index 00000000..1c8618d9
--- /dev/null
+++ b/t/digest_keccak512.t
@@ -0,0 +1,116 @@
+### BEWARE - GENERATED FILE, DO NOT EDIT MANUALLY!
+
+use strict;
+use warnings;
+
+use Test::More tests => 8*3 + 9*4 + 10 + 6;
+
+use Crypt::Digest qw( digest_data digest_data_hex digest_data_b64 digest_data_b64u digest_file digest_file_hex digest_file_b64 digest_file_b64u );
+use Crypt::Digest::Keccak512 qw( keccak512 keccak512_hex keccak512_b64 keccak512_b64u keccak512_file keccak512_file_hex keccak512_file_b64 keccak512_file_b64u );
+
+is( Crypt::Digest::hashsize('Keccak512'), 64, 'hashsize/1');
+is( Crypt::Digest->hashsize('Keccak512'), 64, 'hashsize/2');
+is( Crypt::Digest::Keccak512::hashsize, 64, 'hashsize/3');
+is( Crypt::Digest::Keccak512->hashsize, 64, 'hashsize/4');
+is( Crypt::Digest->new('Keccak512')->hashsize, 64, 'hashsize/5');
+is( Crypt::Digest::Keccak512->new->hashsize, 64, 'hashsize/6');
+
+is( keccak512("A","A","A"), pack("H*","a0243a891584f48aeb59677458705d209c0defd977655cb8a6c78298ac9d5981571659e1d35024285d718dd1f603876ad785f59ea814b91ee61a4433856c6391"), 'keccak512 (raw/tripple_A)');
+is( keccak512_hex("A","A","A"), "a0243a891584f48aeb59677458705d209c0defd977655cb8a6c78298ac9d5981571659e1d35024285d718dd1f603876ad785f59ea814b91ee61a4433856c6391", 'keccak512 (hex/tripple_A)');
+is( keccak512_b64("A","A","A"), "oCQ6iRWE9IrrWWd0WHBdIJwN79l3ZVy4pseCmKydWYFXFlnh01AkKF1xjdH2A4dq14X1nqgUuR7mGkQzhWxjkQ==", 'keccak512 (base64/tripple_A)');
+is( keccak512_b64u("A","A","A"), "oCQ6iRWE9IrrWWd0WHBdIJwN79l3ZVy4pseCmKydWYFXFlnh01AkKF1xjdH2A4dq14X1nqgUuR7mGkQzhWxjkQ", 'keccak512 (base64url/tripple_A)');
+is( digest_data('Keccak512', "A","A","A"), pack("H*","a0243a891584f48aeb59677458705d209c0defd977655cb8a6c78298ac9d5981571659e1d35024285d718dd1f603876ad785f59ea814b91ee61a4433856c6391"), 'keccak512 (digest_data_raw/tripple_A)');
+is( digest_data_hex('Keccak512', "A","A","A"), "a0243a891584f48aeb59677458705d209c0defd977655cb8a6c78298ac9d5981571659e1d35024285d718dd1f603876ad785f59ea814b91ee61a4433856c6391", 'keccak512 (digest_data_hex/tripple_A)');
+is( digest_data_b64('Keccak512', "A","A","A"), "oCQ6iRWE9IrrWWd0WHBdIJwN79l3ZVy4pseCmKydWYFXFlnh01AkKF1xjdH2A4dq14X1nqgUuR7mGkQzhWxjkQ==", 'keccak512 (digest_data_b64/tripple_A)');
+is( digest_data_b64u('Keccak512', "A","A","A"), "oCQ6iRWE9IrrWWd0WHBdIJwN79l3ZVy4pseCmKydWYFXFlnh01AkKF1xjdH2A4dq14X1nqgUuR7mGkQzhWxjkQ", 'keccak512 (digest_data_b64u/tripple_A)');
+is( Crypt::Digest::Keccak512->new->add("A","A","A")->hexdigest, "a0243a891584f48aeb59677458705d209c0defd977655cb8a6c78298ac9d5981571659e1d35024285d718dd1f603876ad785f59ea814b91ee61a4433856c6391", 'keccak512 (OO/tripple_A)');
+is( Crypt::Digest::Keccak512->new->add("A")->add("A")->add("A")->hexdigest, "a0243a891584f48aeb59677458705d209c0defd977655cb8a6c78298ac9d5981571659e1d35024285d718dd1f603876ad785f59ea814b91ee61a4433856c6391", 'keccak512 (OO3/tripple_A)');
+
+
+is( keccak512(""), pack("H*","0eab42de4c3ceb9235fc91acffe746b29c29a8c366b7c60e4e67c466f36a4304c00fa9caf9d87976ba469bcbe06713b435f091ef2769fb160cdab33d3670680e"), 'keccak512 (raw/1)');
+is( keccak512_hex(""), "0eab42de4c3ceb9235fc91acffe746b29c29a8c366b7c60e4e67c466f36a4304c00fa9caf9d87976ba469bcbe06713b435f091ef2769fb160cdab33d3670680e", 'keccak512 (hex/1)');
+is( keccak512_b64(""), "DqtC3kw865I1/JGs/+dGspwpqMNmt8YOTmfEZvNqQwTAD6nK+dh5drpGm8vgZxO0NfCR7ydp+xYM2rM9NnBoDg==", 'keccak512 (base64/1)');
+is( digest_data('Keccak512', ""), pack("H*","0eab42de4c3ceb9235fc91acffe746b29c29a8c366b7c60e4e67c466f36a4304c00fa9caf9d87976ba469bcbe06713b435f091ef2769fb160cdab33d3670680e"), 'keccak512 (digest_data_raw/1)');
+is( digest_data_hex('Keccak512', ""), "0eab42de4c3ceb9235fc91acffe746b29c29a8c366b7c60e4e67c466f36a4304c00fa9caf9d87976ba469bcbe06713b435f091ef2769fb160cdab33d3670680e", 'keccak512 (digest_data_hex/1)');
+is( digest_data_b64('Keccak512', ""), "DqtC3kw865I1/JGs/+dGspwpqMNmt8YOTmfEZvNqQwTAD6nK+dh5drpGm8vgZxO0NfCR7ydp+xYM2rM9NnBoDg==", 'keccak512 (digest_data_b64/1)');
+is( digest_data_b64u('Keccak512', ""), "DqtC3kw865I1_JGs_-dGspwpqMNmt8YOTmfEZvNqQwTAD6nK-dh5drpGm8vgZxO0NfCR7ydp-xYM2rM9NnBoDg", 'keccak512 (digest_data_b64u/1)');
+is( Crypt::Digest::Keccak512->new->add("")->hexdigest, "0eab42de4c3ceb9235fc91acffe746b29c29a8c366b7c60e4e67c466f36a4304c00fa9caf9d87976ba469bcbe06713b435f091ef2769fb160cdab33d3670680e", 'keccak512 (OO/1)');
+
+is( keccak512("123"), pack("H*","8ca32d950873fd2b5b34a7d79c4a294b2fd805abe3261beb04fab61a3b4b75609afd6478aa8d34e03f262d68bb09a2ba9d655e228c96723b2854838a6e613b9d"), 'keccak512 (raw/2)');
+is( keccak512_hex("123"), "8ca32d950873fd2b5b34a7d79c4a294b2fd805abe3261beb04fab61a3b4b75609afd6478aa8d34e03f262d68bb09a2ba9d655e228c96723b2854838a6e613b9d", 'keccak512 (hex/2)');
+is( keccak512_b64("123"), "jKMtlQhz/StbNKfXnEopSy/YBavjJhvrBPq2GjtLdWCa/WR4qo004D8mLWi7CaK6nWVeIoyWcjsoVIOKbmE7nQ==", 'keccak512 (base64/2)');
+is( digest_data('Keccak512', "123"), pack("H*","8ca32d950873fd2b5b34a7d79c4a294b2fd805abe3261beb04fab61a3b4b75609afd6478aa8d34e03f262d68bb09a2ba9d655e228c96723b2854838a6e613b9d"), 'keccak512 (digest_data_raw/2)');
+is( digest_data_hex('Keccak512', "123"), "8ca32d950873fd2b5b34a7d79c4a294b2fd805abe3261beb04fab61a3b4b75609afd6478aa8d34e03f262d68bb09a2ba9d655e228c96723b2854838a6e613b9d", 'keccak512 (digest_data_hex/2)');
+is( digest_data_b64('Keccak512', "123"), "jKMtlQhz/StbNKfXnEopSy/YBavjJhvrBPq2GjtLdWCa/WR4qo004D8mLWi7CaK6nWVeIoyWcjsoVIOKbmE7nQ==", 'keccak512 (digest_data_b64/2)');
+is( digest_data_b64u('Keccak512', "123"), "jKMtlQhz_StbNKfXnEopSy_YBavjJhvrBPq2GjtLdWCa_WR4qo004D8mLWi7CaK6nWVeIoyWcjsoVIOKbmE7nQ", 'keccak512 (digest_data_b64u/2)');
+is( Crypt::Digest::Keccak512->new->add("123")->hexdigest, "8ca32d950873fd2b5b34a7d79c4a294b2fd805abe3261beb04fab61a3b4b75609afd6478aa8d34e03f262d68bb09a2ba9d655e228c96723b2854838a6e613b9d", 'keccak512 (OO/2)');
+
+is( keccak512("test\0test\0test\n"), pack("H*","32c764ac224dfa7a5c8205dada12006a56d15a6377b6fcd65b6e17be8759459ae847d9d7cadf335d4b477541db19883a4d4a7e2dae8f9f8504f4e36cc3417e00"), 'keccak512 (raw/3)');
+is( keccak512_hex("test\0test\0test\n"), "32c764ac224dfa7a5c8205dada12006a56d15a6377b6fcd65b6e17be8759459ae847d9d7cadf335d4b477541db19883a4d4a7e2dae8f9f8504f4e36cc3417e00", 'keccak512 (hex/3)');
+is( keccak512_b64("test\0test\0test\n"), "MsdkrCJN+npcggXa2hIAalbRWmN3tvzWW24XvodZRZroR9nXyt8zXUtHdUHbGYg6TUp+La6Pn4UE9ONsw0F+AA==", 'keccak512 (base64/3)');
+is( digest_data('Keccak512', "test\0test\0test\n"), pack("H*","32c764ac224dfa7a5c8205dada12006a56d15a6377b6fcd65b6e17be8759459ae847d9d7cadf335d4b477541db19883a4d4a7e2dae8f9f8504f4e36cc3417e00"), 'keccak512 (digest_data_raw/3)');
+is( digest_data_hex('Keccak512', "test\0test\0test\n"), "32c764ac224dfa7a5c8205dada12006a56d15a6377b6fcd65b6e17be8759459ae847d9d7cadf335d4b477541db19883a4d4a7e2dae8f9f8504f4e36cc3417e00", 'keccak512 (digest_data_hex/3)');
+is( digest_data_b64('Keccak512', "test\0test\0test\n"), "MsdkrCJN+npcggXa2hIAalbRWmN3tvzWW24XvodZRZroR9nXyt8zXUtHdUHbGYg6TUp+La6Pn4UE9ONsw0F+AA==", 'keccak512 (digest_data_b64/3)');
+is( digest_data_b64u('Keccak512', "test\0test\0test\n"), "MsdkrCJN-npcggXa2hIAalbRWmN3tvzWW24XvodZRZroR9nXyt8zXUtHdUHbGYg6TUp-La6Pn4UE9ONsw0F-AA", 'keccak512 (digest_data_b64u/3)');
+is( Crypt::Digest::Keccak512->new->add("test\0test\0test\n")->hexdigest, "32c764ac224dfa7a5c8205dada12006a56d15a6377b6fcd65b6e17be8759459ae847d9d7cadf335d4b477541db19883a4d4a7e2dae8f9f8504f4e36cc3417e00", 'keccak512 (OO/3)');
+
+
+is( keccak512_file('t/data/binary-test.file'), pack("H*","369b779f34f5eb28cbc04f5624e64897a63dc5e5652e9414fb24e252f91d4d64358d1d837c343c5f338f6afd888f0ccc4770ca6c34a81e0c0f28836b7e4047f8"), 'keccak512 (raw/file/1)');
+is( keccak512_file_hex('t/data/binary-test.file'), "369b779f34f5eb28cbc04f5624e64897a63dc5e5652e9414fb24e252f91d4d64358d1d837c343c5f338f6afd888f0ccc4770ca6c34a81e0c0f28836b7e4047f8", 'keccak512 (hex/file/1)');
+is( keccak512_file_b64('t/data/binary-test.file'), "Npt3nzT16yjLwE9WJOZIl6Y9xeVlLpQU+yTiUvkdTWQ1jR2DfDQ8XzOPav2IjwzMR3DKbDSoHgwPKINrfkBH+A==", 'keccak512 (base64/file/1)');
+is( digest_file('Keccak512', 't/data/binary-test.file'), pack("H*","369b779f34f5eb28cbc04f5624e64897a63dc5e5652e9414fb24e252f91d4d64358d1d837c343c5f338f6afd888f0ccc4770ca6c34a81e0c0f28836b7e4047f8"), 'keccak512 (digest_file_raw/file/1)');
+is( digest_file_hex('Keccak512', 't/data/binary-test.file'), "369b779f34f5eb28cbc04f5624e64897a63dc5e5652e9414fb24e252f91d4d64358d1d837c343c5f338f6afd888f0ccc4770ca6c34a81e0c0f28836b7e4047f8", 'keccak512 (digest_file_hex/file/1)');
+is( digest_file_b64('Keccak512', 't/data/binary-test.file'), "Npt3nzT16yjLwE9WJOZIl6Y9xeVlLpQU+yTiUvkdTWQ1jR2DfDQ8XzOPav2IjwzMR3DKbDSoHgwPKINrfkBH+A==", 'keccak512 (digest_file_b64/file/1)');
+is( digest_file_b64u('Keccak512', 't/data/binary-test.file'), "Npt3nzT16yjLwE9WJOZIl6Y9xeVlLpQU-yTiUvkdTWQ1jR2DfDQ8XzOPav2IjwzMR3DKbDSoHgwPKINrfkBH-A", 'keccak512 (digest_file_b64u/file/1)');
+is( Crypt::Digest::Keccak512->new->addfile('t/data/binary-test.file')->hexdigest, "369b779f34f5eb28cbc04f5624e64897a63dc5e5652e9414fb24e252f91d4d64358d1d837c343c5f338f6afd888f0ccc4770ca6c34a81e0c0f28836b7e4047f8", 'keccak512 (OO/file/1)');
+{
+ open(my $fh, '<', 't/data/binary-test.file');
+ binmode($fh);
+ is( Crypt::Digest::Keccak512->new->addfile($fh)->hexdigest, "369b779f34f5eb28cbc04f5624e64897a63dc5e5652e9414fb24e252f91d4d64358d1d837c343c5f338f6afd888f0ccc4770ca6c34a81e0c0f28836b7e4047f8", 'keccak512 (OO/filehandle/1)');
+ close($fh);
+}
+
+is( keccak512_file('t/data/text-CR.file'), pack("H*","6ec6b5af9b8a35ab4991000286f85b2e253fe00f5904ad4b999859c61c50b1c8f23050f6ad97f87bebd8e0e6b8277896b5123be2a3f961eb594759952c49b793"), 'keccak512 (raw/file/2)');
+is( keccak512_file_hex('t/data/text-CR.file'), "6ec6b5af9b8a35ab4991000286f85b2e253fe00f5904ad4b999859c61c50b1c8f23050f6ad97f87bebd8e0e6b8277896b5123be2a3f961eb594759952c49b793", 'keccak512 (hex/file/2)');
+is( keccak512_file_b64('t/data/text-CR.file'), "bsa1r5uKNatJkQAChvhbLiU/4A9ZBK1LmZhZxhxQscjyMFD2rZf4e+vY4Oa4J3iWtRI74qP5YetZR1mVLEm3kw==", 'keccak512 (base64/file/2)');
+is( digest_file('Keccak512', 't/data/text-CR.file'), pack("H*","6ec6b5af9b8a35ab4991000286f85b2e253fe00f5904ad4b999859c61c50b1c8f23050f6ad97f87bebd8e0e6b8277896b5123be2a3f961eb594759952c49b793"), 'keccak512 (digest_file_raw/file/2)');
+is( digest_file_hex('Keccak512', 't/data/text-CR.file'), "6ec6b5af9b8a35ab4991000286f85b2e253fe00f5904ad4b999859c61c50b1c8f23050f6ad97f87bebd8e0e6b8277896b5123be2a3f961eb594759952c49b793", 'keccak512 (digest_file_hex/file/2)');
+is( digest_file_b64('Keccak512', 't/data/text-CR.file'), "bsa1r5uKNatJkQAChvhbLiU/4A9ZBK1LmZhZxhxQscjyMFD2rZf4e+vY4Oa4J3iWtRI74qP5YetZR1mVLEm3kw==", 'keccak512 (digest_file_b64/file/2)');
+is( digest_file_b64u('Keccak512', 't/data/text-CR.file'), "bsa1r5uKNatJkQAChvhbLiU_4A9ZBK1LmZhZxhxQscjyMFD2rZf4e-vY4Oa4J3iWtRI74qP5YetZR1mVLEm3kw", 'keccak512 (digest_file_b64u/file/2)');
+is( Crypt::Digest::Keccak512->new->addfile('t/data/text-CR.file')->hexdigest, "6ec6b5af9b8a35ab4991000286f85b2e253fe00f5904ad4b999859c61c50b1c8f23050f6ad97f87bebd8e0e6b8277896b5123be2a3f961eb594759952c49b793", 'keccak512 (OO/file/2)');
+{
+ open(my $fh, '<', 't/data/text-CR.file');
+ binmode($fh);
+ is( Crypt::Digest::Keccak512->new->addfile($fh)->hexdigest, "6ec6b5af9b8a35ab4991000286f85b2e253fe00f5904ad4b999859c61c50b1c8f23050f6ad97f87bebd8e0e6b8277896b5123be2a3f961eb594759952c49b793", 'keccak512 (OO/filehandle/2)');
+ close($fh);
+}
+
+is( keccak512_file('t/data/text-CRLF.file'), pack("H*","f68607a6a0c9845780ba2e39c41748ff57188d93dd9b8140573f0a3558dd4f77a8e2c8348a936e43600f2bb2fdf2a73bba27044fb51b6c11787f453be407fbaf"), 'keccak512 (raw/file/3)');
+is( keccak512_file_hex('t/data/text-CRLF.file'), "f68607a6a0c9845780ba2e39c41748ff57188d93dd9b8140573f0a3558dd4f77a8e2c8348a936e43600f2bb2fdf2a73bba27044fb51b6c11787f453be407fbaf", 'keccak512 (hex/file/3)');
+is( keccak512_file_b64('t/data/text-CRLF.file'), "9oYHpqDJhFeAui45xBdI/1cYjZPdm4FAVz8KNVjdT3eo4sg0ipNuQ2APK7L98qc7uicET7UbbBF4f0U75Af7rw==", 'keccak512 (base64/file/3)');
+is( digest_file('Keccak512', 't/data/text-CRLF.file'), pack("H*","f68607a6a0c9845780ba2e39c41748ff57188d93dd9b8140573f0a3558dd4f77a8e2c8348a936e43600f2bb2fdf2a73bba27044fb51b6c11787f453be407fbaf"), 'keccak512 (digest_file_raw/file/3)');
+is( digest_file_hex('Keccak512', 't/data/text-CRLF.file'), "f68607a6a0c9845780ba2e39c41748ff57188d93dd9b8140573f0a3558dd4f77a8e2c8348a936e43600f2bb2fdf2a73bba27044fb51b6c11787f453be407fbaf", 'keccak512 (digest_file_hex/file/3)');
+is( digest_file_b64('Keccak512', 't/data/text-CRLF.file'), "9oYHpqDJhFeAui45xBdI/1cYjZPdm4FAVz8KNVjdT3eo4sg0ipNuQ2APK7L98qc7uicET7UbbBF4f0U75Af7rw==", 'keccak512 (digest_file_b64/file/3)');
+is( digest_file_b64u('Keccak512', 't/data/text-CRLF.file'), "9oYHpqDJhFeAui45xBdI_1cYjZPdm4FAVz8KNVjdT3eo4sg0ipNuQ2APK7L98qc7uicET7UbbBF4f0U75Af7rw", 'keccak512 (digest_file_b64u/file/3)');
+is( Crypt::Digest::Keccak512->new->addfile('t/data/text-CRLF.file')->hexdigest, "f68607a6a0c9845780ba2e39c41748ff57188d93dd9b8140573f0a3558dd4f77a8e2c8348a936e43600f2bb2fdf2a73bba27044fb51b6c11787f453be407fbaf", 'keccak512 (OO/file/3)');
+{
+ open(my $fh, '<', 't/data/text-CRLF.file');
+ binmode($fh);
+ is( Crypt::Digest::Keccak512->new->addfile($fh)->hexdigest, "f68607a6a0c9845780ba2e39c41748ff57188d93dd9b8140573f0a3558dd4f77a8e2c8348a936e43600f2bb2fdf2a73bba27044fb51b6c11787f453be407fbaf", 'keccak512 (OO/filehandle/3)');
+ close($fh);
+}
+
+is( keccak512_file('t/data/text-LF.file'), pack("H*","241eac4274cd76c6263fa67911d3f768afb791c280f03c757f5c2d067eb020e52c4ac934e2712cd350bfcbe01114e0824dec72140f0355b615f126b20c57c446"), 'keccak512 (raw/file/4)');
+is( keccak512_file_hex('t/data/text-LF.file'), "241eac4274cd76c6263fa67911d3f768afb791c280f03c757f5c2d067eb020e52c4ac934e2712cd350bfcbe01114e0824dec72140f0355b615f126b20c57c446", 'keccak512 (hex/file/4)');
+is( keccak512_file_b64('t/data/text-LF.file'), "JB6sQnTNdsYmP6Z5EdP3aK+3kcKA8Dx1f1wtBn6wIOUsSsk04nEs01C/y+ARFOCCTexyFA8DVbYV8SayDFfERg==", 'keccak512 (base64/file/4)');
+is( digest_file('Keccak512', 't/data/text-LF.file'), pack("H*","241eac4274cd76c6263fa67911d3f768afb791c280f03c757f5c2d067eb020e52c4ac934e2712cd350bfcbe01114e0824dec72140f0355b615f126b20c57c446"), 'keccak512 (digest_file_raw/file/4)');
+is( digest_file_hex('Keccak512', 't/data/text-LF.file'), "241eac4274cd76c6263fa67911d3f768afb791c280f03c757f5c2d067eb020e52c4ac934e2712cd350bfcbe01114e0824dec72140f0355b615f126b20c57c446", 'keccak512 (digest_file_hex/file/4)');
+is( digest_file_b64('Keccak512', 't/data/text-LF.file'), "JB6sQnTNdsYmP6Z5EdP3aK+3kcKA8Dx1f1wtBn6wIOUsSsk04nEs01C/y+ARFOCCTexyFA8DVbYV8SayDFfERg==", 'keccak512 (digest_file_b64/file/4)');
+is( digest_file_b64u('Keccak512', 't/data/text-LF.file'), "JB6sQnTNdsYmP6Z5EdP3aK-3kcKA8Dx1f1wtBn6wIOUsSsk04nEs01C_y-ARFOCCTexyFA8DVbYV8SayDFfERg", 'keccak512 (digest_file_b64u/file/4)');
+is( Crypt::Digest::Keccak512->new->addfile('t/data/text-LF.file')->hexdigest, "241eac4274cd76c6263fa67911d3f768afb791c280f03c757f5c2d067eb020e52c4ac934e2712cd350bfcbe01114e0824dec72140f0355b615f126b20c57c446", 'keccak512 (OO/file/4)');
+{
+ open(my $fh, '<', 't/data/text-LF.file');
+ binmode($fh);
+ is( Crypt::Digest::Keccak512->new->addfile($fh)->hexdigest, "241eac4274cd76c6263fa67911d3f768afb791c280f03c757f5c2d067eb020e52c4ac934e2712cd350bfcbe01114e0824dec72140f0355b615f126b20c57c446", 'keccak512 (OO/filehandle/4)');
+ close($fh);
+}
diff --git a/t/digest_md2.t b/t/digest_md2.t
index 312011d7..58b56865 100644
--- a/t/digest_md2.t
+++ b/t/digest_md2.t
@@ -3,7 +3,7 @@
use strict;
use warnings;
-use Test::More tests => 8*3 + 9*4 + 6;
+use Test::More tests => 8*3 + 9*4 + 10 + 6;
use Crypt::Digest qw( digest_data digest_data_hex digest_data_b64 digest_data_b64u digest_file digest_file_hex digest_file_b64 digest_file_b64u );
use Crypt::Digest::MD2 qw( md2 md2_hex md2_b64 md2_b64u md2_file md2_file_hex md2_file_b64 md2_file_b64u );
@@ -15,6 +15,17 @@ is( Crypt::Digest::MD2->hashsize, 16, 'hashsize/4');
is( Crypt::Digest->new('MD2')->hashsize, 16, 'hashsize/5');
is( Crypt::Digest::MD2->new->hashsize, 16, 'hashsize/6');
+is( md2("A","A","A"), pack("H*","8788c1729761fdad983b830f04b19e86"), 'md2 (raw/tripple_A)');
+is( md2_hex("A","A","A"), "8788c1729761fdad983b830f04b19e86", 'md2 (hex/tripple_A)');
+is( md2_b64("A","A","A"), "h4jBcpdh/a2YO4MPBLGehg==", 'md2 (base64/tripple_A)');
+is( md2_b64u("A","A","A"), "h4jBcpdh_a2YO4MPBLGehg", 'md2 (base64url/tripple_A)');
+is( digest_data('MD2', "A","A","A"), pack("H*","8788c1729761fdad983b830f04b19e86"), 'md2 (digest_data_raw/tripple_A)');
+is( digest_data_hex('MD2', "A","A","A"), "8788c1729761fdad983b830f04b19e86", 'md2 (digest_data_hex/tripple_A)');
+is( digest_data_b64('MD2', "A","A","A"), "h4jBcpdh/a2YO4MPBLGehg==", 'md2 (digest_data_b64/tripple_A)');
+is( digest_data_b64u('MD2', "A","A","A"), "h4jBcpdh_a2YO4MPBLGehg", 'md2 (digest_data_b64u/tripple_A)');
+is( Crypt::Digest::MD2->new->add("A","A","A")->hexdigest, "8788c1729761fdad983b830f04b19e86", 'md2 (OO/tripple_A)');
+is( Crypt::Digest::MD2->new->add("A")->add("A")->add("A")->hexdigest, "8788c1729761fdad983b830f04b19e86", 'md2 (OO3/tripple_A)');
+
is( md2(""), pack("H*","8350e5a3e24c153df2275c9f80692773"), 'md2 (raw/1)');
is( md2_hex(""), "8350e5a3e24c153df2275c9f80692773", 'md2 (hex/1)');
diff --git a/t/digest_md4.t b/t/digest_md4.t
index b83d0610..f20f9aae 100644
--- a/t/digest_md4.t
+++ b/t/digest_md4.t
@@ -3,7 +3,7 @@
use strict;
use warnings;
-use Test::More tests => 8*3 + 9*4 + 6;
+use Test::More tests => 8*3 + 9*4 + 10 + 6;
use Crypt::Digest qw( digest_data digest_data_hex digest_data_b64 digest_data_b64u digest_file digest_file_hex digest_file_b64 digest_file_b64u );
use Crypt::Digest::MD4 qw( md4 md4_hex md4_b64 md4_b64u md4_file md4_file_hex md4_file_b64 md4_file_b64u );
@@ -15,6 +15,17 @@ is( Crypt::Digest::MD4->hashsize, 16, 'hashsize/4');
is( Crypt::Digest->new('MD4')->hashsize, 16, 'hashsize/5');
is( Crypt::Digest::MD4->new->hashsize, 16, 'hashsize/6');
+is( md4("A","A","A"), pack("H*","17c3b38c112ac61c1f0d46555f379f14"), 'md4 (raw/tripple_A)');
+is( md4_hex("A","A","A"), "17c3b38c112ac61c1f0d46555f379f14", 'md4 (hex/tripple_A)');
+is( md4_b64("A","A","A"), "F8OzjBEqxhwfDUZVXzefFA==", 'md4 (base64/tripple_A)');
+is( md4_b64u("A","A","A"), "F8OzjBEqxhwfDUZVXzefFA", 'md4 (base64url/tripple_A)');
+is( digest_data('MD4', "A","A","A"), pack("H*","17c3b38c112ac61c1f0d46555f379f14"), 'md4 (digest_data_raw/tripple_A)');
+is( digest_data_hex('MD4', "A","A","A"), "17c3b38c112ac61c1f0d46555f379f14", 'md4 (digest_data_hex/tripple_A)');
+is( digest_data_b64('MD4', "A","A","A"), "F8OzjBEqxhwfDUZVXzefFA==", 'md4 (digest_data_b64/tripple_A)');
+is( digest_data_b64u('MD4', "A","A","A"), "F8OzjBEqxhwfDUZVXzefFA", 'md4 (digest_data_b64u/tripple_A)');
+is( Crypt::Digest::MD4->new->add("A","A","A")->hexdigest, "17c3b38c112ac61c1f0d46555f379f14", 'md4 (OO/tripple_A)');
+is( Crypt::Digest::MD4->new->add("A")->add("A")->add("A")->hexdigest, "17c3b38c112ac61c1f0d46555f379f14", 'md4 (OO3/tripple_A)');
+
is( md4(""), pack("H*","31d6cfe0d16ae931b73c59d7e0c089c0"), 'md4 (raw/1)');
is( md4_hex(""), "31d6cfe0d16ae931b73c59d7e0c089c0", 'md4 (hex/1)');
diff --git a/t/digest_md5.t b/t/digest_md5.t
index c4b22400..2f617b12 100644
--- a/t/digest_md5.t
+++ b/t/digest_md5.t
@@ -3,7 +3,7 @@
use strict;
use warnings;
-use Test::More tests => 8*3 + 9*4 + 6;
+use Test::More tests => 8*3 + 9*4 + 10 + 6;
use Crypt::Digest qw( digest_data digest_data_hex digest_data_b64 digest_data_b64u digest_file digest_file_hex digest_file_b64 digest_file_b64u );
use Crypt::Digest::MD5 qw( md5 md5_hex md5_b64 md5_b64u md5_file md5_file_hex md5_file_b64 md5_file_b64u );
@@ -15,6 +15,17 @@ is( Crypt::Digest::MD5->hashsize, 16, 'hashsize/4');
is( Crypt::Digest->new('MD5')->hashsize, 16, 'hashsize/5');
is( Crypt::Digest::MD5->new->hashsize, 16, 'hashsize/6');
+is( md5("A","A","A"), pack("H*","e1faffb3e614e6c2fba74296962386b7"), 'md5 (raw/tripple_A)');
+is( md5_hex("A","A","A"), "e1faffb3e614e6c2fba74296962386b7", 'md5 (hex/tripple_A)');
+is( md5_b64("A","A","A"), "4fr/s+YU5sL7p0KWliOGtw==", 'md5 (base64/tripple_A)');
+is( md5_b64u("A","A","A"), "4fr_s-YU5sL7p0KWliOGtw", 'md5 (base64url/tripple_A)');
+is( digest_data('MD5', "A","A","A"), pack("H*","e1faffb3e614e6c2fba74296962386b7"), 'md5 (digest_data_raw/tripple_A)');
+is( digest_data_hex('MD5', "A","A","A"), "e1faffb3e614e6c2fba74296962386b7", 'md5 (digest_data_hex/tripple_A)');
+is( digest_data_b64('MD5', "A","A","A"), "4fr/s+YU5sL7p0KWliOGtw==", 'md5 (digest_data_b64/tripple_A)');
+is( digest_data_b64u('MD5', "A","A","A"), "4fr_s-YU5sL7p0KWliOGtw", 'md5 (digest_data_b64u/tripple_A)');
+is( Crypt::Digest::MD5->new->add("A","A","A")->hexdigest, "e1faffb3e614e6c2fba74296962386b7", 'md5 (OO/tripple_A)');
+is( Crypt::Digest::MD5->new->add("A")->add("A")->add("A")->hexdigest, "e1faffb3e614e6c2fba74296962386b7", 'md5 (OO3/tripple_A)');
+
is( md5(""), pack("H*","d41d8cd98f00b204e9800998ecf8427e"), 'md5 (raw/1)');
is( md5_hex(""), "d41d8cd98f00b204e9800998ecf8427e", 'md5 (hex/1)');
diff --git a/t/digest_ripemd128.t b/t/digest_ripemd128.t
index e655aa23..d91faf10 100644
--- a/t/digest_ripemd128.t
+++ b/t/digest_ripemd128.t
@@ -3,7 +3,7 @@
use strict;
use warnings;
-use Test::More tests => 8*3 + 9*4 + 6;
+use Test::More tests => 8*3 + 9*4 + 10 + 6;
use Crypt::Digest qw( digest_data digest_data_hex digest_data_b64 digest_data_b64u digest_file digest_file_hex digest_file_b64 digest_file_b64u );
use Crypt::Digest::RIPEMD128 qw( ripemd128 ripemd128_hex ripemd128_b64 ripemd128_b64u ripemd128_file ripemd128_file_hex ripemd128_file_b64 ripemd128_file_b64u );
@@ -15,6 +15,17 @@ is( Crypt::Digest::RIPEMD128->hashsize, 16, 'hashsize/4');
is( Crypt::Digest->new('RIPEMD128')->hashsize, 16, 'hashsize/5');
is( Crypt::Digest::RIPEMD128->new->hashsize, 16, 'hashsize/6');
+is( ripemd128("A","A","A"), pack("H*","c2750c6ca0c35d367de2993c3f55e1df"), 'ripemd128 (raw/tripple_A)');
+is( ripemd128_hex("A","A","A"), "c2750c6ca0c35d367de2993c3f55e1df", 'ripemd128 (hex/tripple_A)');
+is( ripemd128_b64("A","A","A"), "wnUMbKDDXTZ94pk8P1Xh3w==", 'ripemd128 (base64/tripple_A)');
+is( ripemd128_b64u("A","A","A"), "wnUMbKDDXTZ94pk8P1Xh3w", 'ripemd128 (base64url/tripple_A)');
+is( digest_data('RIPEMD128', "A","A","A"), pack("H*","c2750c6ca0c35d367de2993c3f55e1df"), 'ripemd128 (digest_data_raw/tripple_A)');
+is( digest_data_hex('RIPEMD128', "A","A","A"), "c2750c6ca0c35d367de2993c3f55e1df", 'ripemd128 (digest_data_hex/tripple_A)');
+is( digest_data_b64('RIPEMD128', "A","A","A"), "wnUMbKDDXTZ94pk8P1Xh3w==", 'ripemd128 (digest_data_b64/tripple_A)');
+is( digest_data_b64u('RIPEMD128', "A","A","A"), "wnUMbKDDXTZ94pk8P1Xh3w", 'ripemd128 (digest_data_b64u/tripple_A)');
+is( Crypt::Digest::RIPEMD128->new->add("A","A","A")->hexdigest, "c2750c6ca0c35d367de2993c3f55e1df", 'ripemd128 (OO/tripple_A)');
+is( Crypt::Digest::RIPEMD128->new->add("A")->add("A")->add("A")->hexdigest, "c2750c6ca0c35d367de2993c3f55e1df", 'ripemd128 (OO3/tripple_A)');
+
is( ripemd128(""), pack("H*","cdf26213a150dc3ecb610f18f6b38b46"), 'ripemd128 (raw/1)');
is( ripemd128_hex(""), "cdf26213a150dc3ecb610f18f6b38b46", 'ripemd128 (hex/1)');
diff --git a/t/digest_ripemd160.t b/t/digest_ripemd160.t
index f290f9e2..c9e064cc 100644
--- a/t/digest_ripemd160.t
+++ b/t/digest_ripemd160.t
@@ -3,7 +3,7 @@
use strict;
use warnings;
-use Test::More tests => 8*3 + 9*4 + 6;
+use Test::More tests => 8*3 + 9*4 + 10 + 6;
use Crypt::Digest qw( digest_data digest_data_hex digest_data_b64 digest_data_b64u digest_file digest_file_hex digest_file_b64 digest_file_b64u );
use Crypt::Digest::RIPEMD160 qw( ripemd160 ripemd160_hex ripemd160_b64 ripemd160_b64u ripemd160_file ripemd160_file_hex ripemd160_file_b64 ripemd160_file_b64u );
@@ -15,6 +15,17 @@ is( Crypt::Digest::RIPEMD160->hashsize, 20, 'hashsize/4');
is( Crypt::Digest->new('RIPEMD160')->hashsize, 20, 'hashsize/5');
is( Crypt::Digest::RIPEMD160->new->hashsize, 20, 'hashsize/6');
+is( ripemd160("A","A","A"), pack("H*","e4e130acc1d2a5a63c17efb1eedbd02be28443d1"), 'ripemd160 (raw/tripple_A)');
+is( ripemd160_hex("A","A","A"), "e4e130acc1d2a5a63c17efb1eedbd02be28443d1", 'ripemd160 (hex/tripple_A)');
+is( ripemd160_b64("A","A","A"), "5OEwrMHSpaY8F++x7tvQK+KEQ9E=", 'ripemd160 (base64/tripple_A)');
+is( ripemd160_b64u("A","A","A"), "5OEwrMHSpaY8F--x7tvQK-KEQ9E", 'ripemd160 (base64url/tripple_A)');
+is( digest_data('RIPEMD160', "A","A","A"), pack("H*","e4e130acc1d2a5a63c17efb1eedbd02be28443d1"), 'ripemd160 (digest_data_raw/tripple_A)');
+is( digest_data_hex('RIPEMD160', "A","A","A"), "e4e130acc1d2a5a63c17efb1eedbd02be28443d1", 'ripemd160 (digest_data_hex/tripple_A)');
+is( digest_data_b64('RIPEMD160', "A","A","A"), "5OEwrMHSpaY8F++x7tvQK+KEQ9E=", 'ripemd160 (digest_data_b64/tripple_A)');
+is( digest_data_b64u('RIPEMD160', "A","A","A"), "5OEwrMHSpaY8F--x7tvQK-KEQ9E", 'ripemd160 (digest_data_b64u/tripple_A)');
+is( Crypt::Digest::RIPEMD160->new->add("A","A","A")->hexdigest, "e4e130acc1d2a5a63c17efb1eedbd02be28443d1", 'ripemd160 (OO/tripple_A)');
+is( Crypt::Digest::RIPEMD160->new->add("A")->add("A")->add("A")->hexdigest, "e4e130acc1d2a5a63c17efb1eedbd02be28443d1", 'ripemd160 (OO3/tripple_A)');
+
is( ripemd160(""), pack("H*","9c1185a5c5e9fc54612808977ee8f548b2258d31"), 'ripemd160 (raw/1)');
is( ripemd160_hex(""), "9c1185a5c5e9fc54612808977ee8f548b2258d31", 'ripemd160 (hex/1)');
diff --git a/t/digest_ripemd256.t b/t/digest_ripemd256.t
index 6b13664f..d9809bf7 100644
--- a/t/digest_ripemd256.t
+++ b/t/digest_ripemd256.t
@@ -3,7 +3,7 @@
use strict;
use warnings;
-use Test::More tests => 8*3 + 9*4 + 6;
+use Test::More tests => 8*3 + 9*4 + 10 + 6;
use Crypt::Digest qw( digest_data digest_data_hex digest_data_b64 digest_data_b64u digest_file digest_file_hex digest_file_b64 digest_file_b64u );
use Crypt::Digest::RIPEMD256 qw( ripemd256 ripemd256_hex ripemd256_b64 ripemd256_b64u ripemd256_file ripemd256_file_hex ripemd256_file_b64 ripemd256_file_b64u );
@@ -15,6 +15,17 @@ is( Crypt::Digest::RIPEMD256->hashsize, 32, 'hashsize/4');
is( Crypt::Digest->new('RIPEMD256')->hashsize, 32, 'hashsize/5');
is( Crypt::Digest::RIPEMD256->new->hashsize, 32, 'hashsize/6');
+is( ripemd256("A","A","A"), pack("H*","0c976582631435d4fbc424758105a05a622ae27726f395774858d7ea2b2f5d82"), 'ripemd256 (raw/tripple_A)');
+is( ripemd256_hex("A","A","A"), "0c976582631435d4fbc424758105a05a622ae27726f395774858d7ea2b2f5d82", 'ripemd256 (hex/tripple_A)');
+is( ripemd256_b64("A","A","A"), "DJdlgmMUNdT7xCR1gQWgWmIq4ncm85V3SFjX6isvXYI=", 'ripemd256 (base64/tripple_A)');
+is( ripemd256_b64u("A","A","A"), "DJdlgmMUNdT7xCR1gQWgWmIq4ncm85V3SFjX6isvXYI", 'ripemd256 (base64url/tripple_A)');
+is( digest_data('RIPEMD256', "A","A","A"), pack("H*","0c976582631435d4fbc424758105a05a622ae27726f395774858d7ea2b2f5d82"), 'ripemd256 (digest_data_raw/tripple_A)');
+is( digest_data_hex('RIPEMD256', "A","A","A"), "0c976582631435d4fbc424758105a05a622ae27726f395774858d7ea2b2f5d82", 'ripemd256 (digest_data_hex/tripple_A)');
+is( digest_data_b64('RIPEMD256', "A","A","A"), "DJdlgmMUNdT7xCR1gQWgWmIq4ncm85V3SFjX6isvXYI=", 'ripemd256 (digest_data_b64/tripple_A)');
+is( digest_data_b64u('RIPEMD256', "A","A","A"), "DJdlgmMUNdT7xCR1gQWgWmIq4ncm85V3SFjX6isvXYI", 'ripemd256 (digest_data_b64u/tripple_A)');
+is( Crypt::Digest::RIPEMD256->new->add("A","A","A")->hexdigest, "0c976582631435d4fbc424758105a05a622ae27726f395774858d7ea2b2f5d82", 'ripemd256 (OO/tripple_A)');
+is( Crypt::Digest::RIPEMD256->new->add("A")->add("A")->add("A")->hexdigest, "0c976582631435d4fbc424758105a05a622ae27726f395774858d7ea2b2f5d82", 'ripemd256 (OO3/tripple_A)');
+
is( ripemd256(""), pack("H*","02ba4c4e5f8ecd1877fc52d64d30e37a2d9774fb1e5d026380ae0168e3c5522d"), 'ripemd256 (raw/1)');
is( ripemd256_hex(""), "02ba4c4e5f8ecd1877fc52d64d30e37a2d9774fb1e5d026380ae0168e3c5522d", 'ripemd256 (hex/1)');
diff --git a/t/digest_ripemd320.t b/t/digest_ripemd320.t
index 4dc576d7..716a4724 100644
--- a/t/digest_ripemd320.t
+++ b/t/digest_ripemd320.t
@@ -3,7 +3,7 @@
use strict;
use warnings;
-use Test::More tests => 8*3 + 9*4 + 6;
+use Test::More tests => 8*3 + 9*4 + 10 + 6;
use Crypt::Digest qw( digest_data digest_data_hex digest_data_b64 digest_data_b64u digest_file digest_file_hex digest_file_b64 digest_file_b64u );
use Crypt::Digest::RIPEMD320 qw( ripemd320 ripemd320_hex ripemd320_b64 ripemd320_b64u ripemd320_file ripemd320_file_hex ripemd320_file_b64 ripemd320_file_b64u );
@@ -15,6 +15,17 @@ is( Crypt::Digest::RIPEMD320->hashsize, 40, 'hashsize/4');
is( Crypt::Digest->new('RIPEMD320')->hashsize, 40, 'hashsize/5');
is( Crypt::Digest::RIPEMD320->new->hashsize, 40, 'hashsize/6');
+is( ripemd320("A","A","A"), pack("H*","4cf34b2887f1dd1543fb0ce950bf155fb7c93c63d61adc67e858c1083fd54e4a7e1dab1b9b33ba60"), 'ripemd320 (raw/tripple_A)');
+is( ripemd320_hex("A","A","A"), "4cf34b2887f1dd1543fb0ce950bf155fb7c93c63d61adc67e858c1083fd54e4a7e1dab1b9b33ba60", 'ripemd320 (hex/tripple_A)');
+is( ripemd320_b64("A","A","A"), "TPNLKIfx3RVD+wzpUL8VX7fJPGPWGtxn6FjBCD/VTkp+HasbmzO6YA==", 'ripemd320 (base64/tripple_A)');
+is( ripemd320_b64u("A","A","A"), "TPNLKIfx3RVD-wzpUL8VX7fJPGPWGtxn6FjBCD_VTkp-HasbmzO6YA", 'ripemd320 (base64url/tripple_A)');
+is( digest_data('RIPEMD320', "A","A","A"), pack("H*","4cf34b2887f1dd1543fb0ce950bf155fb7c93c63d61adc67e858c1083fd54e4a7e1dab1b9b33ba60"), 'ripemd320 (digest_data_raw/tripple_A)');
+is( digest_data_hex('RIPEMD320', "A","A","A"), "4cf34b2887f1dd1543fb0ce950bf155fb7c93c63d61adc67e858c1083fd54e4a7e1dab1b9b33ba60", 'ripemd320 (digest_data_hex/tripple_A)');
+is( digest_data_b64('RIPEMD320', "A","A","A"), "TPNLKIfx3RVD+wzpUL8VX7fJPGPWGtxn6FjBCD/VTkp+HasbmzO6YA==", 'ripemd320 (digest_data_b64/tripple_A)');
+is( digest_data_b64u('RIPEMD320', "A","A","A"), "TPNLKIfx3RVD-wzpUL8VX7fJPGPWGtxn6FjBCD_VTkp-HasbmzO6YA", 'ripemd320 (digest_data_b64u/tripple_A)');
+is( Crypt::Digest::RIPEMD320->new->add("A","A","A")->hexdigest, "4cf34b2887f1dd1543fb0ce950bf155fb7c93c63d61adc67e858c1083fd54e4a7e1dab1b9b33ba60", 'ripemd320 (OO/tripple_A)');
+is( Crypt::Digest::RIPEMD320->new->add("A")->add("A")->add("A")->hexdigest, "4cf34b2887f1dd1543fb0ce950bf155fb7c93c63d61adc67e858c1083fd54e4a7e1dab1b9b33ba60", 'ripemd320 (OO3/tripple_A)');
+
is( ripemd320(""), pack("H*","22d65d5661536cdc75c1fdf5c6de7b41b9f27325ebc61e8557177d705a0ec880151c3a32a00899b8"), 'ripemd320 (raw/1)');
is( ripemd320_hex(""), "22d65d5661536cdc75c1fdf5c6de7b41b9f27325ebc61e8557177d705a0ec880151c3a32a00899b8", 'ripemd320 (hex/1)');
diff --git a/t/digest_sha1.t b/t/digest_sha1.t
index c042d09c..a77bef79 100644
--- a/t/digest_sha1.t
+++ b/t/digest_sha1.t
@@ -3,7 +3,7 @@
use strict;
use warnings;
-use Test::More tests => 8*3 + 9*4 + 6;
+use Test::More tests => 8*3 + 9*4 + 10 + 6;
use Crypt::Digest qw( digest_data digest_data_hex digest_data_b64 digest_data_b64u digest_file digest_file_hex digest_file_b64 digest_file_b64u );
use Crypt::Digest::SHA1 qw( sha1 sha1_hex sha1_b64 sha1_b64u sha1_file sha1_file_hex sha1_file_b64 sha1_file_b64u );
@@ -15,6 +15,17 @@ is( Crypt::Digest::SHA1->hashsize, 20, 'hashsize/4');
is( Crypt::Digest->new('SHA1')->hashsize, 20, 'hashsize/5');
is( Crypt::Digest::SHA1->new->hashsize, 20, 'hashsize/6');
+is( sha1("A","A","A"), pack("H*","606ec6e9bd8a8ff2ad14e5fade3f264471e82251"), 'sha1 (raw/tripple_A)');
+is( sha1_hex("A","A","A"), "606ec6e9bd8a8ff2ad14e5fade3f264471e82251", 'sha1 (hex/tripple_A)');
+is( sha1_b64("A","A","A"), "YG7G6b2Kj/KtFOX63j8mRHHoIlE=", 'sha1 (base64/tripple_A)');
+is( sha1_b64u("A","A","A"), "YG7G6b2Kj_KtFOX63j8mRHHoIlE", 'sha1 (base64url/tripple_A)');
+is( digest_data('SHA1', "A","A","A"), pack("H*","606ec6e9bd8a8ff2ad14e5fade3f264471e82251"), 'sha1 (digest_data_raw/tripple_A)');
+is( digest_data_hex('SHA1', "A","A","A"), "606ec6e9bd8a8ff2ad14e5fade3f264471e82251", 'sha1 (digest_data_hex/tripple_A)');
+is( digest_data_b64('SHA1', "A","A","A"), "YG7G6b2Kj/KtFOX63j8mRHHoIlE=", 'sha1 (digest_data_b64/tripple_A)');
+is( digest_data_b64u('SHA1', "A","A","A"), "YG7G6b2Kj_KtFOX63j8mRHHoIlE", 'sha1 (digest_data_b64u/tripple_A)');
+is( Crypt::Digest::SHA1->new->add("A","A","A")->hexdigest, "606ec6e9bd8a8ff2ad14e5fade3f264471e82251", 'sha1 (OO/tripple_A)');
+is( Crypt::Digest::SHA1->new->add("A")->add("A")->add("A")->hexdigest, "606ec6e9bd8a8ff2ad14e5fade3f264471e82251", 'sha1 (OO3/tripple_A)');
+
is( sha1(""), pack("H*","da39a3ee5e6b4b0d3255bfef95601890afd80709"), 'sha1 (raw/1)');
is( sha1_hex(""), "da39a3ee5e6b4b0d3255bfef95601890afd80709", 'sha1 (hex/1)');
diff --git a/t/digest_sha224.t b/t/digest_sha224.t
index 7489768a..7d7244bf 100644
--- a/t/digest_sha224.t
+++ b/t/digest_sha224.t
@@ -3,7 +3,7 @@
use strict;
use warnings;
-use Test::More tests => 8*3 + 9*4 + 6;
+use Test::More tests => 8*3 + 9*4 + 10 + 6;
use Crypt::Digest qw( digest_data digest_data_hex digest_data_b64 digest_data_b64u digest_file digest_file_hex digest_file_b64 digest_file_b64u );
use Crypt::Digest::SHA224 qw( sha224 sha224_hex sha224_b64 sha224_b64u sha224_file sha224_file_hex sha224_file_b64 sha224_file_b64u );
@@ -15,6 +15,17 @@ is( Crypt::Digest::SHA224->hashsize, 28, 'hashsize/4');
is( Crypt::Digest->new('SHA224')->hashsize, 28, 'hashsize/5');
is( Crypt::Digest::SHA224->new->hashsize, 28, 'hashsize/6');
+is( sha224("A","A","A"), pack("H*","808751af5f7936f20d1c79508d98c079e42ec26802ee238a5a486018"), 'sha224 (raw/tripple_A)');
+is( sha224_hex("A","A","A"), "808751af5f7936f20d1c79508d98c079e42ec26802ee238a5a486018", 'sha224 (hex/tripple_A)');
+is( sha224_b64("A","A","A"), "gIdRr195NvINHHlQjZjAeeQuwmgC7iOKWkhgGA==", 'sha224 (base64/tripple_A)');
+is( sha224_b64u("A","A","A"), "gIdRr195NvINHHlQjZjAeeQuwmgC7iOKWkhgGA", 'sha224 (base64url/tripple_A)');
+is( digest_data('SHA224', "A","A","A"), pack("H*","808751af5f7936f20d1c79508d98c079e42ec26802ee238a5a486018"), 'sha224 (digest_data_raw/tripple_A)');
+is( digest_data_hex('SHA224', "A","A","A"), "808751af5f7936f20d1c79508d98c079e42ec26802ee238a5a486018", 'sha224 (digest_data_hex/tripple_A)');
+is( digest_data_b64('SHA224', "A","A","A"), "gIdRr195NvINHHlQjZjAeeQuwmgC7iOKWkhgGA==", 'sha224 (digest_data_b64/tripple_A)');
+is( digest_data_b64u('SHA224', "A","A","A"), "gIdRr195NvINHHlQjZjAeeQuwmgC7iOKWkhgGA", 'sha224 (digest_data_b64u/tripple_A)');
+is( Crypt::Digest::SHA224->new->add("A","A","A")->hexdigest, "808751af5f7936f20d1c79508d98c079e42ec26802ee238a5a486018", 'sha224 (OO/tripple_A)');
+is( Crypt::Digest::SHA224->new->add("A")->add("A")->add("A")->hexdigest, "808751af5f7936f20d1c79508d98c079e42ec26802ee238a5a486018", 'sha224 (OO3/tripple_A)');
+
is( sha224(""), pack("H*","d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f"), 'sha224 (raw/1)');
is( sha224_hex(""), "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f", 'sha224 (hex/1)');
diff --git a/t/digest_sha256.t b/t/digest_sha256.t
index c0f79ccd..0f1e2e6f 100644
--- a/t/digest_sha256.t
+++ b/t/digest_sha256.t
@@ -3,7 +3,7 @@
use strict;
use warnings;
-use Test::More tests => 8*3 + 9*4 + 6;
+use Test::More tests => 8*3 + 9*4 + 10 + 6;
use Crypt::Digest qw( digest_data digest_data_hex digest_data_b64 digest_data_b64u digest_file digest_file_hex digest_file_b64 digest_file_b64u );
use Crypt::Digest::SHA256 qw( sha256 sha256_hex sha256_b64 sha256_b64u sha256_file sha256_file_hex sha256_file_b64 sha256_file_b64u );
@@ -15,6 +15,17 @@ is( Crypt::Digest::SHA256->hashsize, 32, 'hashsize/4');
is( Crypt::Digest->new('SHA256')->hashsize, 32, 'hashsize/5');
is( Crypt::Digest::SHA256->new->hashsize, 32, 'hashsize/6');
+is( sha256("A","A","A"), pack("H*","cb1ad2119d8fafb69566510ee712661f9f14b83385006ef92aec47f523a38358"), 'sha256 (raw/tripple_A)');
+is( sha256_hex("A","A","A"), "cb1ad2119d8fafb69566510ee712661f9f14b83385006ef92aec47f523a38358", 'sha256 (hex/tripple_A)');
+is( sha256_b64("A","A","A"), "yxrSEZ2Pr7aVZlEO5xJmH58UuDOFAG75KuxH9SOjg1g=", 'sha256 (base64/tripple_A)');
+is( sha256_b64u("A","A","A"), "yxrSEZ2Pr7aVZlEO5xJmH58UuDOFAG75KuxH9SOjg1g", 'sha256 (base64url/tripple_A)');
+is( digest_data('SHA256', "A","A","A"), pack("H*","cb1ad2119d8fafb69566510ee712661f9f14b83385006ef92aec47f523a38358"), 'sha256 (digest_data_raw/tripple_A)');
+is( digest_data_hex('SHA256', "A","A","A"), "cb1ad2119d8fafb69566510ee712661f9f14b83385006ef92aec47f523a38358", 'sha256 (digest_data_hex/tripple_A)');
+is( digest_data_b64('SHA256', "A","A","A"), "yxrSEZ2Pr7aVZlEO5xJmH58UuDOFAG75KuxH9SOjg1g=", 'sha256 (digest_data_b64/tripple_A)');
+is( digest_data_b64u('SHA256', "A","A","A"), "yxrSEZ2Pr7aVZlEO5xJmH58UuDOFAG75KuxH9SOjg1g", 'sha256 (digest_data_b64u/tripple_A)');
+is( Crypt::Digest::SHA256->new->add("A","A","A")->hexdigest, "cb1ad2119d8fafb69566510ee712661f9f14b83385006ef92aec47f523a38358", 'sha256 (OO/tripple_A)');
+is( Crypt::Digest::SHA256->new->add("A")->add("A")->add("A")->hexdigest, "cb1ad2119d8fafb69566510ee712661f9f14b83385006ef92aec47f523a38358", 'sha256 (OO3/tripple_A)');
+
is( sha256(""), pack("H*","e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"), 'sha256 (raw/1)');
is( sha256_hex(""), "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", 'sha256 (hex/1)');
diff --git a/t/digest_sha384.t b/t/digest_sha384.t
index 506bb4b3..c65defb3 100644
--- a/t/digest_sha384.t
+++ b/t/digest_sha384.t
@@ -3,7 +3,7 @@
use strict;
use warnings;
-use Test::More tests => 8*3 + 9*4 + 6;
+use Test::More tests => 8*3 + 9*4 + 10 + 6;
use Crypt::Digest qw( digest_data digest_data_hex digest_data_b64 digest_data_b64u digest_file digest_file_hex digest_file_b64 digest_file_b64u );
use Crypt::Digest::SHA384 qw( sha384 sha384_hex sha384_b64 sha384_b64u sha384_file sha384_file_hex sha384_file_b64 sha384_file_b64u );
@@ -15,6 +15,17 @@ is( Crypt::Digest::SHA384->hashsize, 48, 'hashsize/4');
is( Crypt::Digest->new('SHA384')->hashsize, 48, 'hashsize/5');
is( Crypt::Digest::SHA384->new->hashsize, 48, 'hashsize/6');
+is( sha384("A","A","A"), pack("H*","8a5b7c19bcd1704d521f86b9618d86de0ed48fa29711ad4d16230f7d26b36111beaf7fefe8b3be7a17ce0e140ca002fe"), 'sha384 (raw/tripple_A)');
+is( sha384_hex("A","A","A"), "8a5b7c19bcd1704d521f86b9618d86de0ed48fa29711ad4d16230f7d26b36111beaf7fefe8b3be7a17ce0e140ca002fe", 'sha384 (hex/tripple_A)');
+is( sha384_b64("A","A","A"), "ilt8GbzRcE1SH4a5YY2G3g7Uj6KXEa1NFiMPfSazYRG+r3/v6LO+ehfODhQMoAL+", 'sha384 (base64/tripple_A)');
+is( sha384_b64u("A","A","A"), "ilt8GbzRcE1SH4a5YY2G3g7Uj6KXEa1NFiMPfSazYRG-r3_v6LO-ehfODhQMoAL-", 'sha384 (base64url/tripple_A)');
+is( digest_data('SHA384', "A","A","A"), pack("H*","8a5b7c19bcd1704d521f86b9618d86de0ed48fa29711ad4d16230f7d26b36111beaf7fefe8b3be7a17ce0e140ca002fe"), 'sha384 (digest_data_raw/tripple_A)');
+is( digest_data_hex('SHA384', "A","A","A"), "8a5b7c19bcd1704d521f86b9618d86de0ed48fa29711ad4d16230f7d26b36111beaf7fefe8b3be7a17ce0e140ca002fe", 'sha384 (digest_data_hex/tripple_A)');
+is( digest_data_b64('SHA384', "A","A","A"), "ilt8GbzRcE1SH4a5YY2G3g7Uj6KXEa1NFiMPfSazYRG+r3/v6LO+ehfODhQMoAL+", 'sha384 (digest_data_b64/tripple_A)');
+is( digest_data_b64u('SHA384', "A","A","A"), "ilt8GbzRcE1SH4a5YY2G3g7Uj6KXEa1NFiMPfSazYRG-r3_v6LO-ehfODhQMoAL-", 'sha384 (digest_data_b64u/tripple_A)');
+is( Crypt::Digest::SHA384->new->add("A","A","A")->hexdigest, "8a5b7c19bcd1704d521f86b9618d86de0ed48fa29711ad4d16230f7d26b36111beaf7fefe8b3be7a17ce0e140ca002fe", 'sha384 (OO/tripple_A)');
+is( Crypt::Digest::SHA384->new->add("A")->add("A")->add("A")->hexdigest, "8a5b7c19bcd1704d521f86b9618d86de0ed48fa29711ad4d16230f7d26b36111beaf7fefe8b3be7a17ce0e140ca002fe", 'sha384 (OO3/tripple_A)');
+
is( sha384(""), pack("H*","38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b"), 'sha384 (raw/1)');
is( sha384_hex(""), "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b", 'sha384 (hex/1)');
diff --git a/t/digest_sha3_224.t b/t/digest_sha3_224.t
index 6e2ecf39..75aebe6d 100644
--- a/t/digest_sha3_224.t
+++ b/t/digest_sha3_224.t
@@ -3,7 +3,7 @@
use strict;
use warnings;
-use Test::More tests => 8*3 + 9*4 + 6;
+use Test::More tests => 8*3 + 9*4 + 10 + 6;
use Crypt::Digest qw( digest_data digest_data_hex digest_data_b64 digest_data_b64u digest_file digest_file_hex digest_file_b64 digest_file_b64u );
use Crypt::Digest::SHA3_224 qw( sha3_224 sha3_224_hex sha3_224_b64 sha3_224_b64u sha3_224_file sha3_224_file_hex sha3_224_file_b64 sha3_224_file_b64u );
@@ -15,6 +15,17 @@ is( Crypt::Digest::SHA3_224->hashsize, 28, 'hashsize/4');
is( Crypt::Digest->new('SHA3_224')->hashsize, 28, 'hashsize/5');
is( Crypt::Digest::SHA3_224->new->hashsize, 28, 'hashsize/6');
+is( sha3_224("A","A","A"), pack("H*","c09d5af7d9a021c484041218f3c3787fd4274b64ffd012edca0fe55b"), 'sha3_224 (raw/tripple_A)');
+is( sha3_224_hex("A","A","A"), "c09d5af7d9a021c484041218f3c3787fd4274b64ffd012edca0fe55b", 'sha3_224 (hex/tripple_A)');
+is( sha3_224_b64("A","A","A"), "wJ1a99mgIcSEBBIY88N4f9QnS2T/0BLtyg/lWw==", 'sha3_224 (base64/tripple_A)');
+is( sha3_224_b64u("A","A","A"), "wJ1a99mgIcSEBBIY88N4f9QnS2T_0BLtyg_lWw", 'sha3_224 (base64url/tripple_A)');
+is( digest_data('SHA3_224', "A","A","A"), pack("H*","c09d5af7d9a021c484041218f3c3787fd4274b64ffd012edca0fe55b"), 'sha3_224 (digest_data_raw/tripple_A)');
+is( digest_data_hex('SHA3_224', "A","A","A"), "c09d5af7d9a021c484041218f3c3787fd4274b64ffd012edca0fe55b", 'sha3_224 (digest_data_hex/tripple_A)');
+is( digest_data_b64('SHA3_224', "A","A","A"), "wJ1a99mgIcSEBBIY88N4f9QnS2T/0BLtyg/lWw==", 'sha3_224 (digest_data_b64/tripple_A)');
+is( digest_data_b64u('SHA3_224', "A","A","A"), "wJ1a99mgIcSEBBIY88N4f9QnS2T_0BLtyg_lWw", 'sha3_224 (digest_data_b64u/tripple_A)');
+is( Crypt::Digest::SHA3_224->new->add("A","A","A")->hexdigest, "c09d5af7d9a021c484041218f3c3787fd4274b64ffd012edca0fe55b", 'sha3_224 (OO/tripple_A)');
+is( Crypt::Digest::SHA3_224->new->add("A")->add("A")->add("A")->hexdigest, "c09d5af7d9a021c484041218f3c3787fd4274b64ffd012edca0fe55b", 'sha3_224 (OO3/tripple_A)');
+
is( sha3_224(""), pack("H*","6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7"), 'sha3_224 (raw/1)');
is( sha3_224_hex(""), "6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7", 'sha3_224 (hex/1)');
diff --git a/t/digest_sha3_256.t b/t/digest_sha3_256.t
index 6c813bdc..bbb25d47 100644
--- a/t/digest_sha3_256.t
+++ b/t/digest_sha3_256.t
@@ -3,7 +3,7 @@
use strict;
use warnings;
-use Test::More tests => 8*3 + 9*4 + 6;
+use Test::More tests => 8*3 + 9*4 + 10 + 6;
use Crypt::Digest qw( digest_data digest_data_hex digest_data_b64 digest_data_b64u digest_file digest_file_hex digest_file_b64 digest_file_b64u );
use Crypt::Digest::SHA3_256 qw( sha3_256 sha3_256_hex sha3_256_b64 sha3_256_b64u sha3_256_file sha3_256_file_hex sha3_256_file_b64 sha3_256_file_b64u );
@@ -15,6 +15,17 @@ is( Crypt::Digest::SHA3_256->hashsize, 32, 'hashsize/4');
is( Crypt::Digest->new('SHA3_256')->hashsize, 32, 'hashsize/5');
is( Crypt::Digest::SHA3_256->new->hashsize, 32, 'hashsize/6');
+is( sha3_256("A","A","A"), pack("H*","7dcb827a1f5a7cbea423e763a7dd0c7824e3512c7f1ce48cd5710f603b4f1efa"), 'sha3_256 (raw/tripple_A)');
+is( sha3_256_hex("A","A","A"), "7dcb827a1f5a7cbea423e763a7dd0c7824e3512c7f1ce48cd5710f603b4f1efa", 'sha3_256 (hex/tripple_A)');
+is( sha3_256_b64("A","A","A"), "fcuCeh9afL6kI+djp90MeCTjUSx/HOSM1XEPYDtPHvo=", 'sha3_256 (base64/tripple_A)');
+is( sha3_256_b64u("A","A","A"), "fcuCeh9afL6kI-djp90MeCTjUSx_HOSM1XEPYDtPHvo", 'sha3_256 (base64url/tripple_A)');
+is( digest_data('SHA3_256', "A","A","A"), pack("H*","7dcb827a1f5a7cbea423e763a7dd0c7824e3512c7f1ce48cd5710f603b4f1efa"), 'sha3_256 (digest_data_raw/tripple_A)');
+is( digest_data_hex('SHA3_256', "A","A","A"), "7dcb827a1f5a7cbea423e763a7dd0c7824e3512c7f1ce48cd5710f603b4f1efa", 'sha3_256 (digest_data_hex/tripple_A)');
+is( digest_data_b64('SHA3_256', "A","A","A"), "fcuCeh9afL6kI+djp90MeCTjUSx/HOSM1XEPYDtPHvo=", 'sha3_256 (digest_data_b64/tripple_A)');
+is( digest_data_b64u('SHA3_256', "A","A","A"), "fcuCeh9afL6kI-djp90MeCTjUSx_HOSM1XEPYDtPHvo", 'sha3_256 (digest_data_b64u/tripple_A)');
+is( Crypt::Digest::SHA3_256->new->add("A","A","A")->hexdigest, "7dcb827a1f5a7cbea423e763a7dd0c7824e3512c7f1ce48cd5710f603b4f1efa", 'sha3_256 (OO/tripple_A)');
+is( Crypt::Digest::SHA3_256->new->add("A")->add("A")->add("A")->hexdigest, "7dcb827a1f5a7cbea423e763a7dd0c7824e3512c7f1ce48cd5710f603b4f1efa", 'sha3_256 (OO3/tripple_A)');
+
is( sha3_256(""), pack("H*","a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a"), 'sha3_256 (raw/1)');
is( sha3_256_hex(""), "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a", 'sha3_256 (hex/1)');
diff --git a/t/digest_sha3_384.t b/t/digest_sha3_384.t
index dadc964c..91784b72 100644
--- a/t/digest_sha3_384.t
+++ b/t/digest_sha3_384.t
@@ -3,7 +3,7 @@
use strict;
use warnings;
-use Test::More tests => 8*3 + 9*4 + 6;
+use Test::More tests => 8*3 + 9*4 + 10 + 6;
use Crypt::Digest qw( digest_data digest_data_hex digest_data_b64 digest_data_b64u digest_file digest_file_hex digest_file_b64 digest_file_b64u );
use Crypt::Digest::SHA3_384 qw( sha3_384 sha3_384_hex sha3_384_b64 sha3_384_b64u sha3_384_file sha3_384_file_hex sha3_384_file_b64 sha3_384_file_b64u );
@@ -15,6 +15,17 @@ is( Crypt::Digest::SHA3_384->hashsize, 48, 'hashsize/4');
is( Crypt::Digest->new('SHA3_384')->hashsize, 48, 'hashsize/5');
is( Crypt::Digest::SHA3_384->new->hashsize, 48, 'hashsize/6');
+is( sha3_384("A","A","A"), pack("H*","3555ed8a634b235fb07a691e1934b3e81228c859bc1c17acdebb4bab82cd63f06e17caed585533b4615bc6e3fb2e0bc4"), 'sha3_384 (raw/tripple_A)');
+is( sha3_384_hex("A","A","A"), "3555ed8a634b235fb07a691e1934b3e81228c859bc1c17acdebb4bab82cd63f06e17caed585533b4615bc6e3fb2e0bc4", 'sha3_384 (hex/tripple_A)');
+is( sha3_384_b64("A","A","A"), "NVXtimNLI1+wemkeGTSz6BIoyFm8HBes3rtLq4LNY/BuF8rtWFUztGFbxuP7LgvE", 'sha3_384 (base64/tripple_A)');
+is( sha3_384_b64u("A","A","A"), "NVXtimNLI1-wemkeGTSz6BIoyFm8HBes3rtLq4LNY_BuF8rtWFUztGFbxuP7LgvE", 'sha3_384 (base64url/tripple_A)');
+is( digest_data('SHA3_384', "A","A","A"), pack("H*","3555ed8a634b235fb07a691e1934b3e81228c859bc1c17acdebb4bab82cd63f06e17caed585533b4615bc6e3fb2e0bc4"), 'sha3_384 (digest_data_raw/tripple_A)');
+is( digest_data_hex('SHA3_384', "A","A","A"), "3555ed8a634b235fb07a691e1934b3e81228c859bc1c17acdebb4bab82cd63f06e17caed585533b4615bc6e3fb2e0bc4", 'sha3_384 (digest_data_hex/tripple_A)');
+is( digest_data_b64('SHA3_384', "A","A","A"), "NVXtimNLI1+wemkeGTSz6BIoyFm8HBes3rtLq4LNY/BuF8rtWFUztGFbxuP7LgvE", 'sha3_384 (digest_data_b64/tripple_A)');
+is( digest_data_b64u('SHA3_384', "A","A","A"), "NVXtimNLI1-wemkeGTSz6BIoyFm8HBes3rtLq4LNY_BuF8rtWFUztGFbxuP7LgvE", 'sha3_384 (digest_data_b64u/tripple_A)');
+is( Crypt::Digest::SHA3_384->new->add("A","A","A")->hexdigest, "3555ed8a634b235fb07a691e1934b3e81228c859bc1c17acdebb4bab82cd63f06e17caed585533b4615bc6e3fb2e0bc4", 'sha3_384 (OO/tripple_A)');
+is( Crypt::Digest::SHA3_384->new->add("A")->add("A")->add("A")->hexdigest, "3555ed8a634b235fb07a691e1934b3e81228c859bc1c17acdebb4bab82cd63f06e17caed585533b4615bc6e3fb2e0bc4", 'sha3_384 (OO3/tripple_A)');
+
is( sha3_384(""), pack("H*","0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004"), 'sha3_384 (raw/1)');
is( sha3_384_hex(""), "0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004", 'sha3_384 (hex/1)');
diff --git a/t/digest_sha3_512.t b/t/digest_sha3_512.t
index f8ab9aaa..5dbf5c64 100644
--- a/t/digest_sha3_512.t
+++ b/t/digest_sha3_512.t
@@ -3,7 +3,7 @@
use strict;
use warnings;
-use Test::More tests => 8*3 + 9*4 + 6;
+use Test::More tests => 8*3 + 9*4 + 10 + 6;
use Crypt::Digest qw( digest_data digest_data_hex digest_data_b64 digest_data_b64u digest_file digest_file_hex digest_file_b64 digest_file_b64u );
use Crypt::Digest::SHA3_512 qw( sha3_512 sha3_512_hex sha3_512_b64 sha3_512_b64u sha3_512_file sha3_512_file_hex sha3_512_file_b64 sha3_512_file_b64u );
@@ -15,6 +15,17 @@ is( Crypt::Digest::SHA3_512->hashsize, 64, 'hashsize/4');
is( Crypt::Digest->new('SHA3_512')->hashsize, 64, 'hashsize/5');
is( Crypt::Digest::SHA3_512->new->hashsize, 64, 'hashsize/6');
+is( sha3_512("A","A","A"), pack("H*","852cf44eb8d38715c847976b6de526564136d756fa99b4ad5a825fd6e3ba5d891c7b4576b11410a6e951fffa3399b14be1da4222d53b5a35ff236d659899e857"), 'sha3_512 (raw/tripple_A)');
+is( sha3_512_hex("A","A","A"), "852cf44eb8d38715c847976b6de526564136d756fa99b4ad5a825fd6e3ba5d891c7b4576b11410a6e951fffa3399b14be1da4222d53b5a35ff236d659899e857", 'sha3_512 (hex/tripple_A)');
+is( sha3_512_b64("A","A","A"), "hSz0TrjThxXIR5drbeUmVkE211b6mbStWoJf1uO6XYkce0V2sRQQpulR//ozmbFL4dpCItU7WjX/I21lmJnoVw==", 'sha3_512 (base64/tripple_A)');
+is( sha3_512_b64u("A","A","A"), "hSz0TrjThxXIR5drbeUmVkE211b6mbStWoJf1uO6XYkce0V2sRQQpulR__ozmbFL4dpCItU7WjX_I21lmJnoVw", 'sha3_512 (base64url/tripple_A)');
+is( digest_data('SHA3_512', "A","A","A"), pack("H*","852cf44eb8d38715c847976b6de526564136d756fa99b4ad5a825fd6e3ba5d891c7b4576b11410a6e951fffa3399b14be1da4222d53b5a35ff236d659899e857"), 'sha3_512 (digest_data_raw/tripple_A)');
+is( digest_data_hex('SHA3_512', "A","A","A"), "852cf44eb8d38715c847976b6de526564136d756fa99b4ad5a825fd6e3ba5d891c7b4576b11410a6e951fffa3399b14be1da4222d53b5a35ff236d659899e857", 'sha3_512 (digest_data_hex/tripple_A)');
+is( digest_data_b64('SHA3_512', "A","A","A"), "hSz0TrjThxXIR5drbeUmVkE211b6mbStWoJf1uO6XYkce0V2sRQQpulR//ozmbFL4dpCItU7WjX/I21lmJnoVw==", 'sha3_512 (digest_data_b64/tripple_A)');
+is( digest_data_b64u('SHA3_512', "A","A","A"), "hSz0TrjThxXIR5drbeUmVkE211b6mbStWoJf1uO6XYkce0V2sRQQpulR__ozmbFL4dpCItU7WjX_I21lmJnoVw", 'sha3_512 (digest_data_b64u/tripple_A)');
+is( Crypt::Digest::SHA3_512->new->add("A","A","A")->hexdigest, "852cf44eb8d38715c847976b6de526564136d756fa99b4ad5a825fd6e3ba5d891c7b4576b11410a6e951fffa3399b14be1da4222d53b5a35ff236d659899e857", 'sha3_512 (OO/tripple_A)');
+is( Crypt::Digest::SHA3_512->new->add("A")->add("A")->add("A")->hexdigest, "852cf44eb8d38715c847976b6de526564136d756fa99b4ad5a825fd6e3ba5d891c7b4576b11410a6e951fffa3399b14be1da4222d53b5a35ff236d659899e857", 'sha3_512 (OO3/tripple_A)');
+
is( sha3_512(""), pack("H*","a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26"), 'sha3_512 (raw/1)');
is( sha3_512_hex(""), "a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26", 'sha3_512 (hex/1)');
diff --git a/t/digest_sha512.t b/t/digest_sha512.t
index 15ce8b12..2af4c6b4 100644
--- a/t/digest_sha512.t
+++ b/t/digest_sha512.t
@@ -3,7 +3,7 @@
use strict;
use warnings;
-use Test::More tests => 8*3 + 9*4 + 6;
+use Test::More tests => 8*3 + 9*4 + 10 + 6;
use Crypt::Digest qw( digest_data digest_data_hex digest_data_b64 digest_data_b64u digest_file digest_file_hex digest_file_b64 digest_file_b64u );
use Crypt::Digest::SHA512 qw( sha512 sha512_hex sha512_b64 sha512_b64u sha512_file sha512_file_hex sha512_file_b64 sha512_file_b64u );
@@ -15,6 +15,17 @@ is( Crypt::Digest::SHA512->hashsize, 64, 'hashsize/4');
is( Crypt::Digest->new('SHA512')->hashsize, 64, 'hashsize/5');
is( Crypt::Digest::SHA512->new->hashsize, 64, 'hashsize/6');
+is( sha512("A","A","A"), pack("H*","8d708d18b54df3962d696f069ad42dad7762b5d4d3c97ee5fa2dae0673ed46545164c078b8db3d59c4b96020e4316f17bb3d91bf1f6bc0896bbe75416eb8c385"), 'sha512 (raw/tripple_A)');
+is( sha512_hex("A","A","A"), "8d708d18b54df3962d696f069ad42dad7762b5d4d3c97ee5fa2dae0673ed46545164c078b8db3d59c4b96020e4316f17bb3d91bf1f6bc0896bbe75416eb8c385", 'sha512 (hex/tripple_A)');
+is( sha512_b64("A","A","A"), "jXCNGLVN85YtaW8GmtQtrXditdTTyX7l+i2uBnPtRlRRZMB4uNs9WcS5YCDkMW8Xuz2Rvx9rwIlrvnVBbrjDhQ==", 'sha512 (base64/tripple_A)');
+is( sha512_b64u("A","A","A"), "jXCNGLVN85YtaW8GmtQtrXditdTTyX7l-i2uBnPtRlRRZMB4uNs9WcS5YCDkMW8Xuz2Rvx9rwIlrvnVBbrjDhQ", 'sha512 (base64url/tripple_A)');
+is( digest_data('SHA512', "A","A","A"), pack("H*","8d708d18b54df3962d696f069ad42dad7762b5d4d3c97ee5fa2dae0673ed46545164c078b8db3d59c4b96020e4316f17bb3d91bf1f6bc0896bbe75416eb8c385"), 'sha512 (digest_data_raw/tripple_A)');
+is( digest_data_hex('SHA512', "A","A","A"), "8d708d18b54df3962d696f069ad42dad7762b5d4d3c97ee5fa2dae0673ed46545164c078b8db3d59c4b96020e4316f17bb3d91bf1f6bc0896bbe75416eb8c385", 'sha512 (digest_data_hex/tripple_A)');
+is( digest_data_b64('SHA512', "A","A","A"), "jXCNGLVN85YtaW8GmtQtrXditdTTyX7l+i2uBnPtRlRRZMB4uNs9WcS5YCDkMW8Xuz2Rvx9rwIlrvnVBbrjDhQ==", 'sha512 (digest_data_b64/tripple_A)');
+is( digest_data_b64u('SHA512', "A","A","A"), "jXCNGLVN85YtaW8GmtQtrXditdTTyX7l-i2uBnPtRlRRZMB4uNs9WcS5YCDkMW8Xuz2Rvx9rwIlrvnVBbrjDhQ", 'sha512 (digest_data_b64u/tripple_A)');
+is( Crypt::Digest::SHA512->new->add("A","A","A")->hexdigest, "8d708d18b54df3962d696f069ad42dad7762b5d4d3c97ee5fa2dae0673ed46545164c078b8db3d59c4b96020e4316f17bb3d91bf1f6bc0896bbe75416eb8c385", 'sha512 (OO/tripple_A)');
+is( Crypt::Digest::SHA512->new->add("A")->add("A")->add("A")->hexdigest, "8d708d18b54df3962d696f069ad42dad7762b5d4d3c97ee5fa2dae0673ed46545164c078b8db3d59c4b96020e4316f17bb3d91bf1f6bc0896bbe75416eb8c385", 'sha512 (OO3/tripple_A)');
+
is( sha512(""), pack("H*","cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"), 'sha512 (raw/1)');
is( sha512_hex(""), "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e", 'sha512 (hex/1)');
diff --git a/t/digest_sha512_224.t b/t/digest_sha512_224.t
index dc2033d8..ad19e438 100644
--- a/t/digest_sha512_224.t
+++ b/t/digest_sha512_224.t
@@ -3,7 +3,7 @@
use strict;
use warnings;
-use Test::More tests => 8*3 + 9*4 + 6;
+use Test::More tests => 8*3 + 9*4 + 10 + 6;
use Crypt::Digest qw( digest_data digest_data_hex digest_data_b64 digest_data_b64u digest_file digest_file_hex digest_file_b64 digest_file_b64u );
use Crypt::Digest::SHA512_224 qw( sha512_224 sha512_224_hex sha512_224_b64 sha512_224_b64u sha512_224_file sha512_224_file_hex sha512_224_file_b64 sha512_224_file_b64u );
@@ -15,6 +15,17 @@ is( Crypt::Digest::SHA512_224->hashsize, 28, 'hashsize/4');
is( Crypt::Digest->new('SHA512_224')->hashsize, 28, 'hashsize/5');
is( Crypt::Digest::SHA512_224->new->hashsize, 28, 'hashsize/6');
+is( sha512_224("A","A","A"), pack("H*","3d5a0b742f4c61d315c6ce86457a9fa30903880d30558c68ce4713b3"), 'sha512_224 (raw/tripple_A)');
+is( sha512_224_hex("A","A","A"), "3d5a0b742f4c61d315c6ce86457a9fa30903880d30558c68ce4713b3", 'sha512_224 (hex/tripple_A)');
+is( sha512_224_b64("A","A","A"), "PVoLdC9MYdMVxs6GRXqfowkDiA0wVYxozkcTsw==", 'sha512_224 (base64/tripple_A)');
+is( sha512_224_b64u("A","A","A"), "PVoLdC9MYdMVxs6GRXqfowkDiA0wVYxozkcTsw", 'sha512_224 (base64url/tripple_A)');
+is( digest_data('SHA512_224', "A","A","A"), pack("H*","3d5a0b742f4c61d315c6ce86457a9fa30903880d30558c68ce4713b3"), 'sha512_224 (digest_data_raw/tripple_A)');
+is( digest_data_hex('SHA512_224', "A","A","A"), "3d5a0b742f4c61d315c6ce86457a9fa30903880d30558c68ce4713b3", 'sha512_224 (digest_data_hex/tripple_A)');
+is( digest_data_b64('SHA512_224', "A","A","A"), "PVoLdC9MYdMVxs6GRXqfowkDiA0wVYxozkcTsw==", 'sha512_224 (digest_data_b64/tripple_A)');
+is( digest_data_b64u('SHA512_224', "A","A","A"), "PVoLdC9MYdMVxs6GRXqfowkDiA0wVYxozkcTsw", 'sha512_224 (digest_data_b64u/tripple_A)');
+is( Crypt::Digest::SHA512_224->new->add("A","A","A")->hexdigest, "3d5a0b742f4c61d315c6ce86457a9fa30903880d30558c68ce4713b3", 'sha512_224 (OO/tripple_A)');
+is( Crypt::Digest::SHA512_224->new->add("A")->add("A")->add("A")->hexdigest, "3d5a0b742f4c61d315c6ce86457a9fa30903880d30558c68ce4713b3", 'sha512_224 (OO3/tripple_A)');
+
is( sha512_224(""), pack("H*","6ed0dd02806fa89e25de060c19d3ac86cabb87d6a0ddd05c333b84f4"), 'sha512_224 (raw/1)');
is( sha512_224_hex(""), "6ed0dd02806fa89e25de060c19d3ac86cabb87d6a0ddd05c333b84f4", 'sha512_224 (hex/1)');
diff --git a/t/digest_sha512_256.t b/t/digest_sha512_256.t
index d5412c2e..147918ce 100644
--- a/t/digest_sha512_256.t
+++ b/t/digest_sha512_256.t
@@ -3,7 +3,7 @@
use strict;
use warnings;
-use Test::More tests => 8*3 + 9*4 + 6;
+use Test::More tests => 8*3 + 9*4 + 10 + 6;
use Crypt::Digest qw( digest_data digest_data_hex digest_data_b64 digest_data_b64u digest_file digest_file_hex digest_file_b64 digest_file_b64u );
use Crypt::Digest::SHA512_256 qw( sha512_256 sha512_256_hex sha512_256_b64 sha512_256_b64u sha512_256_file sha512_256_file_hex sha512_256_file_b64 sha512_256_file_b64u );
@@ -15,6 +15,17 @@ is( Crypt::Digest::SHA512_256->hashsize, 32, 'hashsize/4');
is( Crypt::Digest->new('SHA512_256')->hashsize, 32, 'hashsize/5');
is( Crypt::Digest::SHA512_256->new->hashsize, 32, 'hashsize/6');
+is( sha512_256("A","A","A"), pack("H*","b28a62969d8b9b02297ba615c485be2dffef907ca419c2a494004026d6c4bdf4"), 'sha512_256 (raw/tripple_A)');
+is( sha512_256_hex("A","A","A"), "b28a62969d8b9b02297ba615c485be2dffef907ca419c2a494004026d6c4bdf4", 'sha512_256 (hex/tripple_A)');
+is( sha512_256_b64("A","A","A"), "sopilp2LmwIpe6YVxIW+Lf/vkHykGcKklABAJtbEvfQ=", 'sha512_256 (base64/tripple_A)');
+is( sha512_256_b64u("A","A","A"), "sopilp2LmwIpe6YVxIW-Lf_vkHykGcKklABAJtbEvfQ", 'sha512_256 (base64url/tripple_A)');
+is( digest_data('SHA512_256', "A","A","A"), pack("H*","b28a62969d8b9b02297ba615c485be2dffef907ca419c2a494004026d6c4bdf4"), 'sha512_256 (digest_data_raw/tripple_A)');
+is( digest_data_hex('SHA512_256', "A","A","A"), "b28a62969d8b9b02297ba615c485be2dffef907ca419c2a494004026d6c4bdf4", 'sha512_256 (digest_data_hex/tripple_A)');
+is( digest_data_b64('SHA512_256', "A","A","A"), "sopilp2LmwIpe6YVxIW+Lf/vkHykGcKklABAJtbEvfQ=", 'sha512_256 (digest_data_b64/tripple_A)');
+is( digest_data_b64u('SHA512_256', "A","A","A"), "sopilp2LmwIpe6YVxIW-Lf_vkHykGcKklABAJtbEvfQ", 'sha512_256 (digest_data_b64u/tripple_A)');
+is( Crypt::Digest::SHA512_256->new->add("A","A","A")->hexdigest, "b28a62969d8b9b02297ba615c485be2dffef907ca419c2a494004026d6c4bdf4", 'sha512_256 (OO/tripple_A)');
+is( Crypt::Digest::SHA512_256->new->add("A")->add("A")->add("A")->hexdigest, "b28a62969d8b9b02297ba615c485be2dffef907ca419c2a494004026d6c4bdf4", 'sha512_256 (OO3/tripple_A)');
+
is( sha512_256(""), pack("H*","c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a"), 'sha512_256 (raw/1)');
is( sha512_256_hex(""), "c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a", 'sha512_256 (hex/1)');
diff --git a/t/digest_tiger192.t b/t/digest_tiger192.t
index 8f0cf7f0..9e14403c 100644
--- a/t/digest_tiger192.t
+++ b/t/digest_tiger192.t
@@ -3,7 +3,7 @@
use strict;
use warnings;
-use Test::More tests => 8*3 + 9*4 + 6;
+use Test::More tests => 8*3 + 9*4 + 10 + 6;
use Crypt::Digest qw( digest_data digest_data_hex digest_data_b64 digest_data_b64u digest_file digest_file_hex digest_file_b64 digest_file_b64u );
use Crypt::Digest::Tiger192 qw( tiger192 tiger192_hex tiger192_b64 tiger192_b64u tiger192_file tiger192_file_hex tiger192_file_b64 tiger192_file_b64u );
@@ -15,6 +15,17 @@ is( Crypt::Digest::Tiger192->hashsize, 24, 'hashsize/4');
is( Crypt::Digest->new('Tiger192')->hashsize, 24, 'hashsize/5');
is( Crypt::Digest::Tiger192->new->hashsize, 24, 'hashsize/6');
+is( tiger192("A","A","A"), pack("H*","04682253acc4e609201422ad50ad6be2c51cf1698b0a41c9"), 'tiger192 (raw/tripple_A)');
+is( tiger192_hex("A","A","A"), "04682253acc4e609201422ad50ad6be2c51cf1698b0a41c9", 'tiger192 (hex/tripple_A)');
+is( tiger192_b64("A","A","A"), "BGgiU6zE5gkgFCKtUK1r4sUc8WmLCkHJ", 'tiger192 (base64/tripple_A)');
+is( tiger192_b64u("A","A","A"), "BGgiU6zE5gkgFCKtUK1r4sUc8WmLCkHJ", 'tiger192 (base64url/tripple_A)');
+is( digest_data('Tiger192', "A","A","A"), pack("H*","04682253acc4e609201422ad50ad6be2c51cf1698b0a41c9"), 'tiger192 (digest_data_raw/tripple_A)');
+is( digest_data_hex('Tiger192', "A","A","A"), "04682253acc4e609201422ad50ad6be2c51cf1698b0a41c9", 'tiger192 (digest_data_hex/tripple_A)');
+is( digest_data_b64('Tiger192', "A","A","A"), "BGgiU6zE5gkgFCKtUK1r4sUc8WmLCkHJ", 'tiger192 (digest_data_b64/tripple_A)');
+is( digest_data_b64u('Tiger192', "A","A","A"), "BGgiU6zE5gkgFCKtUK1r4sUc8WmLCkHJ", 'tiger192 (digest_data_b64u/tripple_A)');
+is( Crypt::Digest::Tiger192->new->add("A","A","A")->hexdigest, "04682253acc4e609201422ad50ad6be2c51cf1698b0a41c9", 'tiger192 (OO/tripple_A)');
+is( Crypt::Digest::Tiger192->new->add("A")->add("A")->add("A")->hexdigest, "04682253acc4e609201422ad50ad6be2c51cf1698b0a41c9", 'tiger192 (OO3/tripple_A)');
+
is( tiger192(""), pack("H*","3293ac630c13f0245f92bbb1766e16167a4e58492dde73f3"), 'tiger192 (raw/1)');
is( tiger192_hex(""), "3293ac630c13f0245f92bbb1766e16167a4e58492dde73f3", 'tiger192 (hex/1)');
diff --git a/t/digest_whirlpool.t b/t/digest_whirlpool.t
index 4eb7b6f3..16a1a3dd 100644
--- a/t/digest_whirlpool.t
+++ b/t/digest_whirlpool.t
@@ -3,7 +3,7 @@
use strict;
use warnings;
-use Test::More tests => 8*3 + 9*4 + 6;
+use Test::More tests => 8*3 + 9*4 + 10 + 6;
use Crypt::Digest qw( digest_data digest_data_hex digest_data_b64 digest_data_b64u digest_file digest_file_hex digest_file_b64 digest_file_b64u );
use Crypt::Digest::Whirlpool qw( whirlpool whirlpool_hex whirlpool_b64 whirlpool_b64u whirlpool_file whirlpool_file_hex whirlpool_file_b64 whirlpool_file_b64u );
@@ -15,6 +15,17 @@ is( Crypt::Digest::Whirlpool->hashsize, 64, 'hashsize/4');
is( Crypt::Digest->new('Whirlpool')->hashsize, 64, 'hashsize/5');
is( Crypt::Digest::Whirlpool->new->hashsize, 64, 'hashsize/6');
+is( whirlpool("A","A","A"), pack("H*","a4dea38c743f318db7169e28ac27aff173942b67b56f9881da464bdac48f47cc481ee29746557cf013d1c54c7a76912c1380b168251df7118293511fd89a9a64"), 'whirlpool (raw/tripple_A)');
+is( whirlpool_hex("A","A","A"), "a4dea38c743f318db7169e28ac27aff173942b67b56f9881da464bdac48f47cc481ee29746557cf013d1c54c7a76912c1380b168251df7118293511fd89a9a64", 'whirlpool (hex/tripple_A)');
+is( whirlpool_b64("A","A","A"), "pN6jjHQ/MY23Fp4orCev8XOUK2e1b5iB2kZL2sSPR8xIHuKXRlV88BPRxUx6dpEsE4CxaCUd9xGCk1Ef2JqaZA==", 'whirlpool (base64/tripple_A)');
+is( whirlpool_b64u("A","A","A"), "pN6jjHQ_MY23Fp4orCev8XOUK2e1b5iB2kZL2sSPR8xIHuKXRlV88BPRxUx6dpEsE4CxaCUd9xGCk1Ef2JqaZA", 'whirlpool (base64url/tripple_A)');
+is( digest_data('Whirlpool', "A","A","A"), pack("H*","a4dea38c743f318db7169e28ac27aff173942b67b56f9881da464bdac48f47cc481ee29746557cf013d1c54c7a76912c1380b168251df7118293511fd89a9a64"), 'whirlpool (digest_data_raw/tripple_A)');
+is( digest_data_hex('Whirlpool', "A","A","A"), "a4dea38c743f318db7169e28ac27aff173942b67b56f9881da464bdac48f47cc481ee29746557cf013d1c54c7a76912c1380b168251df7118293511fd89a9a64", 'whirlpool (digest_data_hex/tripple_A)');
+is( digest_data_b64('Whirlpool', "A","A","A"), "pN6jjHQ/MY23Fp4orCev8XOUK2e1b5iB2kZL2sSPR8xIHuKXRlV88BPRxUx6dpEsE4CxaCUd9xGCk1Ef2JqaZA==", 'whirlpool (digest_data_b64/tripple_A)');
+is( digest_data_b64u('Whirlpool', "A","A","A"), "pN6jjHQ_MY23Fp4orCev8XOUK2e1b5iB2kZL2sSPR8xIHuKXRlV88BPRxUx6dpEsE4CxaCUd9xGCk1Ef2JqaZA", 'whirlpool (digest_data_b64u/tripple_A)');
+is( Crypt::Digest::Whirlpool->new->add("A","A","A")->hexdigest, "a4dea38c743f318db7169e28ac27aff173942b67b56f9881da464bdac48f47cc481ee29746557cf013d1c54c7a76912c1380b168251df7118293511fd89a9a64", 'whirlpool (OO/tripple_A)');
+is( Crypt::Digest::Whirlpool->new->add("A")->add("A")->add("A")->hexdigest, "a4dea38c743f318db7169e28ac27aff173942b67b56f9881da464bdac48f47cc481ee29746557cf013d1c54c7a76912c1380b168251df7118293511fd89a9a64", 'whirlpool (OO3/tripple_A)');
+
is( whirlpool(""), pack("H*","19fa61d75522a4669b44e39c1d2e1726c530232130d407f89afee0964997f7a73e83be698b288febcf88e3e03c4f0757ea8964e59b63d93708b138cc42a66eb3"), 'whirlpool (raw/1)');
is( whirlpool_hex(""), "19fa61d75522a4669b44e39c1d2e1726c530232130d407f89afee0964997f7a73e83be698b288febcf88e3e03c4f0757ea8964e59b63d93708b138cc42a66eb3", 'whirlpool (hex/1)');
diff --git a/t/jwk.t b/t/jwk.t
index 11e4c36f..14385203 100644
--- a/t/jwk.t
+++ b/t/jwk.t
@@ -147,7 +147,7 @@ my $EC1 = {
curve_cofactor => 1,
curve_Gx => "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296",
curve_Gy => "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
- curve_name => "secp256r1",
+ curve_oid => "1.2.840.10045.3.1.7",
curve_order => "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
curve_prime => "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
k => "F3BD0C07A81FB932781ED52752F60CC89A6BE5E51934FE01938DDB55D8F77801",
@@ -167,7 +167,7 @@ my $EC2 = {
curve_cofactor => 1,
curve_Gx => "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296",
curve_Gy => "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
- curve_name => "secp256r1",
+ curve_oid => "1.2.840.10045.3.1.7",
curve_order => "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
curve_prime => "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
k => "",
@@ -183,7 +183,7 @@ my $EC2 = {
is($kh->{pub_x}, $EC1->{pub_x}, "EC x test HASH1");
is($kh->{pub_y}, $EC1->{pub_y}, "EC y test HASH1");
is($kh->{k}, $EC1->{k}, "EC k test HASH1");
- is($kh->{curve_name}, "secp256r1", "EC curve test HASH1");
+ is($kh->{curve_oid}, "1.2.840.10045.3.1.7", "EC curve test HASH1");
ok($ec->is_private, "EC private test HASH1");
my $jwk = $ec->export_key_jwk('private');
my $jwkp = $ec->export_key_jwk('public');
@@ -205,7 +205,7 @@ my $EC2 = {
is($kh->{pub_x}, $EC1->{pub_x}, "EC x test JWK1");
is($kh->{pub_y}, $EC1->{pub_y}, "EC y test JWK1");
is($kh->{k}, $EC1->{k}, "EC k test JWK1");
- is($kh->{curve_name}, "secp256r1", "EC curve test JWK1");
+ is($kh->{curve_oid}, "1.2.840.10045.3.1.7", "EC curve test JWK1");
ok($ec->is_private, "EC private test JWK1");
$jwk_tp = $ec->export_key_jwk_thumbprint('SHA256');
is($jwk_tp, $ec1_jwk_thumbprint_sha256, 'export_key_jwk_thumbprint(SHA256)');
@@ -215,7 +215,7 @@ my $EC2 = {
is($kh->{pub_x}, $EC1->{pub_x}, "EC x test JWK2");
is($kh->{pub_y}, $EC1->{pub_y}, "EC y test JWK2");
is($kh->{k}, "", "EC k test JWK2");
- is($kh->{curve_name}, "secp256r1", "EC curve test JWK2");
+ is($kh->{curve_oid}, "1.2.840.10045.3.1.7", "EC curve test JWK2");
ok(!$ec->is_private, "EC !private test JWK2");
$jwk_tp = $ec->export_key_jwk_thumbprint('SHA256');
is($jwk_tp, $ec1_jwk_thumbprint_sha256, 'export_key_jwk_thumbprint(SHA256)');
@@ -227,7 +227,7 @@ my $EC2 = {
is($kh->{pub_x}, $EC1->{pub_x}, "EC x test HASH2");
is($kh->{pub_y}, $EC1->{pub_y}, "EC y test HASH2");
is($kh->{k}, "", "EC k test HASH2");
- is($kh->{curve_name}, "secp256r1", "EC curve test HASH2");
+ is($kh->{curve_oid}, "1.2.840.10045.3.1.7", "EC curve test HASH2");
ok(!$ec->is_private, "EC private test HASH2");
}
diff --git a/t/mac_blake2b.t b/t/mac_blake2b.t
index 0e275a90..b04b8aef 100644
--- a/t/mac_blake2b.t
+++ b/t/mac_blake2b.t
@@ -3,7 +3,7 @@
use strict;
use warnings;
-use Test::More tests => 36;
+use Test::More tests => 36 + 8;
use Crypt::Mac::BLAKE2b qw( blake2b blake2b_hex blake2b_b64 blake2b_b64u );
@@ -43,3 +43,12 @@ is( unpack('H*', blake2b(32,'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',"test\0test\0test
is( blake2b_hex(32,'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',"test\0test\0test\n"), 'dc29010f123a4cd59c91da5fc494375962502ca2179021ebca2f6dd41befa8d2', 'BLAKE2b/func+hex/6');
is( blake2b_b64(32,'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',"test\0test\0test\n"), '3CkBDxI6TNWckdpfxJQ3WWJQLKIXkCHryi9t1BvvqNI=', 'BLAKE2b/func+b64/6');
is( blake2b_b64u(32,'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',"test\0test\0test\n"), '3CkBDxI6TNWckdpfxJQ3WWJQLKIXkCHryi9t1BvvqNI', 'BLAKE2b/func+b64u/6');
+
+is( unpack('H*', Crypt::Mac::BLAKE2b->new(32, '12345678901234561234567890123456')->add("A","A","A")->mac), '794a20cc22c1f9f278aa1219ded10105cc9cfd264e66a327f32fbc309b2d404f', 'BLAKE2b/oo+raw/tripple_A');
+is( unpack('H*', Crypt::Mac::BLAKE2b->new(32, '12345678901234561234567890123456')->add("A")->add("A")->add("A")->mac), '794a20cc22c1f9f278aa1219ded10105cc9cfd264e66a327f32fbc309b2d404f', 'BLAKE2b/oo3+raw/tripple_A');
+is( Crypt::Mac::BLAKE2b->new(32, '12345678901234561234567890123456')->add("A","A","A")->hexmac, '794a20cc22c1f9f278aa1219ded10105cc9cfd264e66a327f32fbc309b2d404f', 'BLAKE2b/oo+hex/tripple_A');
+is( Crypt::Mac::BLAKE2b->new(32, '12345678901234561234567890123456')->add("A")->add("A")->add("A")->hexmac, '794a20cc22c1f9f278aa1219ded10105cc9cfd264e66a327f32fbc309b2d404f', 'BLAKE2b/oo3+hex/tripple_A');
+is( unpack('H*', blake2b(32, '12345678901234561234567890123456',"A","A","A")), '794a20cc22c1f9f278aa1219ded10105cc9cfd264e66a327f32fbc309b2d404f', 'BLAKE2b/func+raw/tripple_A');
+is( blake2b_hex (32, '12345678901234561234567890123456',"A","A","A"), '794a20cc22c1f9f278aa1219ded10105cc9cfd264e66a327f32fbc309b2d404f', 'BLAKE2b/func+hex/tripple_A');
+is( blake2b_b64 (32, '12345678901234561234567890123456',"A","A","A"), 'eUogzCLB+fJ4qhIZ3tEBBcyc/SZOZqMn8y+8MJstQE8=', 'BLAKE2b/func+b64/tripple_A');
+is( blake2b_b64u(32, '12345678901234561234567890123456',"A","A","A"), 'eUogzCLB-fJ4qhIZ3tEBBcyc_SZOZqMn8y-8MJstQE8', 'BLAKE2b/func+b64u/tripple_A');
diff --git a/t/mac_blake2s.t b/t/mac_blake2s.t
index 5698556c..179ea9b9 100644
--- a/t/mac_blake2s.t
+++ b/t/mac_blake2s.t
@@ -3,7 +3,7 @@
use strict;
use warnings;
-use Test::More tests => 36;
+use Test::More tests => 36 + 8;
use Crypt::Mac::BLAKE2s qw( blake2s blake2s_hex blake2s_b64 blake2s_b64u );
@@ -43,3 +43,12 @@ is( unpack('H*', blake2s(32,'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',"test\0test\0test
is( blake2s_hex(32,'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',"test\0test\0test\n"), 'a31f0e2ba5e73a3aab7e14503690515662758279075d7b68512709824923e65c', 'BLAKE2s/func+hex/6');
is( blake2s_b64(32,'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',"test\0test\0test\n"), 'ox8OK6XnOjqrfhRQNpBRVmJ1gnkHXXtoUScJgkkj5lw=', 'BLAKE2s/func+b64/6');
is( blake2s_b64u(32,'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',"test\0test\0test\n"), 'ox8OK6XnOjqrfhRQNpBRVmJ1gnkHXXtoUScJgkkj5lw', 'BLAKE2s/func+b64u/6');
+
+is( unpack('H*', Crypt::Mac::BLAKE2s->new(32, '12345678901234561234567890123456')->add("A","A","A")->mac), '8acd7813fe7251676d1cf2817c09a25840fa9a1df7143536448a5dfdf7365725', 'BLAKE2s/oo+raw/tripple_A');
+is( unpack('H*', Crypt::Mac::BLAKE2s->new(32, '12345678901234561234567890123456')->add("A")->add("A")->add("A")->mac), '8acd7813fe7251676d1cf2817c09a25840fa9a1df7143536448a5dfdf7365725', 'BLAKE2s/oo3+raw/tripple_A');
+is( Crypt::Mac::BLAKE2s->new(32, '12345678901234561234567890123456')->add("A","A","A")->hexmac, '8acd7813fe7251676d1cf2817c09a25840fa9a1df7143536448a5dfdf7365725', 'BLAKE2s/oo+hex/tripple_A');
+is( Crypt::Mac::BLAKE2s->new(32, '12345678901234561234567890123456')->add("A")->add("A")->add("A")->hexmac, '8acd7813fe7251676d1cf2817c09a25840fa9a1df7143536448a5dfdf7365725', 'BLAKE2s/oo3+hex/tripple_A');
+is( unpack('H*', blake2s(32, '12345678901234561234567890123456',"A","A","A")), '8acd7813fe7251676d1cf2817c09a25840fa9a1df7143536448a5dfdf7365725', 'BLAKE2s/func+raw/tripple_A');
+is( blake2s_hex (32, '12345678901234561234567890123456',"A","A","A"), '8acd7813fe7251676d1cf2817c09a25840fa9a1df7143536448a5dfdf7365725', 'BLAKE2s/func+hex/tripple_A');
+is( blake2s_b64 (32, '12345678901234561234567890123456',"A","A","A"), 'is14E/5yUWdtHPKBfAmiWED6mh33FDU2RIpd/fc2VyU=', 'BLAKE2s/func+b64/tripple_A');
+is( blake2s_b64u(32, '12345678901234561234567890123456',"A","A","A"), 'is14E_5yUWdtHPKBfAmiWED6mh33FDU2RIpd_fc2VyU', 'BLAKE2s/func+b64u/tripple_A');
diff --git a/t/mac_f9.t b/t/mac_f9.t
index 374468ca..73011dd7 100644
--- a/t/mac_f9.t
+++ b/t/mac_f9.t
@@ -3,7 +3,7 @@
use strict;
use warnings;
-use Test::More tests => 72;
+use Test::More tests => 72 + 8;
use Crypt::Mac::F9 qw( f9 f9_hex f9_b64 f9_b64u );
@@ -79,3 +79,12 @@ is( unpack('H*', f9('Blowfish','12345678901234561234567890123456',"test\0test\0t
is( f9_hex('Blowfish','12345678901234561234567890123456',"test\0test\0test\n"), 'fa83d84023c43a81', 'F9/func+hex/12');
is( f9_b64('Blowfish','12345678901234561234567890123456',"test\0test\0test\n"), '+oPYQCPEOoE=', 'F9/func+b64/12');
is( f9_b64u('Blowfish','12345678901234561234567890123456',"test\0test\0test\n"), '-oPYQCPEOoE', 'F9/func+b64u/12');
+
+is( unpack('H*', Crypt::Mac::F9->new('AES', '1234567890123456')->add("A","A","A")->mac), 'a30e9e0ee8cd9d7401f9a9967e82b5a1', 'F9/oo+raw/tripple_A');
+is( unpack('H*', Crypt::Mac::F9->new('AES', '1234567890123456')->add("A")->add("A")->add("A")->mac), 'a30e9e0ee8cd9d7401f9a9967e82b5a1', 'F9/oo3+raw/tripple_A');
+is( Crypt::Mac::F9->new('AES', '1234567890123456')->add("A","A","A")->hexmac, 'a30e9e0ee8cd9d7401f9a9967e82b5a1', 'F9/oo+hex/tripple_A');
+is( Crypt::Mac::F9->new('AES', '1234567890123456')->add("A")->add("A")->add("A")->hexmac, 'a30e9e0ee8cd9d7401f9a9967e82b5a1', 'F9/oo3+hex/tripple_A');
+is( unpack('H*', f9('AES', '1234567890123456',"A","A","A")), 'a30e9e0ee8cd9d7401f9a9967e82b5a1', 'F9/func+raw/tripple_A');
+is( f9_hex ('AES', '1234567890123456',"A","A","A"), 'a30e9e0ee8cd9d7401f9a9967e82b5a1', 'F9/func+hex/tripple_A');
+is( f9_b64 ('AES', '1234567890123456',"A","A","A"), 'ow6eDujNnXQB+amWfoK1oQ==', 'F9/func+b64/tripple_A');
+is( f9_b64u('AES', '1234567890123456',"A","A","A"), 'ow6eDujNnXQB-amWfoK1oQ', 'F9/func+b64u/tripple_A');
diff --git a/t/mac_hmac.t b/t/mac_hmac.t
index f7b4def3..404d1fc3 100644
--- a/t/mac_hmac.t
+++ b/t/mac_hmac.t
@@ -3,7 +3,7 @@
use strict;
use warnings;
-use Test::More tests => 72;
+use Test::More tests => 72 + 8;
use Crypt::Mac::HMAC qw( hmac hmac_hex hmac_b64 hmac_b64u );
@@ -79,3 +79,12 @@ is( unpack('H*', hmac('Whirlpool','secretkey',"test\0test\0test\n")), 'dab6a22e0
is( hmac_hex('Whirlpool','secretkey',"test\0test\0test\n"), 'dab6a22e05b46ce641e022e6ea2b42646a25b994ed15fed09145e3906d159efba37b899c344f589b3ad5868cd631a8eb304d21dedf47e364c791ccfa665681f7', 'HMAC/func+hex/12');
is( hmac_b64('Whirlpool','secretkey',"test\0test\0test\n"), '2raiLgW0bOZB4CLm6itCZGoluZTtFf7QkUXjkG0Vnvuje4mcNE9YmzrVhozWMajrME0h3t9H42THkcz6ZlaB9w==', 'HMAC/func+b64/12');
is( hmac_b64u('Whirlpool','secretkey',"test\0test\0test\n"), '2raiLgW0bOZB4CLm6itCZGoluZTtFf7QkUXjkG0Vnvuje4mcNE9YmzrVhozWMajrME0h3t9H42THkcz6ZlaB9w', 'HMAC/func+b64u/12');
+
+is( unpack('H*', Crypt::Mac::HMAC->new('SHA1', 'secretkey')->add("A","A","A")->mac), '99070fd56a6595bbb458747d63808344fed0b9c1', 'HMAC/oo+raw/tripple_A');
+is( unpack('H*', Crypt::Mac::HMAC->new('SHA1', 'secretkey')->add("A")->add("A")->add("A")->mac), '99070fd56a6595bbb458747d63808344fed0b9c1', 'HMAC/oo3+raw/tripple_A');
+is( Crypt::Mac::HMAC->new('SHA1', 'secretkey')->add("A","A","A")->hexmac, '99070fd56a6595bbb458747d63808344fed0b9c1', 'HMAC/oo+hex/tripple_A');
+is( Crypt::Mac::HMAC->new('SHA1', 'secretkey')->add("A")->add("A")->add("A")->hexmac, '99070fd56a6595bbb458747d63808344fed0b9c1', 'HMAC/oo3+hex/tripple_A');
+is( unpack('H*', hmac('SHA1', 'secretkey',"A","A","A")), '99070fd56a6595bbb458747d63808344fed0b9c1', 'HMAC/func+raw/tripple_A');
+is( hmac_hex ('SHA1', 'secretkey',"A","A","A"), '99070fd56a6595bbb458747d63808344fed0b9c1', 'HMAC/func+hex/tripple_A');
+is( hmac_b64 ('SHA1', 'secretkey',"A","A","A"), 'mQcP1Wpllbu0WHR9Y4CDRP7QucE=', 'HMAC/func+b64/tripple_A');
+is( hmac_b64u('SHA1', 'secretkey',"A","A","A"), 'mQcP1Wpllbu0WHR9Y4CDRP7QucE', 'HMAC/func+b64u/tripple_A');
diff --git a/t/mac_omac.t b/t/mac_omac.t
index 6f84bc80..ea8ae320 100644
--- a/t/mac_omac.t
+++ b/t/mac_omac.t
@@ -3,7 +3,7 @@
use strict;
use warnings;
-use Test::More tests => 72;
+use Test::More tests => 72 + 8;
use Crypt::Mac::OMAC qw( omac omac_hex omac_b64 omac_b64u );
@@ -79,3 +79,12 @@ is( unpack('H*', omac('Blowfish','12345678901234561234567890123456',"test\0test\
is( omac_hex('Blowfish','12345678901234561234567890123456',"test\0test\0test\n"), '40e6d018b49ada77', 'OMAC/func+hex/12');
is( omac_b64('Blowfish','12345678901234561234567890123456',"test\0test\0test\n"), 'QObQGLSa2nc=', 'OMAC/func+b64/12');
is( omac_b64u('Blowfish','12345678901234561234567890123456',"test\0test\0test\n"), 'QObQGLSa2nc', 'OMAC/func+b64u/12');
+
+is( unpack('H*', Crypt::Mac::OMAC->new('AES', '1234567890123456')->add("A","A","A")->mac), '49b745733f380fb4cdd8ce1ff1e52abc', 'OMAC/oo+raw/tripple_A');
+is( unpack('H*', Crypt::Mac::OMAC->new('AES', '1234567890123456')->add("A")->add("A")->add("A")->mac), '49b745733f380fb4cdd8ce1ff1e52abc', 'OMAC/oo3+raw/tripple_A');
+is( Crypt::Mac::OMAC->new('AES', '1234567890123456')->add("A","A","A")->hexmac, '49b745733f380fb4cdd8ce1ff1e52abc', 'OMAC/oo+hex/tripple_A');
+is( Crypt::Mac::OMAC->new('AES', '1234567890123456')->add("A")->add("A")->add("A")->hexmac, '49b745733f380fb4cdd8ce1ff1e52abc', 'OMAC/oo3+hex/tripple_A');
+is( unpack('H*', omac('AES', '1234567890123456',"A","A","A")), '49b745733f380fb4cdd8ce1ff1e52abc', 'OMAC/func+raw/tripple_A');
+is( omac_hex ('AES', '1234567890123456',"A","A","A"), '49b745733f380fb4cdd8ce1ff1e52abc', 'OMAC/func+hex/tripple_A');
+is( omac_b64 ('AES', '1234567890123456',"A","A","A"), 'SbdFcz84D7TN2M4f8eUqvA==', 'OMAC/func+b64/tripple_A');
+is( omac_b64u('AES', '1234567890123456',"A","A","A"), 'SbdFcz84D7TN2M4f8eUqvA', 'OMAC/func+b64u/tripple_A');
diff --git a/t/mac_pelican.t b/t/mac_pelican.t
index b46815fc..1ece329f 100644
--- a/t/mac_pelican.t
+++ b/t/mac_pelican.t
@@ -3,7 +3,7 @@
use strict;
use warnings;
-use Test::More tests => 72;
+use Test::More tests => 72 + 8;
use Crypt::Mac::Pelican qw( pelican pelican_hex pelican_b64 pelican_b64u );
@@ -79,3 +79,12 @@ is( unpack('H*', pelican('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',"test\0test\0test\n"
is( pelican_hex('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',"test\0test\0test\n"), '8a798fcb2181d9f9ed81fcd2a7f6cd4e', 'Pelican/func+hex/12');
is( pelican_b64('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',"test\0test\0test\n"), 'inmPyyGB2fntgfzSp/bNTg==', 'Pelican/func+b64/12');
is( pelican_b64u('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',"test\0test\0test\n"), 'inmPyyGB2fntgfzSp_bNTg', 'Pelican/func+b64u/12');
+
+is( unpack('H*', Crypt::Mac::Pelican->new('1234567890123456')->add("A","A","A")->mac), '6f7dda998b3fdfeaa80737e5127532a5', 'Pelican/oo+raw/tripple_A');
+is( unpack('H*', Crypt::Mac::Pelican->new('1234567890123456')->add("A")->add("A")->add("A")->mac), '6f7dda998b3fdfeaa80737e5127532a5', 'Pelican/oo3+raw/tripple_A');
+is( Crypt::Mac::Pelican->new('1234567890123456')->add("A","A","A")->hexmac, '6f7dda998b3fdfeaa80737e5127532a5', 'Pelican/oo+hex/tripple_A');
+is( Crypt::Mac::Pelican->new('1234567890123456')->add("A")->add("A")->add("A")->hexmac, '6f7dda998b3fdfeaa80737e5127532a5', 'Pelican/oo3+hex/tripple_A');
+is( unpack('H*', pelican('1234567890123456',"A","A","A")), '6f7dda998b3fdfeaa80737e5127532a5', 'Pelican/func+raw/tripple_A');
+is( pelican_hex ('1234567890123456',"A","A","A"), '6f7dda998b3fdfeaa80737e5127532a5', 'Pelican/func+hex/tripple_A');
+is( pelican_b64 ('1234567890123456',"A","A","A"), 'b33amYs/3+qoBzflEnUypQ==', 'Pelican/func+b64/tripple_A');
+is( pelican_b64u('1234567890123456',"A","A","A"), 'b33amYs_3-qoBzflEnUypQ', 'Pelican/func+b64u/tripple_A');
diff --git a/t/mac_pmac.t b/t/mac_pmac.t
index 19bec12c..6ca6e539 100644
--- a/t/mac_pmac.t
+++ b/t/mac_pmac.t
@@ -3,7 +3,7 @@
use strict;
use warnings;
-use Test::More tests => 72;
+use Test::More tests => 72 + 8;
use Crypt::Mac::PMAC qw( pmac pmac_hex pmac_b64 pmac_b64u );
@@ -79,3 +79,12 @@ is( unpack('H*', pmac('Blowfish','12345678901234561234567890123456',"test\0test\
is( pmac_hex('Blowfish','12345678901234561234567890123456',"test\0test\0test\n"), '3797cde072a8e286', 'PMAC/func+hex/12');
is( pmac_b64('Blowfish','12345678901234561234567890123456',"test\0test\0test\n"), 'N5fN4HKo4oY=', 'PMAC/func+b64/12');
is( pmac_b64u('Blowfish','12345678901234561234567890123456',"test\0test\0test\n"), 'N5fN4HKo4oY', 'PMAC/func+b64u/12');
+
+is( unpack('H*', Crypt::Mac::PMAC->new('AES', '1234567890123456')->add("A","A","A")->mac), 'c46c52ff026e4e24837bc51a7e21f8cb', 'PMAC/oo+raw/tripple_A');
+is( unpack('H*', Crypt::Mac::PMAC->new('AES', '1234567890123456')->add("A")->add("A")->add("A")->mac), 'c46c52ff026e4e24837bc51a7e21f8cb', 'PMAC/oo3+raw/tripple_A');
+is( Crypt::Mac::PMAC->new('AES', '1234567890123456')->add("A","A","A")->hexmac, 'c46c52ff026e4e24837bc51a7e21f8cb', 'PMAC/oo+hex/tripple_A');
+is( Crypt::Mac::PMAC->new('AES', '1234567890123456')->add("A")->add("A")->add("A")->hexmac, 'c46c52ff026e4e24837bc51a7e21f8cb', 'PMAC/oo3+hex/tripple_A');
+is( unpack('H*', pmac('AES', '1234567890123456',"A","A","A")), 'c46c52ff026e4e24837bc51a7e21f8cb', 'PMAC/func+raw/tripple_A');
+is( pmac_hex ('AES', '1234567890123456',"A","A","A"), 'c46c52ff026e4e24837bc51a7e21f8cb', 'PMAC/func+hex/tripple_A');
+is( pmac_b64 ('AES', '1234567890123456',"A","A","A"), 'xGxS/wJuTiSDe8UafiH4yw==', 'PMAC/func+b64/tripple_A');
+is( pmac_b64u('AES', '1234567890123456',"A","A","A"), 'xGxS_wJuTiSDe8UafiH4yw', 'PMAC/func+b64u/tripple_A');
diff --git a/t/mac_poly1305.t b/t/mac_poly1305.t
index ed29f56c..2f0036fe 100644
--- a/t/mac_poly1305.t
+++ b/t/mac_poly1305.t
@@ -3,7 +3,7 @@
use strict;
use warnings;
-use Test::More tests => 36;
+use Test::More tests => 36 + 8;
use Crypt::Mac::Poly1305 qw( poly1305 poly1305_hex poly1305_b64 poly1305_b64u );
@@ -43,3 +43,12 @@ is( unpack('H*', poly1305('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',"test\0test\0test\n
is( poly1305_hex('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',"test\0test\0test\n"), '4c02cea60201d83ae4b2d644789422e5', 'Poly1305/func+hex/6');
is( poly1305_b64('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',"test\0test\0test\n"), 'TALOpgIB2DrkstZEeJQi5Q==', 'Poly1305/func+b64/6');
is( poly1305_b64u('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',"test\0test\0test\n"), 'TALOpgIB2DrkstZEeJQi5Q', 'Poly1305/func+b64u/6');
+
+is( unpack('H*', Crypt::Mac::Poly1305->new('12345678901234561234567890123456')->add("A","A","A")->mac), '7c1e6c34ad72384ac4f52eb49f642abc', 'Poly1305/oo+raw/tripple_A');
+is( unpack('H*', Crypt::Mac::Poly1305->new('12345678901234561234567890123456')->add("A")->add("A")->add("A")->mac), '7c1e6c34ad72384ac4f52eb49f642abc', 'Poly1305/oo3+raw/tripple_A');
+is( Crypt::Mac::Poly1305->new('12345678901234561234567890123456')->add("A","A","A")->hexmac, '7c1e6c34ad72384ac4f52eb49f642abc', 'Poly1305/oo+hex/tripple_A');
+is( Crypt::Mac::Poly1305->new('12345678901234561234567890123456')->add("A")->add("A")->add("A")->hexmac, '7c1e6c34ad72384ac4f52eb49f642abc', 'Poly1305/oo3+hex/tripple_A');
+is( unpack('H*', poly1305('12345678901234561234567890123456',"A","A","A")), '7c1e6c34ad72384ac4f52eb49f642abc', 'Poly1305/func+raw/tripple_A');
+is( poly1305_hex ('12345678901234561234567890123456',"A","A","A"), '7c1e6c34ad72384ac4f52eb49f642abc', 'Poly1305/func+hex/tripple_A');
+is( poly1305_b64 ('12345678901234561234567890123456',"A","A","A"), 'fB5sNK1yOErE9S60n2QqvA==', 'Poly1305/func+b64/tripple_A');
+is( poly1305_b64u('12345678901234561234567890123456',"A","A","A"), 'fB5sNK1yOErE9S60n2QqvA', 'Poly1305/func+b64u/tripple_A');
diff --git a/t/mac_xcbc.t b/t/mac_xcbc.t
index 50686c42..b756356d 100644
--- a/t/mac_xcbc.t
+++ b/t/mac_xcbc.t
@@ -3,7 +3,7 @@
use strict;
use warnings;
-use Test::More tests => 72;
+use Test::More tests => 72 + 8;
use Crypt::Mac::XCBC qw( xcbc xcbc_hex xcbc_b64 xcbc_b64u );
@@ -79,3 +79,12 @@ is( unpack('H*', xcbc('Blowfish','12345678901234561234567890123456',"test\0test\
is( xcbc_hex('Blowfish','12345678901234561234567890123456',"test\0test\0test\n"), '98276a4a6aafd86b', 'XCBC/func+hex/12');
is( xcbc_b64('Blowfish','12345678901234561234567890123456',"test\0test\0test\n"), 'mCdqSmqv2Gs=', 'XCBC/func+b64/12');
is( xcbc_b64u('Blowfish','12345678901234561234567890123456',"test\0test\0test\n"), 'mCdqSmqv2Gs', 'XCBC/func+b64u/12');
+
+is( unpack('H*', Crypt::Mac::XCBC->new('AES', '1234567890123456')->add("A","A","A")->mac), 'da243c0a133fc33cd1f96b872c0bec9b', 'XCBC/oo+raw/tripple_A');
+is( unpack('H*', Crypt::Mac::XCBC->new('AES', '1234567890123456')->add("A")->add("A")->add("A")->mac), 'da243c0a133fc33cd1f96b872c0bec9b', 'XCBC/oo3+raw/tripple_A');
+is( Crypt::Mac::XCBC->new('AES', '1234567890123456')->add("A","A","A")->hexmac, 'da243c0a133fc33cd1f96b872c0bec9b', 'XCBC/oo+hex/tripple_A');
+is( Crypt::Mac::XCBC->new('AES', '1234567890123456')->add("A")->add("A")->add("A")->hexmac, 'da243c0a133fc33cd1f96b872c0bec9b', 'XCBC/oo3+hex/tripple_A');
+is( unpack('H*', xcbc('AES', '1234567890123456',"A","A","A")), 'da243c0a133fc33cd1f96b872c0bec9b', 'XCBC/func+raw/tripple_A');
+is( xcbc_hex ('AES', '1234567890123456',"A","A","A"), 'da243c0a133fc33cd1f96b872c0bec9b', 'XCBC/func+hex/tripple_A');
+is( xcbc_b64 ('AES', '1234567890123456',"A","A","A"), '2iQ8ChM/wzzR+WuHLAvsmw==', 'XCBC/func+b64/tripple_A');
+is( xcbc_b64u('AES', '1234567890123456',"A","A","A"), '2iQ8ChM_wzzR-WuHLAvsmw', 'XCBC/func+b64u/tripple_A');
diff --git a/t/mode_ctr.t b/t/mode_ctr.t
index 623894aa..ebe2128a 100644
--- a/t/mode_ctr.t
+++ b/t/mode_ctr.t
@@ -1,6 +1,6 @@
use strict;
use warnings;
-use Test::More tests => 8;
+use Test::More tests => 24;
use Crypt::Mode::CTR;
@@ -15,10 +15,28 @@ sub do_test {
my $pt = pack("H*", $a{pt});
my $key = pack("H*", $a{key});
my $iv = pack("H*", $a{iv});
+ # test: encrypt/decrypt in a single step
my $ct_out = Crypt::Mode::CTR->new('AES', $a{mode}, $a{width})->encrypt($pt, $key, $iv);
- is(unpack("H*", $ct_out), $a{ct}, "cipher text [m=$a{mode}, w=$a{width}]");
+ is(unpack("H*", $ct_out), $a{ct}, "cipher text1 [m=$a{mode}, w=$a{width}]");
my $pt_out = Crypt::Mode::CTR->new('AES', $a{mode}, $a{width})->decrypt($ct_out, $key, $iv);
- is(unpack("H*", $pt_out), $a{pt}, "plain text [m=$a{mode}, w=$a{width}]");
+ is(unpack("H*", $pt_out), $a{pt}, "plain text1 [m=$a{mode}, w=$a{width}]");
+ # test: add(@in)
+ my $mode;
+ my @in = map { pack("H*", $_) } ($a{pt} =~ /(..)/g);
+ $mode = Crypt::Mode::CTR->new('AES', $a{mode}, $a{width})->start_encrypt($key, $iv);
+ $ct_out = $mode->add(@in) . $mode->finish;
+ is(unpack("H*", $ct_out), $a{ct}, "cipher text2 [m=$a{mode}, w=$a{width}]");
+ $mode = Crypt::Mode::CTR->new('AES', $a{mode}, $a{width})->start_encrypt($key, $iv);
+ $ct_out = join ('', map { $mode->add($_) } @in) . $mode->finish;
+ is(unpack("H*", $ct_out), $a{ct}, "cipher text3 [m=$a{mode}, w=$a{width}]");
+ # test: add(?)->add(?)->add(?)->add(?)
+ @in = split //, $ct_out;
+ $mode = Crypt::Mode::CTR->new('AES', $a{mode}, $a{width})->start_decrypt($key, $iv);
+ $pt_out = $mode->add(@in) . $mode->finish;
+ is(unpack("H*", $pt_out), $a{pt}, "plain text2 [m=$a{mode}, w=$a{width}]");
+ $mode = Crypt::Mode::CTR->new('AES', $a{mode}, $a{width})->start_decrypt($key, $iv);
+ $pt_out = join ('', map { $mode->add($_) } @in) . $mode->finish;
+ is(unpack("H*", $pt_out), $a{pt}, "plain text3 [m=$a{mode}, w=$a{width}]");
}
do_test(%$_) for (
diff --git a/t/pk_dsa.t b/t/pk_dsa.t
index 6926022b..3fb7f697 100644
--- a/t/pk_dsa.t
+++ b/t/pk_dsa.t
@@ -75,9 +75,9 @@ use Crypt::Misc 'decode_b64';
ok($pu1->verify_message($sig, "message"), 'verify_message');
my $hash = pack("H*","04624fae618e9ad0c5e479f62e1420c71fff34dd");
- $sig = $pr1->sign_hash($hash, 'SHA1');
+ $sig = $pr1->sign_hash($hash);
ok(length $sig > 60, 'sign_hash ' . length($sig));
- ok($pu1->verify_hash($sig, $hash, 'SHA1'), 'verify_hash');
+ ok($pu1->verify_hash($sig, $hash), 'verify_hash');
my $pr2 = Crypt::PK::DSA->new;
$pr2->import_key('t/data/cryptx_priv_dsa2.der');
@@ -195,7 +195,7 @@ MARKER
ok($sig, 'dsa_sign_message');
ok(dsa_verify_message('t/data/cryptx_pub_dsa1.der', $sig, 'test string'), 'dsa_verify_message');
my $hash = pack("H*","04624fae618e9ad0c5e479f62e1420c71fff34dd");
- $sig = dsa_sign_hash('t/data/cryptx_priv_dsa1.der', $hash, 'SHA1');
+ $sig = dsa_sign_hash('t/data/cryptx_priv_dsa1.der', $hash);
ok($sig, 'dsa_sign_hash');
- ok(dsa_verify_hash('t/data/cryptx_pub_dsa1.der', $sig, $hash, 'SHA1'), 'dsa_verify_hash');
+ ok(dsa_verify_hash('t/data/cryptx_pub_dsa1.der', $sig, $hash), 'dsa_verify_hash');
}
diff --git a/t/pk_ecc.t b/t/pk_ecc.t
index e247f5cc..7d7b9fcd 100644
--- a/t/pk_ecc.t
+++ b/t/pk_ecc.t
@@ -179,16 +179,24 @@ for my $pub (qw/openssl_ec-short.pub.pem openssl_ec-short.pub.der/) {
ok($@, 'key not generated');
# known curves lookup
- my $params = $Crypt::PK::ECC::curve{secp384r1};
+ my $params = { # NIST P-384
+ prime => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF",
+ A => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC",
+ B => "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF",
+ Gx => "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7",
+ Gy => "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F",
+ order => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973",
+ cofactor => 1,
+ };
$k = Crypt::PK::ECC->new;
ok($k->generate_key($params), "generate_key hash params");
is($k->key2hash->{curve_name}, 'secp384r1', "key2hash curve_name");
- is($k->key2hash->{curve_oid}, $params->{oid}, "key2hash curve_oid");
+ is($k->key2hash->{curve_oid}, '1.3.132.0.34', "key2hash curve_oid");
ok($k->export_key_der('private_short'), "export_key_der auto oid");
$k = Crypt::PK::ECC->new;
- ok($k->generate_key({ %$params, A => '0' }), "generate_key invalid auto oid");
- is($k->key2hash->{curve_name}, 'custom', "key2hash custom curve_name");
+ ok($k->generate_key({ %$params, cofactor => 6 }), "generate_key invalid auto oid");
+ ok(!exists($k->key2hash->{curve_name}) || $k->key2hash->{curve_name} eq 'custom', "key2hash custom curve_name");
ok(!exists($k->key2hash->{curve_oid}), "key2hash curve_oid doesn't exist");
eval { $k->export_key_der('private_short'); };
ok($@, "export_key_der invalid auto oid");
diff --git a/t/pkcs8.t b/t/pkcs8.t
index 96eaef3d..feb1a869 100644
--- a/t/pkcs8.t
+++ b/t/pkcs8.t
@@ -1,6 +1,6 @@
use strict;
use warnings;
-use Test::More tests => 8;
+use Test::More tests => 12;
use Crypt::PK::RSA;
use Crypt::PK::ECC;
@@ -38,7 +38,7 @@ for my $f (qw/pkcs8.rsa-priv-nopass.pem pkcs8.rsa-priv-nopass.der/) {
### XXX-FIXME password protected pkcs8 private keys are not supported
### for my $f (qw/pkcs8.rsa-priv-pass.der pkcs8.rsa-priv-pass.pem/) {
-### $rsa->import_key("t/data/$f");
+### $rsa->import_key("t/data/$f", "secret");
### ok($rsa->is_private, "RSA is_private $f");
### }
@@ -47,8 +47,7 @@ for my $f (qw/pkcs8.ec-short-priv-nopass.der pkcs8.ec-short-priv-nopass.pem pkcs
ok($ec->is_private, "ECC is_private $f");
}
-### XXX-FIXME password protected pkcs8 private keys are not supported
-### for my $f (qw/pkcs8.ec-priv-pass.der pkcs8.ec-priv-pass.pem pkcs8.ec-short-priv-pass.der pkcs8.ec-short-priv-pass.pem/) {
-### $ec->import_key("t/data/$f");
-### ok($ec->is_private, "ECC is_private $f");
-### }
+for my $f (qw/pkcs8.ec-priv-pass.der pkcs8.ec-priv-pass.pem pkcs8.ec-short-priv-pass.der pkcs8.ec-short-priv-pass.pem/) {
+ $ec->import_key("t/data/$f", "secret");
+ ok($ec->is_private, "ECC is_private $f (pw)");
+}
diff --git a/t/wycheproof.t b/t/wycheproof.t
index fa2217e3..608e8482 100644
--- a/t/wycheproof.t
+++ b/t/wycheproof.t
@@ -7,7 +7,7 @@ use warnings;
use Test::More;
plan skip_all => "No JSON::* module installed" unless eval { require JSON::PP } || eval { require JSON::XS } || eval { require Cpanel::JSON::XS };
-plan tests => 762;
+plan tests => 1298;
use CryptX;
use Crypt::Misc 'read_rawfile';
@@ -117,9 +117,9 @@ if (1) {
# do the test
my $testname = "type=$type/$sha tcId=$tcId comment='$comment' expected-result=$result";
my $pk = Crypt::PK::DSA->new( \$keyPem );
- my $valid = $pk->verify_message($sig, $message, $sha);
my $hash = digest_data($sha, $message);
my $valid_h = $pk->verify_hash($sig, $hash);
+ my $valid = $pk->verify_message($sig, $message, $sha);
if ($result eq 'valid' || $result eq 'acceptable') {
ok($valid, $testname);
}
@@ -133,13 +133,7 @@ if (1) {
}
}
-if (0) {
- #XXX-TODO:
- # not ok 749 - type=ECDSAVer/SHA256 tcId=50 comment='appending unused 0's' expected-result=invalid verify_message=1
- # not ok 819 - type=ECDSAVer/SHA256 tcId=120 comment='Modified r or s, e.g. by adding or subtracting the order of the group' expected-result=invalid verify_message=1
- # not ok 820 - type=ECDSAVer/SHA256 tcId=121 comment='Modified r or s, e.g. by adding or subtracting the order of the group' expected-result=invalid verify_message=1
- # not ok 821 - type=ECDSAVer/SHA256 tcId=122 comment='Modified r or s, e.g. by adding or subtracting the order of the group' expected-result=invalid verify_message=1
-
+if (1) {
use Crypt::PK::ECC;
my $tests = CryptX::_decode_json read_rawfile 't/wycheproof/ecdsa_test.json';
@@ -157,17 +151,21 @@ if (0) {
my $result = $t->{result};
my $message = pack "H*", $t->{message};
my $sig = pack "H*", $t->{sig};
+ # skip unsupported tests:
+ next if $tcId==9 && $result eq 'acceptable' && $comment eq "BER:long form encoding of length";
+ next if $tcId==10 && $result eq 'acceptable' && $comment eq "BER:long form encoding of length";
+ next if $tcId==12 && $result eq 'acceptable' && $comment eq "BER:length contains leading 0";
+ next if $tcId==13 && $result eq 'acceptable' && $comment eq "BER:length contains leading 0";
+ next if $tcId==14 && $result eq 'acceptable' && $comment eq "BER:indefinite length";
+ next if $tcId==15 && $result eq 'acceptable' && $comment eq "BER:prepending 0's to integer";
+ next if $tcId==16 && $result eq 'acceptable' && $comment eq "BER:prepending 0's to integer";
# do the test
my $testname = "type=$type/$sha tcId=$tcId comment='$comment' expected-result=$result";
my $pk = Crypt::PK::ECC->new( \$keyPem );
my $valid = $pk->verify_message($sig, $message, $sha);
- if ($result eq 'valid') {
+ if ($result eq 'valid' || $result eq 'acceptable') {
ok($valid, "$testname verify_message=$valid");
}
- elsif ($result eq 'acceptable') {
- #XXX-TODO
- #ok($valid, "$testname verify_message=$valid");
- }
elsif ($result eq 'invalid') {
ok(!$valid, "$testname verify_message=$valid");
}
@@ -178,7 +176,7 @@ if (0) {
}
}
-if (0) {
+if (1) {
use Crypt::PK::ECC;
my $tests = CryptX::_decode_json read_rawfile 't/wycheproof/ecdsa_webcrypto_test.json';
@@ -201,14 +199,10 @@ if (0) {
# do the test
my $testname = "type=$type/$sha tcId=$tcId comment='$comment' expected-result=$result";
my $pk = Crypt::PK::ECC->new( \$keyPem );
- my $valid = $pk->verify_message($sig, $message, $sha);
- if ($result eq 'valid') {
+ my $valid = $pk->verify_message_rfc7518($sig, $message, $sha);
+ if ($result eq 'valid' || $result eq 'acceptable') {
ok($valid, "$testname verify_message=$valid");
}
- elsif ($result eq 'acceptable') {
- #XXX-TODO
- #ok($valid, "$testname verify_message=$valid");
- }
elsif ($result eq 'invalid') {
ok(!$valid, "$testname verify_message=$valid");
}